Get worklogs from emails

This commit is contained in:
Daniel O'Connell 2019-10-07 22:28:07 +02:00
parent b67a6138a0
commit c7c0dc92d7
5 changed files with 85 additions and 17 deletions

View File

@ -6,6 +6,8 @@
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/tools.cli "0.4.2"]
[com.draines/postal "2.0.3"]
[io.forward/clojure-mail "1.0.8"]
[commons-net "3.6"]
[clj-http "3.10.0"]
[cheshire "5.9.0"]
[clj-pdf "2.4.0"]]

View File

@ -1,30 +1,18 @@
(ns invoices.core
(:require [invoices.pdf :as pdf]
[invoices.settings :refer [invoices]]
[invoices.jira :refer [prev-timesheet]]
[invoices.timesheets :refer [prev-timesheet]]
[invoices.time :refer [prev-month last-working-day date-applies?]]
[invoices.calc :refer [set-price]]
[invoices.email :refer [send-email]]
[clojure.tools.cli :refer [parse-opts]]
[clojure.string :as str]
[clojure.java.shell :refer [sh]]
[postal.core :refer [send-message]])
[clojure.java.shell :refer [sh]])
(:gen-class))
(defn invoice-number [when number]
(->> [(or number 1) (-> when .getMonthValue) (-> when .getYear)] (map str) (str/join "/")))
(defn send-email [to from {smtp :smtp} invoice]
(when (not-any? nil? [to from smtp invoice])
(->>
(send-message smtp {:from from
:to [to]
:subject invoice
:body [{:type :attachment
:content (java.io.File. (str invoice ".pdf"))
:content-type "application/pdf"}]})
:error (= :SUCCESS)
(println " - email sent: "))))
(defn run-callback [file callback]
(let [command (concat callback [file])
str-command (str/join " " command)

74
src/invoices/email.clj Normal file
View File

@ -0,0 +1,74 @@
(ns invoices.email
(:require [clojure.string :as str]
[invoices.time :as time]
[postal.core :refer [send-message]]
[clojure-mail.core :as mail]
[clojure-mail.gmail :as gmail]
[clojure-mail.folder :as folder]
[clojure-mail.message :refer (read-message) :as mess]))
(defn send-email [to from {smtp :smtp} invoice]
(when (not-any? nil? [to from smtp invoice])
(->>
(send-message smtp {:from from
:to [to]
:subject invoice
:body [{:type :attachment
:content (java.io.File. (str invoice ".pdf"))
:content-type "application/pdf"}]})
:error (= :SUCCESS)
(println " - email sent: "))))
(defn server-find-messages
"Find all messages in the given folder, filtering them by subject and sender (use nil to ignore)."
[client folder subject from]
(->>
{:subject subject :from from}
(remove (comp nil? second))
flatten
(apply folder/search (mail/open-folder client folder :readonly))
(into [])))
(defn manual-find-messages
"Find all messages in the given folder, filtering them by subject and sender (use nil to ignore).
WARNING: This can be very slow, as it fetches each message seperately.
"
[client folder subject from]
(let [subjecter (if subject #(str/includes? (mess/subject %) subject) identity)
fromer (if from #(str/includes? (-> % mess/from first :address) from) identity)]
(filter
#(and (subjecter %) (fromer %))
(mail/all-messages client folder))))
(defn find-messages
"Get all messages for the given month from the given imap server."
[month
{imap :host user :user password :pass try-manual :try-manual folder :folder from :from subject :subject}]
(let [client (mail/store "imaps" imap user password)
subject (time/format-month subject month)
messages (server-find-messages client folder subject from)]
(if (and (empty? messages) try-manual)
(manual-find-messages client folder subject from)
messages)))
(defn split-cells [content]
(->> content
str/split-lines
(remove str/blank?)
(map #(str/split % #"[\s;]"))))
(defn zip-item [headers cell]
(into (sorted-map) (map vector headers cell)))
(defn extract-items [headers message]
(->> message
mess/get-content
split-cells
(map (partial zip-item headers))))
(defn get-worklogs
"Get all worklogs for the given month from the given imap server."
[month imap]
(->> imap (find-messages month) (map (partial extract-items (:headers imap))) flatten))

View File

@ -1,4 +1,5 @@
(ns invoices.time)
(ns invoices.time
(:require [clojure.string :as str]))
(defn last-day
@ -25,3 +26,6 @@
[date {to :to from :from}]
(and (or (nil? to) (-> date .toString (compare to) (< 0)))
(or (nil? from) (-> date .toString (compare from) (>= 0)))))
(defn format-month [formatter month]
(->> formatter (java.time.format.DateTimeFormatter/ofPattern) (.format month)))

View File

@ -1,4 +1,4 @@
(ns invoices.jira
(ns invoices.timesheets
(:require [clj-http.client :as client]
[invoices.time :refer [last-day prev-month]]))