Skip to content

Commit

Permalink
Merge remote-tracking branch 'avbranco/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
drewr committed Apr 16, 2011
2 parents 5dc6ea4 + 226ef32 commit a059c39
Show file tree
Hide file tree
Showing 17 changed files with 144 additions and 111 deletions.
20 changes: 10 additions & 10 deletions README.markdown
Expand Up @@ -21,29 +21,29 @@ and SMTP support. It supports sendmail natively.
At a bare minimum, provide a map with `:from`, `:to`, `:subject`, and `:body`.
This will locally inject the message into sendmail.

user> (in-ns 'com.draines.postal.core)
#<Namespace com.draines.postal.core>
com.draines.postal.core> (send-message {:from "me@draines.com"
user> (in-ns 'postal.core)
#<Namespace postal.core>
postal.core> (send-message {:from "me@draines.com"
:to ["mom@example.com" "dad@example.com"]
:cc "bob@example.com"
:subject "Hi!"
:body "Test."})
{:code 0, :error :SUCCESS, :message "message sent"}
com.draines.postal.core>
postal.core>

To use SMTP, add metadata with a `:host` key.

com.draines.postal.core> (send-message #^{:host "mail.isp.net"}
postal.core> (send-message #^{:host "mail.isp.net"}
{:from "me@draines.com"
:to "foo@example.com"
:subject "Hi!"
:body "Test."})
{:code 0, :error :SUCCESS, :message "message sent"}
com.draines.postal.core>
postal.core>

Attachments and multipart messages can be added as sequences of maps:

com.draines.postal.core> (send-message #^{:host "mail.isp.net"}
postal.core> (send-message #^{:host "mail.isp.net"}
{:from "me@draines.com"
:to "foo@example.com"
:subject "Hi!"
Expand All @@ -55,19 +55,19 @@ Attachments and multipart messages can be added as sequences of maps:
{:type :inline
:content (java.io.File. "/tmp/foo.txt")}]})
{:code 0, :error :SUCCESS, :message "message sent"}
com.draines.postal.core>
postal.core>

You can stress-test a server by:

com.draines.postal.core> (stress #^{:host "localhost"
postal.core> (stress #^{:host "localhost"
:num 1000
:delay 250 ;; msecs
:threads 5 ;; concurrent connections}
{:from "foo@lolz.dom"
:to "bar@lolz.dom"})
sent 1000 msgs to localhost:25
nil
com.draines.postal.core>
postal.core>


### Building
Expand Down
4 changes: 1 addition & 3 deletions project.clj
Expand Up @@ -7,6 +7,4 @@
[javax.mail/mail "1.4.4"
:exclusions [javax.activation/activation]]]
:dev-dependencies [[swank-clojure "1.2.1"]
[lein-clojars "0.6.0"]]
:source-path "src/clj"
:main com.draines.postal.main)
[lein-clojars "0.6.0"]])
1 change: 0 additions & 1 deletion src/clj/com/draines/postal/main.clj

This file was deleted.

8 changes: 4 additions & 4 deletions src/clj/com/draines/postal/core.clj → src/postal/core.clj
@@ -1,7 +1,7 @@
(ns com.draines.postal.core
(:use [com.draines.postal.sendmail :only [sendmail-send]]
[com.draines.postal.smtp :only [smtp-send]]
[com.draines.postal.stress :only [spam]]))
(ns postal.core
(:use [postal.sendmail :only [sendmail-send]]
[postal.smtp :only [smtp-send]]
[postal.stress :only [spam]]))

(defn send-message [msg]
(when-not (and (:from msg)
Expand Down
@@ -1,4 +1,4 @@
(ns com.draines.postal.date
(ns postal.date
(:import [java.util Date]
[java.text SimpleDateFormat ParsePosition]))

Expand Down
1 change: 1 addition & 0 deletions src/postal/main.clj
@@ -0,0 +1 @@
(ns postal.main)
77 changes: 3 additions & 74 deletions src/clj/com/draines/postal/message.clj → src/postal/message.clj
@@ -1,6 +1,5 @@
(ns com.draines.postal.message
(:use [clojure.test :only [run-tests deftest is]]
[com.draines.postal.date :only [make-date]])
(ns postal.message
(:use [postal.date :only [make-date]])
(:import [java.util Properties UUID]
[javax.mail Session Message$RecipientType]
[javax.mail.internet MimeMessage InternetAddress
Expand Down Expand Up @@ -99,74 +98,4 @@
{:from from
:to to
:subject (format "%s Test -- %s" tag uuid)
:body (format "Test %s" uuid)}))

(deftest test-simple
(let [m {:from "fee@bar.dom"
:to "Foo Bar <foo@bar.dom>"
:cc ["baz@bar.dom" "Quux <quux@bar.dom>"]
:date (java.util.Date.)
:subject "Test"
:body "Test!"}]
(is (= "Subject: Test" (re-find #"Subject: Test" (message->str m))))
(is (re-find #"Cc: baz@bar.dom, Quux <quux@bar.dom>" (message->str m)))))

(deftest test-multipart
(let [m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:body [{:type "text/html"
:content "<b>some html</b>"}]}]
(is (= "multipart/mixed" (re-find #"multipart/mixed" (message->str m))))
(is (= "Content-Type: text/html"
(re-find #"Content-Type: text/html" (message->str m))))
(is (= "some html" (re-find #"some html" (message->str m))))))

(deftest test-inline
(let [f (doto (java.io.File/createTempFile "_postal-" ".txt"))
_ (doto (java.io.PrintWriter. f)
(.println "tempfile contents") (.close))
m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:body [{:type :inline
:content f}]}]
(is (= "tempfile" (re-find #"tempfile" (message->str m))))
(.delete f)))

(deftest test-attachment
(let [f1 (doto (java.io.File/createTempFile "_postal-" ".txt"))
_ (doto (java.io.PrintWriter. f1)
(.println "tempfile contents") (.close))
f2 "/etc/resolv.conf"
m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:body [{:type :attachment
:content f1}
{:type :attachment
:content f2}]}]
(is (= "tempfile" (re-find #"tempfile" (message->str m))))
(.delete f1)))

(deftest test-fixture
(let [from "foo@bar.dom"
to "baz@bar.dom"
tag "[TEST]"]
(is (re-find #"^\[TEST" (:subject (make-fixture from to :tag tag))))))

(deftest test-extra-headers
(let [m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:User-Agent "Lorem Ipsum"
:body "Foo!"}]
(is (re-find #"User-Agent: Lorem Ipsum" (message->str m)))))

(deftest test-bad-addrs
(let [m {:from "foo @bar.dom"
:to "badddz@@@bar.dom"
:subject "Test"
:body "Bad recipient!"}]
(is (not (re-find #"badddz" (message->str m))))
(is (not (re-find #"foo @bar" (message->str m))))))
:body (format "Test %s" uuid)}))
@@ -1,5 +1,5 @@
(ns com.draines.postal.sendmail
(:use [com.draines.postal.message :only [message->str sender recipients]]))
(ns postal.sendmail
(:use [postal.message :only [message->str sender recipients]]))

(def sendmails ["/usr/lib/sendmail"
"/usr/sbin/sendmail"
Expand Down
4 changes: 2 additions & 2 deletions src/clj/com/draines/postal/smtp.clj → src/postal/smtp.clj
@@ -1,5 +1,5 @@
(ns com.draines.postal.smtp
(:use [com.draines.postal.message :only [make-jmessage]])
(ns postal.smtp
(:use [postal.message :only [make-jmessage]])
(:import [javax.mail Transport Session]))

(defn smtp-send
Expand Down
18 changes: 4 additions & 14 deletions src/clj/com/draines/postal/stress.clj → src/postal/stress.clj
@@ -1,10 +1,9 @@
(ns com.draines.postal.stress
(ns postal.stress
(:import [java.util Date]
[java.text SimpleDateFormat]
[java.util.concurrent CountDownLatch])
(:use [clojure.test]
[com.draines.postal.smtp :only [smtp-send]]
[com.draines.postal.message :only [make-fixture]]))
(:use [postal.smtp :only [smtp-send]]
[postal.message :only [make-fixture]]))

(def DATEFORMAT (SimpleDateFormat. "yyyy-MM-dd.HH:mm:ss"))

Expand Down Expand Up @@ -64,13 +63,4 @@
ct))
(partition-work n threads)))]
(.await latch)
(reduce #(+ %1 (deref %2)) 0 res))))


(deftest test-partition-work
(is (= [5 5] (partition-work 10 2)))
(is (= [3 3 3 1] (partition-work 10 3)))
(is (= [111 111 111 111 111 111 111 111 111 111 3]
(partition-work 1113 10))))


(reduce #(+ %1 (deref %2)) 0 res))))
6 changes: 6 additions & 0 deletions test/postal/test/core.clj
@@ -0,0 +1,6 @@
(ns postal.test.core
(:use [postal.core]
[postal.sendmail :only [sendmail-send]]
[postal.smtp :only [smtp-send]]
[postal.stress :only [spam]]))

7 changes: 7 additions & 0 deletions test/postal/test/date.clj
@@ -0,0 +1,7 @@
(ns postal.test.date
(:use [postal.date])
(:import [java.util Date]
[java.text SimpleDateFormat ParsePosition]))



2 changes: 2 additions & 0 deletions test/postal/test/main.clj
@@ -0,0 +1,2 @@
(ns postal.test.main
(:use [postal.main]))
78 changes: 78 additions & 0 deletions test/postal/test/message.clj
@@ -0,0 +1,78 @@
(ns postal.test.message
(:use [postal.message]
[clojure.test :only [run-tests deftest is]]
[postal.date :only [make-date]])
(:import [java.util Properties UUID]
[javax.mail Session Message$RecipientType]
[javax.mail.internet MimeMessage InternetAddress
AddressException]))

(deftest test-simple
(let [m {:from "fee@bar.dom"
:to "Foo Bar <foo@bar.dom>"
:cc ["baz@bar.dom" "Quux <quux@bar.dom>"]
:date (java.util.Date.)
:subject "Test"
:body "Test!"}]
(is (= "Subject: Test" (re-find #"Subject: Test" (message->str m))))
(is (re-find #"Cc: baz@bar.dom, Quux <quux@bar.dom>" (message->str m)))))

(deftest test-multipart
(let [m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:body [{:type "text/html"
:content "<b>some html</b>"}]}]
(is (= "multipart/mixed" (re-find #"multipart/mixed" (message->str m))))
(is (= "Content-Type: text/html"
(re-find #"Content-Type: text/html" (message->str m))))
(is (= "some html" (re-find #"some html" (message->str m))))))

(deftest test-inline
(let [f (doto (java.io.File/createTempFile "_postal-" ".txt"))
_ (doto (java.io.PrintWriter. f)
(.println "tempfile contents") (.close))
m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:body [{:type :inline
:content f}]}]
(is (= "tempfile" (re-find #"tempfile" (message->str m))))
(.delete f)))

(deftest test-attachment
(let [f1 (doto (java.io.File/createTempFile "_postal-" ".txt"))
_ (doto (java.io.PrintWriter. f1)
(.println "tempfile contents") (.close))
f2 "/etc/resolv.conf"
m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:body [{:type :attachment
:content f1}
{:type :attachment
:content f2}]}]
(is (= "tempfile" (re-find #"tempfile" (message->str m))))
(.delete f1)))

(deftest test-fixture
(let [from "foo@bar.dom"
to "baz@bar.dom"
tag "[TEST]"]
(is (re-find #"^\[TEST" (:subject (make-fixture from to :tag tag))))))

(deftest test-extra-headers
(let [m {:from "foo@bar.dom"
:to "baz@bar.dom"
:subject "Test"
:User-Agent "Lorem Ipsum"
:body "Foo!"}]
(is (re-find #"User-Agent: Lorem Ipsum" (message->str m)))))

(deftest test-bad-addrs
(let [m {:from "foo @bar.dom"
:to "badddz@@@bar.dom"
:subject "Test"
:body "Bad recipient!"}]
(is (not (re-find #"badddz" (message->str m))))
(is (not (re-find #"foo @bar" (message->str m))))))
3 changes: 3 additions & 0 deletions test/postal/test/sendmail.clj
@@ -0,0 +1,3 @@
(ns postal.test.sendmail
(:use [postal.message :only [message->str sender recipients]]))

3 changes: 3 additions & 0 deletions test/postal/test/smtp.clj
@@ -0,0 +1,3 @@
(ns postal.test.smtp
(:use [postal.message :only [make-jmessage]])
(:import [javax.mail Transport Session]))
17 changes: 17 additions & 0 deletions test/postal/test/stress.clj
@@ -0,0 +1,17 @@
(ns postal.test.stress
(:import [java.util Date]
[java.text SimpleDateFormat]
[java.util.concurrent CountDownLatch])
(:use [clojure.test]
[postal.stress]
[postal.smtp :only [smtp-send]]
[postal.message :only [make-fixture]]))


(deftest test-partition-work
(is (= [5 5] (partition-work 10 2)))
(is (= [3 3 3 1] (partition-work 10 3)))
(is (= [111 111 111 111 111 111 111 111 111 111 3]
(partition-work 1113 10))))


0 comments on commit a059c39

Please sign in to comment.