Applications that read emails

I have long written applications that have the crucial functionality of sending emails. But now we are considering a solution that negotiates successful payments by reading notification emails sent (with this provider, it is either emails or setting up a post address for it to make an http notification). As I decide which way to go, I need to look in to the reality of an email-reading application. Any wisdom, recommendations, or how-tos out there for doing this in Clojure?

I’m afraid I can’t help on the mail thing, but my first reaction is that setting up an endpoint for those POSTs may be the simpler way to go about this…

2 Likes

I agree with @mvarela that using POST endpoints is the simpler way.

And this opinion is informed by having had to parse incoming emails (that contain attachments containing inventory data), and setting up an “inbound parse” using the sendgrid product, this “inbound parse” functionality simply making available POSTing received emails to an HTTP(S) endpoint.

1 Like

Also have a look at https://emailengine.app/ which acts as a rest api on top of email.

Depending on your situation it can save you from having to deal with IMAP.

1 Like

Agreed handling a post request sounds infinitely more nice than parsing emails. But if you do want to play around with parsing emails, it’s pretty easy to receive them; here’s code I’ve been using to receive newsletters for a while:

{:deps {org.subethamail/subethasmtp {:mvn/version "3.1.7"}}}

(ns example
  (:require [clojure.java.io :as io])
  (:import [javax.mail.internet MimeMessage]
           [javax.mail Session]
           [org.subethamail.smtp.helper
            SimpleMessageListenerAdapter
            SimpleMessageListener]
           [org.subethamail.smtp.server SMTPServer]))

(defn handle-deliver [{:keys [from to data]}]
  (let [raw-text (slurp data) ; You'll probably want to store this somewhere
        parsed-msg (MimeMessage.
                     (Session/getInstance
                       (java.util.Properties.))
                     (io/input-stream (.getBytes raw)))]
        ; ... do stuff with parsed-msg
    ))

(defn should-accept? [{:keys [from to]}]
  ; e.g. make sure to is valid
  )

(comment

  ; start an SMTP server
  (def server (doto (SMTPServer.
                      (SimpleMessageListenerAdapter.
                        (proxy [SimpleMessageListener] []
                          ; I like to call out to other fns immediately so they
                          ; can be redefined from the repl without restarting
                          ; the server.
                          (accept [from to]
                            (should-accept? {:from from
                                             :to to}))
                          (deliver [from to data]
                            (handle-deliver {:from from
                                             :to to
                                             :data data})))))
                (.setPort 2525) ; I set iptables to forward port 25 to 2525
                (.start))

    ; stop it
    (.stop server)
    ))
6 Likes

Welcome to Clojureverse, Jacob! You are definitely experienced at dealing with emails. I think I will follow the overwhelming consensus that parsing the emails is a pain – but thanks for your code snippet!

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.