-
-
Save vdebergue/3085938916b56aa90e9f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SMTP config | |
smtp { | |
# set to false in production | |
mock = true | |
user = "" | |
pass = "" | |
host = "localhost" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
libraryDependencies += "org.apache.commons" % "commons-email" % "1.3.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package utils | |
import javax.mail.internet.InternetAddress | |
import javax.mail.util.ByteArrayDataSource | |
import org.apache.commons.mail._ | |
import scala.util.{Try, Failure, Success} | |
import scala.concurrent.ExecutionContext | |
import scala.concurrent.Future | |
import java.io._ | |
case class Email( | |
bodyText: Option[String] = None, | |
bodyHtml: Option[String] = None, | |
charset: Option[String] = None, | |
subject: Option[String] = None, | |
from: Option[String] = None, | |
replyTo: Option[String] = None, | |
recipients: Seq[String] = Seq.empty, | |
ccRecipients: Seq[String] = Seq.empty, | |
bccRecipients: Seq[String] = Seq.empty, | |
headers: Map[String, String] = Map.empty, | |
pjs: Seq[EmailSenderAttachment] = Seq.empty | |
) | |
trait EmailSender { | |
def sendSync(email: Email): Try[Email] | |
def sendAsync(email: Email)(implicit e: ExecutionContext): Future[Try[Email]] = Future { sendSync(email) } | |
} | |
object EmailSender extends EmailSender { | |
private val confPrefix = "smtp" | |
val conf = play.api.Play.current.configuration.getConfig(confPrefix).getOrElse(throwConfigurationNotFound) | |
val mock: Boolean = conf.getBoolean("mock").getOrElse(false) | |
val host: String = if (mock) "mock" else getString("host") | |
val port: Int = conf.getInt("port").getOrElse(25) | |
val ssl: Boolean = conf.getBoolean("ssl").getOrElse(false) | |
val tls: Boolean = conf.getBoolean("tls").getOrElse(false) | |
val user: Option[String] = conf.getString("user") | |
val pass: Option[String] = conf.getString("pass") | |
def get(log: String=>Unit = ((m: String) => play.api.Logger.debug(m))): EmailSender = { | |
if (mock) EmailSenderMock(log) | |
else EmailSenderReal(host, port, ssl, tls, user, pass) | |
} | |
def sendSync(email: Email): Try[Email] = get().sendSync(email) | |
private def getString(key: String) = { | |
conf.getString(key).getOrElse(throwMissingFieldError(key)) | |
} | |
private def throwMissingFieldError(key: String) = { | |
throw conf.globalError( | |
"EmailSender - Unable to find key: [%s.%s]".format(confPrefix, key) | |
) | |
} | |
private def throwConfigurationNotFound() = { | |
throw play.api.Play.current.configuration.globalError( | |
"EmailSender - Configuration not found: [%s]".format(confPrefix) | |
) | |
} | |
} | |
case class EmailSenderReal( | |
host: String, | |
port: Int, | |
ssl: Boolean, | |
tls: Boolean, | |
user: Option[String], | |
pass: Option[String] | |
) extends EmailSender { | |
def sendSync(email: Email): Try[Email] = { | |
Try { | |
val aemail = createEmailer(email.bodyText, email.bodyHtml) | |
aemail.setCharset(email.charset.getOrElse("utf-8")) | |
aemail.setSubject(email.subject.getOrElse("")) | |
email.from.foreach(setAddress(_) { (address, name) => aemail.setFrom(address, name) }) | |
email.replyTo.foreach(setAddress(_) { (address, name) => aemail.addReplyTo(address, name) }) | |
email.recipients.foreach(setAddress(_) { (address, name) => aemail.addTo(address, name) }) | |
email.ccRecipients.foreach(setAddress(_) { (address, name) => aemail.addCc(address, name) }) | |
email.bccRecipients.foreach(setAddress(_) { (address, name) => aemail.addBcc(address, name) }) | |
email.headers.foreach { case (k,v) => aemail.addHeader(k, v) } | |
aemail.setHostName(host) | |
aemail.setSmtpPort(port) | |
aemail.setSSLOnConnect(ssl) | |
aemail.setStartTLSEnabled(tls) | |
email.pjs.foreach { esa => aemail.attach(esa.ds, esa.name, esa.description, esa.disposition)} | |
for(u <- user; p <- pass) yield aemail.setAuthenticator(new DefaultAuthenticator(u, p)) | |
aemail.setDebug(false) | |
aemail.send | |
} | |
} | |
private def createEmailer(bodyText: Option[String], bodyHtml: Option[String]): MultiPartEmail = { | |
(bodyHtml, bodyText) match { | |
case (None, _) => | |
val e = new MultiPartEmail() | |
e.setMsg(bodyText.getOrElse("")) | |
e | |
case (Some(html), None) => | |
val e = new HtmlEmail() | |
e.setHtmlMsg(html) | |
e | |
case (Some(html), Some(text)) => | |
val e = new HtmlEmail() | |
e.setHtmlMsg(html) | |
e.setTextMsg(text) | |
e | |
} | |
} | |
private def setAddress(emailAddress: String)(setter: (String, String) => Unit) = { | |
try { | |
val iAddress = new InternetAddress(emailAddress); | |
val address = iAddress.getAddress() | |
val name = iAddress.getPersonal() | |
setter(address, name) | |
} catch { | |
case e: Throwable => | |
setter(emailAddress, null) | |
} | |
} | |
} | |
case class EmailSenderMock(log: String=>Unit) extends EmailSender { | |
def sendSync(email: Email): Try[Email] = { | |
Try { | |
log("MOCK MAILER: send email") | |
email.from.foreach(from => log(s"FROM: $from")) | |
email.replyTo.foreach(replyTo => log(s"REPLYTO: $replyTo")) | |
email.recipients.foreach(to => log(s"TO: $to")) | |
email.ccRecipients.foreach(cc => log(s"CC: $cc")) | |
email.bccRecipients.foreach(bcc => log(s"BCC: $bcc")) | |
email.subject.foreach(subject => log(s"SUBJECT: $subject")) | |
email.bodyText.foreach(bodyText => log(s"TEXT: $bodyText")) | |
email.bodyHtml.foreach(bodyHtml => log(s"TEXT: $bodyHtml")) | |
email.pjs.foreach(pj => log(s"ATTACHMENT (${pj.ds.getContentType}): ${pj.name}")) | |
} | |
} | |
} | |
case class EmailSenderAttachment( | |
ds: ByteArrayDataSource, | |
name: String, | |
description: String, | |
disposition: String | |
) | |
object EmailSenderUtil { | |
def toEmailSenderAttachment(doc: Array[Byte], contentType: String, name: String, description: String) : EmailSenderAttachment = { | |
EmailSenderAttachment( | |
new ByteArrayDataSource(doc, contentType), | |
name, | |
description, | |
EmailAttachment.ATTACHMENT | |
) | |
} | |
def toEmailSenderAttachment(is: InputStream, contentType: String, name: String, description: String): EmailSenderAttachment = { | |
EmailSenderAttachment( | |
new ByteArrayDataSource(is, contentType), | |
name, | |
description, | |
EmailAttachment.ATTACHMENT | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment