Permalink
Browse files

Merge branch 'master' into issue-27

Conflicts:
	src/postal/message.clj
	test/postal/test/message.clj
  • Loading branch information...
2 parents 99c7a6a + 72c6f46 commit e5a3f03e21609a8480984b6b448d092e26d65945 @drewr committed Aug 4, 2013
View
21 CHANGES
@@ -1,3 +1,24 @@
+1.10.3
+
+* Fix bug where nil user/pass will trigger authentication.
+
+1.10.2
+
+* Eliminate many instances of reflection.
+
+1.10.1
+
+* Don't include clojure in dependencies.
+
+1.10.0
+
+* Allow custom filename and description for attachments.
+
+1.9.0
+
+* Support custom message ID.
+* Supply default, customizable user agent.
+
1.8.0
* Add nested multipart support.
View
44 README.md
@@ -20,11 +20,11 @@ SSL.
### Install
-Served by Clojars. In your project.clj:
+Served by Clojars. In your Leiningen project.clj:
- [com.draines/postal "1.8.0"]
+ [com.draines/postal "1.10.3"]
-Likewise substitute any tag, like `1.6.0` etc.
+Likewise substitute any tag name from git.
### Examples
@@ -131,8 +131,10 @@ Attachments and multipart messages can be added as sequences of maps:
{:code 0, :error :SUCCESS, :message "message sent"}
postal.core>
-If your attachment has a content-type that is not recognized by JavaMail, e.g.,
-`.pdf` or `.doc`, you can set `:content-type`.
+If your attachment has a content-type that is not recognized by
+JavaMail, e.g., `.pdf` or `.doc`, you can set `:content-type`. You
+can also set `:file-name` and `:description` if you don't like the
+filename that `:content` uses.
If you want another multipart type than "mixed", you can specify it as a keyword
as the first value in the map sequence. That way you can for example create an
@@ -160,6 +162,32 @@ support (or suppress) HTML-mails:
Postal uses JavaMail under the covers, which defaults to charset
`us-ascii`. To set the charset, set the `:type`, like `"text/html; charset=utf-8"`.
+#### Message ID
+
+Postal will supply a message ID by default that looks like
+`[random]@postal.[host]`. You can customize this by supplying a
+`:message-id` header with a function that takes no args. The included
+`postal.support/message-id` can be used if you'd like to make use of
+its randomness and only customize the hostname.
+
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Message IDs!"
+ :body "Regards."
+ :message-id #(postal.support/message-id "foo.bar.dom")}
+
+#### User Agent
+
+You can customize the default `User-Agent` header (by default
+`postal/VERSION`).
+
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Message IDs!"
+ :body "Regards."
+ :user-agent "MyMailer 1.0"}
+
+
#### Stress-testing
You can stress-test a server by:
@@ -188,7 +216,11 @@ Jeff Palmucci
Allen Rohner
Paul Stadig
Sam Ritchie
+J. David Lowe
+Kevin Dejong
+Colin Jones
+Andy Fingerhut
## License
-Postal is (c) 2009-2011 Andrew A. Raines and released under the MIT license.
+Postal is (c) 2009-2013 Andrew A. Raines and released under the MIT license.
View
9 project.clj
@@ -1,5 +1,8 @@
-(defproject com.draines/postal "1.9-SNAPSHOT"
+(defproject com.draines/postal "1.11-SNAPSHOT"
:repositories {"java.net" "http://download.java.net/maven/2"}
- :dependencies [[org.clojure/clojure "1.4.0"]
+ :dependencies [[commons-codec "1.7"]
[javax.mail/mail "1.4.4"
- :exclusions [javax.activation/activation]]])
+ :exclusions [javax.activation/activation]]]
+ :profiles {:dev {:dependencies [[org.clojure/clojure "1.5.1"]]}
+ :1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]}
+ :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]}})
View
23 src/postal/core.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.core
(:use [postal.sendmail :only [sendmail-send]]
[postal.smtp :only [smtp-send]]
View
25 src/postal/date.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.date
(:import [java.util Date]
[java.text SimpleDateFormat ParsePosition]))
@@ -6,4 +29,4 @@
([tmpl s]
(.parse (SimpleDateFormat. tmpl) s (ParsePosition. 0)))
([]
- (Date.)))
+ (Date.)))
View
23 src/postal/main.clj
@@ -1 +1,24 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.main)
View
64 src/postal/message.clj
@@ -1,8 +1,31 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.message
(:use [clojure.set :only [difference]]
[clojure.java.io :only [file]]
[postal.date :only [make-date]]
- [postal.support :only [do-when make-props]])
+ [postal.support :only [do-when make-props message-id user-agent]])
(:import [java.util UUID]
[javax.mail Session Message$RecipientType]
[javax.mail.internet MimeMessage InternetAddress
@@ -14,21 +37,21 @@
(declare make-jmessage)
(defn recipients [msg]
- (let [jmsg (make-jmessage msg)]
+ (let [^javax.mail.Message jmsg (make-jmessage msg)]
(map str (.getAllRecipients jmsg))))
(defn sender [msg]
(or (:sender msg) (:from msg)))
(defn make-address
- ([addr charset]
+ ([^String addr ^String charset]
(let [a (try (InternetAddress. addr)
(catch Exception _))]
(if a
(InternetAddress. (.getAddress a)
(.getPersonal a)
charset))))
- ([addr name-str charset]
+ ([^String addr ^String name-str ^String charset]
(try (InternetAddress. addr name-str charset)
(catch Exception _))))
@@ -40,13 +63,14 @@
(defn message->str [msg]
(with-open [out (java.io.ByteArrayOutputStream.)]
- (let [jmsg (if (instance? MimeMessage msg) msg (make-jmessage msg))]
+ (let [^javax.mail.Message jmsg (if (instance? MimeMessage msg)
+ msg (make-jmessage msg))]
(.writeTo jmsg out)
(str out))))
(defn add-recipient! [jmsg rtype addr charset]
(if-let [addr (make-address addr charset)]
- (doto jmsg
+ (doto ^javax.mail.Message jmsg
(.addRecipient rtype addr))
jmsg))
@@ -79,6 +103,12 @@
(when (:content-type part)
(.setHeader attachment-part "Content-Type" (:content-type part)))
+ (when (:content-id part)
+ (.setContentID attachment-part (str "<" (:content-id part) ">")))
+ (when (:file-name part)
+ (.setFileName attachment-part (:file-name part)))
+ (when (:description part)
+ (.setDescription attachment-part (:description part)))
attachment-part)
(doto (javax.mail.internet.MimeBodyPart.)
(.setContent (:content part) (:type part)))))
@@ -88,23 +118,23 @@
;; alternative, encrypted...
;; The caller can use the first two entries to specify a type.
;; If no type is given, we default to "mixed" (for attachments etc.)
- [multiPartType, parts] (if (keyword? (first parts))
+ [^String multiPartType, parts] (if (keyword? (first parts))
[(name (first parts)) (rest parts)]
["mixed" parts])
mp (javax.mail.internet.MimeMultipart. multiPartType)]
(doseq [part parts]
(.addBodyPart mp (eval-part part)))
mp))
-(defn add-multipart! [jmsg parts]
+(defn add-multipart! [^javax.mail.Message jmsg parts]
(.setContent jmsg (eval-multipart parts)))
-(defn add-extra! [jmsg msgrest]
+(defn add-extra! [^javax.mail.Message jmsg msgrest]
(doseq [[n v] msgrest]
(.addHeader jmsg (if (keyword? n) (name n) n) v))
jmsg)
-(defn add-body! [jmsg body charset]
+(defn add-body! [^javax.mail.Message jmsg body charset]
(if (string? body)
(doto jmsg (.setText body charset))
(doto jmsg (add-multipart! body))))
@@ -128,9 +158,15 @@
(Session/getInstance props)))]
(make-jmessage msg session)))
([msg session]
- (let [standard [:from :reply-to :to :cc :bcc :date :subject :body]
+ (let [standard [:from :reply-to :to :cc :bcc
+ :date :subject :body :message-id
+ :user-agent]
charset (or (:charset msg) default-charset)
- jmsg (MimeMessage. session)]
+ jmsg (proxy [MimeMessage] [session]
+ (updateMessageID []
+ (.setHeader
+ this
+ "Message-ID" ((:message-id msg message-id)))))]
(doto jmsg
(add-recipients! Message$RecipientType/TO (:to msg) charset)
(add-recipients! Message$RecipientType/CC (:cc msg) charset)
@@ -142,8 +178,10 @@
(make-addresses reply-to charset)))
(.setSubject (:subject msg))
(.setSentDate (or (:date msg) (make-date)))
+ (.addHeader "User-Agent" (:user-agent msg (user-agent)))
(add-extra! (drop-keys msg standard))
- (add-body! (:body msg) charset)))))
+ (add-body! (:body msg) charset)
+ (.saveChanges)))))
(defn make-fixture [from to & {:keys [tag]}]
(let [uuid (str (UUID/randomUUID))
View
29 src/postal/sendmail.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.sendmail
(:use [postal.message :only [message->str sender recipients]]))
@@ -33,9 +56,11 @@
:message message}))
(defn sendmail-find []
- (first (filter #(.isFile (java.io.File. %)) sendmails)))
+ (if-let [SENDMAIL (System/getenv "SENDMAIL")]
+ SENDMAIL
+ (first (filter #(.isFile (java.io.File. ^String %)) sendmails))))
-(defn sanitize [text]
+(defn sanitize [^String text]
(.replaceAll text "\r\n" (System/getProperty "line.separator")))
(defn sendmail-send [msg]
View
47 src/postal/smtp.clj
@@ -1,13 +1,38 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.smtp
(:use [postal.message :only [make-jmessage]]
[postal.support :only [make-props]])
(:import [javax.mail Transport Session]))
-(defn ^:dynamic smtp-send* [session proto {:keys [host port user pass]} msgs]
+(defn ^:dynamic smtp-send* [^Session session ^String proto
+ {:keys [host port user pass]} msgs]
+ (assert (or (and (nil? user) (nil? pass)) (and user pass)))
(with-open [transport (.getTransport session proto)]
- (.connect transport host port (str user) (str pass))
+ (.connect transport host port user pass)
(let [jmsgs (map #(make-jmessage % session) msgs)]
- (doseq [jmsg jmsgs]
+ (doseq [^javax.mail.Message jmsg jmsgs]
(.sendMessage transport jmsg (.getAllRecipients jmsg)))
{:code 0 :error :SUCCESS :message "messages sent"})))
@@ -22,12 +47,12 @@
([args & msgs]
(let [{:keys [host port user pass sender ssl]
:or {host "localhost"}} args
- port (if (nil? port)
- (if ssl 465 25)
- port)
- proto (if ssl "smtps" "smtp")
- args (merge args {:port port
- :proto proto})
- session (doto (Session/getInstance (make-props sender args))
- (.setDebug false))]
+ port (if (nil? port)
+ (if ssl 465 25)
+ port)
+ proto (if ssl "smtps" "smtp")
+ args (merge args {:port port
+ :proto proto})
+ session (doto (Session/getInstance (make-props sender args))
+ (.setDebug false))]
(smtp-send* session proto args msgs))))
View
25 src/postal/stress.clj
@@ -1,11 +1,34 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.stress
(:import [java.util Date]
[java.text SimpleDateFormat]
[java.util.concurrent CountDownLatch])
(:use [postal.smtp :only [smtp-send]]
[postal.message :only [make-fixture]]))
-(def DATEFORMAT (SimpleDateFormat. "yyyy-MM-dd.HH:mm:ss"))
+(def ^SimpleDateFormat DATEFORMAT (SimpleDateFormat. "yyyy-MM-dd.HH:mm:ss"))
(defonce counter (atom 0))
View
54 src/postal/support.clj
@@ -1,5 +1,30 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.support
- (:import [java.util Properties]))
+ (:require [clojure.java.io :as io])
+ (:import (java.util Properties Random)
+ (org.apache.commons.codec.binary Base64)))
(defmacro do-when
[arg condition & body]
@@ -14,3 +39,30 @@
(do-when sender (.put "mail.smtp.from" sender))
(do-when user (.put "mail.smtp.user" user))
(do-when tls (.put "mail.smtp.starttls.enable" "true"))))
+
+(defn hostname []
+ (.getHostName (java.net.InetAddress/getLocalHost)))
+
+(defn message-id
+ ([]
+ (message-id (format "postal.%s" (hostname))))
+ ([host]
+ (let [bs (byte-array 16)
+ r (Random.)
+ _ (.nextBytes r bs)
+ rs (String. (Base64/encodeBase64 bs))
+ onlychars (apply str (re-seq #"[0-9A-Za-z]" rs))
+ epoch (.getTime (java.util.Date.))]
+ (format "<%s.%s@%s>" onlychars epoch host))))
+
+(defn pom-version []
+ (let [pom "META-INF/maven/com.draines/postal/pom.properties"
+ props (doto (Properties.)
+ (.load (-> pom io/resource io/input-stream)))]
+ (.getProperty props "version")))
+
+(defn user-agent []
+ (let [prop (Properties.)
+ ver (or (System/getProperty "postal.version")
+ (pom-version))]
+ (format "postal/%s" ver)))
View
1 test/META-INF/maven/com.draines/postal/pom.properties
@@ -0,0 +1 @@
+version=99999999
View
23 test/postal/test/core.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.core
(:require [postal.core :as postal]
[postal.sendmail :as local]
View
23 test/postal/test/date.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.date
(:use [postal.date])
(:import [java.util Date]
View
23 test/postal/test/main.clj
@@ -1,2 +1,25 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.main
(:use [postal.main]))
View
195 test/postal/test/message.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.message
(:use [postal.message]
[clojure.test :only [run-tests deftest is]]
@@ -20,90 +43,110 @@
(is (re-find #"(?i)content-type:.*us-ascii" (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))))))
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body [{:type "text/html"
+ :content "<b>some html</b>"}]})]
+ (is (.contains m "multipart/mixed"))
+ (is (.contains m "Content-Type: text/html"))
+ (is (.contains m "some html"))))
(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))))
+ m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body [{:type :inline
+ :content f}]})]
+ (is (.contains m "tempfile"))
(.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))))
+ m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body [{:type :attachment
+ :content f1}
+ {:type :attachment
+ :content f2}]})]
+ (is (.contains m "tempfile"))
+ (.delete f1)))
+
+(deftest test-attachment-with-custom-name-and-description
+ (let [f1 (doto (java.io.File/createTempFile "_postal-" ".txt"))
+ _ (doto (java.io.PrintWriter. f1)
+ (.println "tempfile contents") (.close))
+ m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body [{:type "text/plain"
+ :content "See attached"}
+ {:type :attachment
+ :file-name "ImportantDocumentA.txt"
+ :description "A document that we should all marvel at"
+ :content f1}]})]
+ (is (.contains m "tempfile"))
+ (is (.contains m "ImportantDocumentA.txt"))
+ (is (.contains m "A document that we should all marvel at"))
(.delete f1)))
(deftest test-nested
(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 [[:alternative
- {:type "text/html"
- :content "<b>some html</b>"}
- {:type "text/plain"
- :content "some text"}]
- {:type :attachment
- :content f}]}]
- (is (= "multipart/mixed" (re-find #"multipart/mixed" (message->str m))))
- (is (= "multipart/alternative"
- (re-find #"multipart/alternative" (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))))
- (is (= "Content-Type: text/plain"
- (re-find #"Content-Type: text/plain" (message->str m))))
- (is (= "some text" (re-find #"some text" (message->str m))))
- (is (= "tempfile" (re-find #"tempfile" (message->str m))))
+ m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body [[:alternative
+ {:type "text/html"
+ :content "<b>some html</b>"}
+ {:type "text/plain"
+ :content "some text"}]
+ {:type :attachment
+ :content f}]})]
+ (is (.contains m "multipart/mixed"))
+ (is (.contains m "multipart/alternative"))
+ (is (.contains m "Content-Type: text/html"))
+ (is (.contains m "some html"))
+ (is (.contains m "Content-Type: text/plain"))
+ (is (.contains m "some text"))
+ (is (.contains m "tempfile"))
(.delete f)))
(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))))))
+ (is (zero? (.indexOf (:subject (make-fixture from to :tag tag)) "[TEST")))))
(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)))))
+ (is (.contains (message->str m) "User-Agent: Lorem Ipsum"))))
(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))))))
+ (let [m (message->str
+ {:from "foo @bar.dom"
+ :to "badddz@@@bar.dom"
+ :subject "Test"
+ :body "Bad recipient!"})]
+ (is (not (.contains m "badddz")))
+ (is (not (.contains m "foo @bar")))))
(deftest test-reply-to
(let [m {:from "foo@bar.dom"
@@ -131,4 +174,52 @@
(is (.contains (message->str m)
"Content-Type: text/plain; charset=iso-8859-1"))
(is (.contains (message->str m) "=?iso-8859-1?B?7T8=?="))
- (is (.contains (message->str m) "Plain Addr"))))
+ (is (.contains (message->str m) "Plain Addr")))
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body "Reply me!"
+ :reply-to "yermom@bar.dom"})]
+ (is (.contains m "Reply-To: yermom"))))
+
+(deftest test-only-bcc
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :bcc "baz@bar.dom"
+ :subject "Test"
+ :body "Only Bcc!!"})]
+ (is (.contains m "Bcc: baz"))
+ (is (not (.contains m "To: ")))))
+
+(deftest test-message-id
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body "Where is that message ID!"})]
+ (is (re-find #"Message-ID: <.*?@postal\..*>" m)))
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body "Where is that message ID!"
+ :message-id #(postal.support/message-id "foo.bar.dom")})]
+ (is (.contains m "@foo.bar.dom")))
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body "Where is that message ID!"
+ :message-id (fn [] "foo")})]
+ (is (.contains m "Message-ID: foo"))))
+
+(deftest test-user-agent
+ (let [m (message->str
+ {:from "foo@bar.dom"
+ :to "baz@bar.dom"
+ :subject "Test"
+ :body "Where is that message ID!"
+ :user-agent "foo/1.0"})]
+ (is (.contains m "User-Agent: foo"))))
+
View
23 test/postal/test/sendmail.clj
@@ -1,2 +1,25 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.sendmail
(:use [postal.message :only [message->str sender recipients]]))
View
29 test/postal/test/smtp.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.smtp
(:use [clojure.test])
(:require [postal.smtp :as smtp] :reload))
@@ -36,4 +59,10 @@
{"mail.smtp.user" "foo"
"mail.smtp.port" 465
"mail.smtp.auth" "true"
+ "mail.smtp.host" "smtp.bar.dom"})
+ (is-props {:host "smtp.bar.dom"
+ :user nil
+ :pass nil}
+ {"mail.smtp.port" 25
+ "mail.smtp.auth" "false"
"mail.smtp.host" "smtp.bar.dom"}))
View
23 test/postal/test/stress.clj
@@ -1,3 +1,26 @@
+;; Copyright (c) Andrew A. Raines
+;;
+;; Permission is hereby granted, free of charge, to any person
+;; obtaining a copy of this software and associated documentation
+;; files (the "Software"), to deal in the Software without
+;; restriction, including without limitation the rights to use,
+;; copy, modify, merge, publish, distribute, sublicense, and/or sell
+;; copies of the Software, and to permit persons to whom the
+;; Software is furnished to do so, subject to the following
+;; conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+;; OTHER DEALINGS IN THE SOFTWARE.
+
(ns postal.test.stress
(:import [java.util Date]
[java.text SimpleDateFormat]

0 comments on commit e5a3f03

Please sign in to comment.