Skip to content

Instantly share code, notes, and snippets.

@taylorSando
Last active November 3, 2015 19:48
Show Gist options
  • Save taylorSando/979ab571923286b96662 to your computer and use it in GitHub Desktop.
Save taylorSando/979ab571923286b96662 to your computer and use it in GitHub Desktop.
Email polling
(ns workzone.services.email-poll
(:require [clojure.tools.logging :as log]
[clojure.core.async :as core.async]
[clojure.set]
[workzone.model.error :as model.error]
[plumbing.core :refer :all]
[puppetlabs.trapperkeeper.core :refer [defservice]])
(:import javax.mail.Flags
javax.mail.Message
javax.mail.internet.InternetAddress
javax.mail.Session))
(defn extract-email-address [e]
(when e
(re-find #"(?i)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
e)))
(defn -extract-email [msg]
{:subject (.getSubject msg)
:from (extract-email-address (javax.mail.internet.InternetAddress/toString (.getFrom msg)))
:to (-> msg
(.getRecipients javax.mail.Message$RecipientType/TO)
javax.mail.internet.InternetAddress/toString
extract-email-address)
:cc (-> msg
(.getRecipients javax.mail.Message$RecipientType/CC)
javax.mail.internet.InternetAddress/toString
extract-email-address)})
(defn extract-lead-email [msg]
(let [e (-extract-email msg)]
(clojure.set/rename-keys e {:from :lead-publisher
:to :lead-subscriber
:cc :customer-email})))
(defn extract-referral-email [msg]
(let [e (-extract-email msg)]
{:from-user (:from e)
:invited-users [(:to e) (:cc e)]}))
;; This should probably get split up into two functions, an extraction
;; function that gets the emails and returns them, and the actual
;; function to do the doseq email actions. Not sure if deleting
;; the emails has a side effect on the emails taken though.
(defn extract-emails [services store email-extractor email-action-fn]
(let [folder (. store getFolder "inbox")
_ (.open folder (javax.mail.Folder/READ_WRITE))
messages (.getMessages folder) ]
(when (count messages)
(doseq [m messages]
(email-action-fn services (email-extractor m)))
(.setFlags
folder messages (javax.mail.Flags. javax.mail.Flags$Flag/DELETED) true))
(.close folder true)))
(defnk email-poller
[services
poll-active?
email-store
email-extractor
email-action-fn
[:config host username password]]
(clojure.core.async/go-loop []
(clojure.core.async/<! (clojure.core.async/timeout 30000))
(when @poll-active?
(reset! email-store
(.getStore
(javax.mail.Session/getDefaultInstance (System/getProperties))
"pop3s"))
(.connect @email-store host username password)
(clojure.core.async/go-loop []
(clojure.core.async/<! (clojure.core.async/timeout 5000))
(when (and (.isConnected @email-store) @poll-active?)
(try
(extract-emails
services
@email-store
email-extractor
email-action-fn)
;; Going to keep running this no matter what
(catch Exception e
(log/error (model.error/extract-exception e))))
(recur)))
(recur))))
(defprotocol EmailPollService
(check [this]))
(defservice service
EmailPollService
[[:DatomicService conn db]
[:LeadModel publish-email-lead]
[:UserReferralModel create-referral ]
[:EnvironmentConfigService get-in-config]]
(init [this context]
(log/trace "Initializing Email Polilng Service")
(let [poll-active? (atom true)
lead-email-store (atom nil)
referral-email-store (atom nil)
services {:dbs {:main {:db (db) :conn (conn)}}}
lead-poll-config
,{:host (get-in-config [:lead-email-server :host])
:username (get-in-config [:lead-email-server :username])
:password (get-in-config [:lead-email-server :password])}
referral-poll-config
,{:host (get-in-config [:referral-email-server :host])
:username (get-in-config [:referral-email-server :username])
:password (get-in-config [:referral-email-server :password])}]
(email-poller {:services services
:poll-active? poll-active?
:email-store lead-email-store
:email-extractor extract-lead-email
:email-action-fn publish-email-lead
:config lead-poll-config})
(email-poller {:services services
:poll-active? poll-active?
:email-store referral-email-store
:email-extractor extract-referral-email
:email-action-fn create-referral
:config referral-poll-config})
(assoc context
:lead-email-store lead-email-store
:referral-email-store referral-email-store
:poll-active? poll-active?)))
(check [this])
(stop [this context]
(log/trace "Shutting Down Email Polling Service")
(when (.isConnected @(:lead-email-store context))
(.close @(:lead-email-store context)))
(when (.isConnected @(:referral-email-store context))
(.close @(:referral-email-store context)))
(reset! (:poll-active? context) false)
(dissoc context :lead-email-store :referral-email-store :poll-active?)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment