sending email (SMTP + SSL)

207 views
Skip to first unread message

Chouser

unread,
Feb 29, 2008, 10:27:01 AM2/29/08
to Clojure
I don't know if anyone else will care, but here's a function for
sending email over SSL SMTP that I got working last night:

(defn sendmail [& optlist]
(let [props (new java.util.Properties)
opts (merge (apply hash-map optlist) {
:starttls.enable true
:auth true
:socketFactory.port (opts :port)
:socketFactory.class
"javax.net.ssl.SSLSocketFactory"
:socketFactory.fallback false})]
(doseq opt opts
(. props
(put (str "mail.smtp." (. (str (key opt)) (substring 1)))
(str (val opt)))))
(. javax.mail.Transport
(send
(doto (new javax.mail.internet.MimeMessage
(. javax.mail.Session
(getInstance
props
(new net.n01se.chouser.SimpleAuthenticator
(opts :user) (opts :password)))))
(setText (opts :text))
(setSubject (opts :subject))
(setFrom (new javax.mail.internet.InternetAddress
(opts :user)))
(addRecipient
(. javax.mail.Message$RecipientType TO)
(new javax.mail.internet.InternetAddress
(opts :to))))))))

Then use it like so:

(sendmail :user "sen...@example.com" :password "nottellingyou"
:host "smtp.gmail.com" :port 465
:to "reci...@example.com" :subject "test message"
:text "This is the message")

Unfortunately I couldn't figure out how to get it to work without this
little Java class:

package net.n01se.chouser;

public class SimpleAuthenticator extends javax.mail.Authenticator
{
String email, password;

public SimpleAuthenticator( String e, String p ) {
email = e;
password = p;
}

public javax.mail.PasswordAuthentication getPasswordAuthentication()
{
return new javax.mail.PasswordAuthentication(email, password);
}
}

So much thanks to Rich (as usual). Anybody know how I could implement
SimpleAuthenticator in Clojure instead of Java?

--Chouser

Chouser

unread,
Feb 29, 2008, 10:31:31 AM2/29/08
to Clojure
Oops, sorry, had an incorrect untested change.

On Feb 29, 10:27 am, Chouser <chou...@gmail.com> wrote:
> (defn sendmail [& optlist]
> (let [props (new java.util.Properties)
> opts (merge (apply hash-map optlist) {
> :starttls.enable true

That should be:

(defn sendmail [& optlist]
(let [props (new java.util.Properties)
opts (apply hash-map optlist)
opts (merge (apply hash-map optlist) {
:starttls.enable true

--Chouser

Chouser

unread,
Mar 4, 2008, 4:19:52 PM3/4/08
to Clojure
This version uses the new dynamic proxies so it no longer requires a
Java helper class:

(defn sendmail [& optlist]
(let [props (new java.util.Properties)
opts (apply hash-map optlist)
opts (merge (apply hash-map optlist) {
:starttls.enable true
:auth true
:socketFactory.port (opts :port)
:socketFactory.class
"javax.net.ssl.SSLSocketFactory"
:socketFactory.fallback false})]
(doseq opt opts
(. props
(put (str "mail.smtp." (. (str (key opt)) (substring
1)))
(str (val opt)))))
(let [msg (new javax.mail.internet.MimeMessage
(. javax.mail.Session
(getInstance
props
(proxy [javax.mail.Authenticator] []
(getPasswordAuthentication []
(new
javax.mail.PasswordAuthentication
(opts :user)
(opts :password)))))))]
(cond (opts :text) (. msg (setText (opts :text)))
:else (. msg (setText (opts :html) "UTF-8"
"html")))
(. msg (setSubject (opts :subject)))
(. msg (setFrom (new javax.mail.internet.InternetAddress
(opts :user))))
(doseq rcpt (opts :to)
(. msg (addRecipient
(. javax.mail.Message$RecipientType TO)
(new javax.mail.internet.InternetAddress
rcpt))))
(. javax.mail.Transport (send msg)))))

This version also supports multiple recipients and html message
bodies:

(sendmail :user "fr...@example.com" :password "nottellingyou"
:host "smtp.gmail.com" :port 465
:to ["t...@example.com" "t...@example.com] :subject "test
message"
:html "This is the <b>message</b>")
Reply all
Reply to author
Forward
0 new messages