jurajburian / mailer

Scala mail client wrapper

GitHub

Mailer

alt tag A thin wrapper over JavaMail library written in the Scala language. Mailer's aim is to be used in situations when it is necessary to send multiple mails efficiently. Mailer achieves this by creating a single instance of javax.mail.Session, getting and opening a javax.mail.Transport instance, and sending a bulk of emails through it.

There is actually an existing JavaMail e-mail sender library written in Scala, called Courier. The main motivation of creating another JavaMail wrapper was to solve the several issues of the existing Courier library using following improvements:

  1. Reuses the Transport instance - Courier library creates new Transport instance each time the message is sent. Since this may cause performance problems when sending a bulk of e-mails, Mailer keeps the single instance of Transport opened until the connection is explicitly closed.
  2. Does not force asynchronous sending using the Future - Courier library works in asynchronous manner using the Future and there is no way sending e-mail synchronously. Mailer, on the other hand, keeps the decision about synchronicity on the user, so it can be user for example very effectively in combination with the Akka Actor framework.

Remark: Multiple threads can use a Session. Since a Transport represents a connection to a mail server, and only a single thread can use the connection at a time, a Transport will synchronize access from multiple threads to maintain thread safety, but you'll really only want to use it from a single thread.

API documentation

ScalaDoc documentation is available online for the following Mailer versions. Up-to-date documentation for the most actual version can be displayed anytime here.

Install

Mailer is available for Scala 2.11 and 2.12 To get started with SBT, add dependency to your build.sbt file:

libraryDependencies += "com.github.jurajburian" %% "mailer" % "1.2.3" withSources

Usage

1/ Build plain Java Mail Session:

import com.github.jurajburian.mailer._
val session = (SmtpAddress("smtp.gmail.com", 587) :: SessionFactory()).session(Some("user@gmail.com"-> "password"))
//or for example:
val session2 = (SessionFactory() + (SmtpAddress("smtp.gmail.com", 587)).session()

One can use more properties (instance of Prop) like SmtpTimeout concatenated by :: or + operator. List of all available properties can be found in ScalaDoc, as the known subclasses of the Prop trait.

2/ Build Mailer instance

val mailer = Mailer(session)

Use optional parameter transport: Option[Transport] in Mailer.apply method if is necessary to use different than default transport implementation.

3/ Build message content

Message content is represented by the Content class, an easy-to-use simple wrapper with set of helper methods around the javax.mail.internet.MimeMultipart class. When new instance of Content class is created, individual contents (internally represented by javax.mail.internet.MimeBodyPart) can be added using available helper methods for particular content types (e.g. Content#html for adding HTML content), or instances of javax.mail.internet.MimeBodyPart can be added directly using the Content#append method.

Example of use:

val content: Content = new Content().text("raw text content part").html("<b>HTML</b> content part")

Specific message headers (RFC 822) can be also added to every single message content. Message header is represented by the MessageHeader trait, where one can implement custom classes for specific headers to achieve more typesafe way of adding headers, such as built-in ContentDisposition header shown below. If no specific implementation fits, CustomHeader implementation can be used, allowing to create header with any name and value.

// adds the header "Content-Disposition: inline; filename=foobar.txt" to the selected content
val contentDispositionHeader = ContentDisposition("inline", Map("filename" -> "foobar.txt"))
val content = new Content().text("some text", headers = Seq(contentDispositionHeader))

4/ Send Mail

import javax.mail.internet.InternetAddress
val content = new Content().text("Hello there!")
val msg = Message(
      from = new InternetAddress(SenderAddress),
      subject = "my subject",
      content = content,
      to = Seq(new InternetAddress(ReceiverAddress)))
val mailer = Mailer(session)
// recomendations: use try
Try{mailer.send(msg)}
// or  future
Future{mailer.send(msg)}

Remark: All methods from the Mailer trait may thrown javax.mail.MessagingException.

5/ Close Session

Mailer "session" should be closed. Call mailer.close() or Try{mailer.close()} for this purpose.

Changelog

  • v1.2.3
    • Bugfix: "Message-ID" header now gets correctly set if specified on the message.
  • v1.2.2
    • Bugfix: Added file name to Content.
  • v1.2.1
    • Bugfix: Custom message (or message content) headers are now set after all JavaMail headers, preventing JavaMail from overwriting custom headers.
  • v1.2.0
    • Added option to set custom message headers either to the message itself, or (in case of multipart message) to every body part separately.
    • Scala version update (2.11.7 -> 2.11.8)
    • SBT version update (0.3.9 -> 0.3.11)
  • v1.1.0
    • instance of javax.mail.Transport, used by the mailer is now accessible via Mailer#transport
    • MailerSpec test suite now properly closes SMTP session after test is finished
  • v1.0.0
    • initial release

Contributors

Known users