diff --git a/README.adoc b/README.adoc
index 4b77dba..19cf5b4 100644
--- a/README.adoc
+++ b/README.adoc
@@ -35,6 +35,8 @@ play.mailer {
}
```
+You can also configure the mailer programmatically, see below.
+
## Usage
### Java
@@ -61,7 +63,11 @@ public class MyComponent {
// sends text, HTML or both...
email.setBodyText("A text message");
email.setBodyHtml("
An html message
");
- mailerClient.send(email);
+ // configures the mailer before sending the email
+ Map conf = new HashMap<>();
+ conf.put("host", "typesafe.org");
+ conf.put("port", 1234);
+ mailerClient.configure(new Configuration(conf)).send(email);
}
}
```
@@ -91,7 +97,8 @@ class MyComponent @Inject() (mailerClient: MailerClient) {
bodyText = Some("A text message"),
bodyHtml = Some("An html message
")
)
- mailerClient.send(email)
+ // configures the mailer before sending the email
+ mailer.configure(Configuration.from(Map("host" -> "typesafe.org", "port" -> 1234))).send(email)
}
}
```
diff --git a/sample/app/controllers/ApplicationJava.java b/sample/app/controllers/ApplicationJava.java
index be24a5c..ff1be75 100644
--- a/sample/app/controllers/ApplicationJava.java
+++ b/sample/app/controllers/ApplicationJava.java
@@ -1,6 +1,7 @@
package controllers;
import org.apache.commons.mail.EmailAttachment;
+import play.Configuration;
import play.Play;
import play.api.libs.mailer.MailerClient;
import play.libs.mailer.Email;
@@ -9,6 +10,8 @@
import javax.inject.Inject;
import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
public class ApplicationJava extends Controller {
@@ -31,5 +34,16 @@ public Result send() {
String id = mailer.send(email);
return ok("Email " + id + " sent!");
}
-
+
+ public Result configureAndSend() {
+ final Email email = new Email();
+ email.setSubject("Simple email");
+ email.setFrom("from@email.com");
+ email.addTo("to@email.com");
+ Map conf = new HashMap<>();
+ conf.put("host", "typesafe.org");
+ conf.put("port", 1234);
+ String id = mailer.configure(new Configuration(conf)).send(email);
+ return ok("Email " + id + " sent!");
+ }
}
diff --git a/sample/app/controllers/ApplicationScala.scala b/sample/app/controllers/ApplicationScala.scala
index e21c5ca..e4bc837 100644
--- a/sample/app/controllers/ApplicationScala.scala
+++ b/sample/app/controllers/ApplicationScala.scala
@@ -4,6 +4,7 @@ import java.io.File
import javax.inject.Inject
import org.apache.commons.mail.EmailAttachment
+import play.api.Configuration
import play.api.Play.current
import play.api.libs.mailer._
import play.api.mvc.{Action, Controller}
@@ -25,4 +26,10 @@ class ApplicationScala @Inject()(mailer: MailerClient) extends Controller {
val id = mailer.send(email)
Ok(s"Email $id sent!")
}
+
+ def configureAndSend = Action {
+ val email = Email("Simple email", "from@email.com", Seq("to@email.com"))
+ val id = mailer.configure(Configuration.from(Map("host" -> "typesafe.org", "port" -> 1234))).send(email)
+ Ok(s"Email $id sent!")
+ }
}
diff --git a/sample/build.sbt b/sample/build.sbt
index 172870d..63153ee 100644
--- a/sample/build.sbt
+++ b/sample/build.sbt
@@ -10,7 +10,7 @@ scalaVersion := "2.11.6"
resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases"
libraryDependencies ++= Seq(
- "com.typesafe.play" %% "play-mailer" % "3.0.1-SNAPSHOT"
+ "com.typesafe.play" %% "play-mailer" % "3.0.2-SNAPSHOT"
)
routesGenerator := InjectedRoutesGenerator
diff --git a/sample/conf/routes b/sample/conf/routes
index 912be50..4641222 100644
--- a/sample/conf/routes
+++ b/sample/conf/routes
@@ -2,5 +2,8 @@
# This file defines all application routes (Higher priority routes first)
# ~~~~
-GET /send/java controllers.ApplicationJava.send()
-GET /send/scala controllers.ApplicationScala.send()
+GET /send/java controllers.ApplicationJava.send()
+GET /send/scala controllers.ApplicationScala.send()
+
+GET /configureAndSend/java controllers.ApplicationJava.configureAndSend()
+GET /configureAndSend/scala controllers.ApplicationScala.configureAndSend()
diff --git a/src/main/java/play/libs/mailer/MailerClient.java b/src/main/java/play/libs/mailer/MailerClient.java
index 4a88625..1cd6483 100644
--- a/src/main/java/play/libs/mailer/MailerClient.java
+++ b/src/main/java/play/libs/mailer/MailerClient.java
@@ -1,5 +1,7 @@
package play.libs.mailer;
+import play.Configuration;
+
/**
* A mailer client.
*/
@@ -12,4 +14,12 @@ public interface MailerClient {
* @return The message id.
*/
String send(Email email);
+
+ /**
+ * Configure the underlying instance of mailer
+ *
+ * @param configuration The configuration
+ * @return The mailer client
+ */
+ MailerClient configure(Configuration configuration);
}
diff --git a/src/main/scala/play/api/libs/mailer/MailerPlugin.scala b/src/main/scala/play/api/libs/mailer/MailerPlugin.scala
index 64559ce..18aa252 100644
--- a/src/main/scala/play/api/libs/mailer/MailerPlugin.scala
+++ b/src/main/scala/play/api/libs/mailer/MailerPlugin.scala
@@ -8,6 +8,7 @@ import org.apache.commons.mail._
import play.api.inject._
import play.api.{Configuration, Environment, Logger, PlayConfig}
import play.libs.mailer.{Email => JEmail, MailerClient => JMailerClient}
+import play.{Configuration => JConfiguration}
import scala.collection.JavaConverters._
@@ -38,12 +39,24 @@ trait MailerClient extends JMailerClient {
*/
def send(data: Email): String
+ /**
+ * Configure the underlying instance of mailer.
+ *
+ * @param configuration configuration
+ * @return the mailer client
+ */
+ def configure(configuration: Configuration): MailerClient
+
+ override def configure(configuration: JConfiguration): JMailerClient = {
+ configure(Configuration(configuration.underlying()))
+ }
+
override def send(data: JEmail): String = {
val email = convert(data)
send(email)
}
- protected def convert(data: play.libs.mailer.Email): Email = {
+ protected def convert(data: JEmail): Email = {
val attachments = data.getAttachments.asScala.map {
case attachment =>
if (Option(attachment.getFile).isDefined) {
@@ -79,14 +92,14 @@ trait MailerClient extends JMailerClient {
class CommonsMailer @Inject()(configuration: Configuration) extends MailerClient {
- private val mailerConfig = PlayConfig(configuration).getDeprecatedWithFallback("play.mailer", "smtp")
- private lazy val mock = mailerConfig.get[Boolean]("mock")
+ private val defaultConfig = PlayConfig(configuration).getDeprecatedWithFallback("play.mailer", "smtp")
+ private lazy val mock = defaultConfig.get[Boolean]("mock")
private lazy val instance = {
if (mock) {
new MockMailer()
} else {
- new SMTPMailer(SMTPConfiguration(mailerConfig)) {
+ new SMTPMailer(defaultConfig) {
override def send(email: MultiPartEmail): String = email.send()
override def createMultiPartEmail(): MultiPartEmail = new MultiPartEmail()
override def createHtmlEmail(): HtmlEmail = new HtmlEmail()
@@ -94,10 +107,16 @@ class CommonsMailer @Inject()(configuration: Configuration) extends MailerClient
}
}
- override def send(data: Email): String = instance.send(data)
+ override def send(data: Email): String = {
+ instance.send(data)
+ }
+
+ override def configure(configuration: Configuration) = {
+ instance.configure(configuration)
+ }
}
-abstract class SMTPMailer(config: SMTPConfiguration) extends MailerClient {
+abstract class SMTPMailer(defaultConfig: PlayConfig, var config: Option[SMTPConfiguration] = None) extends MailerClient {
def send(email: MultiPartEmail): String
@@ -107,7 +126,13 @@ abstract class SMTPMailer(config: SMTPConfiguration) extends MailerClient {
override def send(data: Email): String = send(createEmail(data))
+ override def configure(configuration: Configuration) = {
+ config = Some(SMTPConfiguration(PlayConfig(Configuration.reference.getConfig("play.mailer").get ++ configuration)))
+ this
+ }
+
def createEmail(data: Email): MultiPartEmail = {
+ val conf = config.getOrElse(SMTPConfiguration(defaultConfig))
val email = createEmail(data.bodyText, data.bodyHtml, data.charset.getOrElse("utf-8"))
email.setSubject(data.subject)
setAddress(data.from) { (address, name) => email.setFrom(address, name) }
@@ -119,8 +144,8 @@ abstract class SMTPMailer(config: SMTPConfiguration) extends MailerClient {
data.headers.foreach {
header => email.addHeader(header._1, header._2)
}
- config.timeout.foreach(email.setSocketTimeout)
- config.connectionTimeout.foreach(email.setSocketConnectionTimeout)
+ conf.timeout.foreach(email.setSocketTimeout)
+ conf.connectionTimeout.foreach(email.setSocketConnectionTimeout)
data.attachments.foreach {
case attachmentData: AttachmentData =>
val description = attachmentData.description.getOrElse(attachmentData.name)
@@ -137,16 +162,16 @@ abstract class SMTPMailer(config: SMTPConfiguration) extends MailerClient {
emailAttachment.setDisposition(disposition)
email.attach(emailAttachment)
}
- email.setHostName(config.host)
- email.setSmtpPort(config.port)
- email.setSSLOnConnect(config.ssl)
- if (config.ssl) {
- email.setSslSmtpPort(config.port.toString)
+ email.setHostName(conf.host)
+ email.setSmtpPort(conf.port)
+ email.setSSLOnConnect(conf.ssl)
+ if (conf.ssl) {
+ email.setSslSmtpPort(conf.port.toString)
}
- email.setStartTLSEnabled(config.tls)
- for (u <- config.user; p <- config.password) yield email.setAuthenticator(new DefaultAuthenticator(u, p))
- if (config.debugMode && Logger.isDebugEnabled) {
- email.setDebug(config.debugMode)
+ email.setStartTLSEnabled(conf.tls)
+ for (u <- conf.user; p <- conf.password) yield email.setAuthenticator(new DefaultAuthenticator(u, p))
+ if (conf.debugMode && Logger.isDebugEnabled) {
+ email.setDebug(conf.debugMode)
email.getMailSession.setDebugOut(new PrintStream(new FilterOutputStream(null) {
override def write(b: Array[Byte]) {
Logger.debug(new String(b))
@@ -222,6 +247,8 @@ class MockMailer @Inject() extends MailerClient {
email.headers.foreach(header => Logger.info(s"header: $header"))
""
}
+
+ override def configure(configuration: Configuration) = this
}
sealed trait Attachment
@@ -263,7 +290,7 @@ case class SMTPConfiguration(host: String,
object SMTPConfiguration {
def apply(config: PlayConfig) = new SMTPConfiguration(
- config.getOptional[String]("host").getOrElse(throw new RuntimeException("play.mailer.host needs to be set in application.conf in order to use this plugin (or set play.mailer.mock to true)")),
+ config.getOptional[String]("host").getOrElse(throw new RuntimeException("host needs to be set in order to use this plugin (or set play.mailer.mock to true in application.conf)")),
config.get[Int]("port"),
config.get[Boolean]("ssl"),
config.get[Boolean]("tls"),
@@ -273,4 +300,4 @@ object SMTPConfiguration {
config.getOptional[Int]("timeout"),
config.getOptional[Int]("connectiontimeout")
)
-}
+}
\ No newline at end of file
diff --git a/src/test/scala/play/api/libs/mailer/MailerPluginSpec.scala b/src/test/scala/play/api/libs/mailer/MailerPluginSpec.scala
index b97cd87..f4ae587 100644
--- a/src/test/scala/play/api/libs/mailer/MailerPluginSpec.scala
+++ b/src/test/scala/play/api/libs/mailer/MailerPluginSpec.scala
@@ -5,6 +5,7 @@ import javax.mail.Part
import org.apache.commons.mail.{EmailConstants, HtmlEmail, MultiPartEmail}
import org.specs2.mutable._
+import play.api.{PlayConfig, Configuration}
import play.api.test._
class MailerPluginSpec extends Specification {
@@ -12,6 +13,7 @@ class MailerPluginSpec extends Specification {
object SimpleMailerClient extends MailerClient {
override def send(data: Email): String = ""
override def convert(data: play.libs.mailer.Email) = super.convert(data)
+ override def configure(configuration: Configuration): MailerClient = this
}
class MockMultiPartEmail extends MultiPartEmail {
override def getPrimaryBodyPart = super.getPrimaryBodyPart
@@ -26,7 +28,7 @@ class MailerPluginSpec extends Specification {
object MockSMTPMailer extends MockSMTPMailerWithTimeouts(None, None)
class MockSMTPMailerWithTimeouts(smtpTimeout: Option[Int], smtpConnectionTimeout: Option[Int])
- extends SMTPMailer(SMTPConfiguration("typesafe.org", 1234, ssl = true, tls = false, Some("user"), Some("password"), debugMode = false, smtpTimeout, smtpConnectionTimeout)) {
+ extends SMTPMailer(PlayConfig(Configuration.empty), Some(SMTPConfiguration("typesafe.org", 1234, ssl = true, tls = false, Some("user"), Some("password"), debugMode = false, smtpTimeout, smtpConnectionTimeout))) {
override def send(email: MultiPartEmail) = ""
override def createMultiPartEmail(): MultiPartEmail = new MockMultiPartEmail
override def createHtmlEmail(): HtmlEmail = new MockHtmlEmail
@@ -47,6 +49,27 @@ class MailerPluginSpec extends Specification {
email.getMailSession.getProperty("mail.debug") mustEqual "false"
}
+ "reconfigure SMTP" in {
+ val mailer = MockSMTPMailer
+ mailer.configure(Configuration.from(Map(
+ "host" -> "playframework.com",
+ "port" -> 5678,
+ "ssl" -> false,
+ "tls" -> true
+ )))
+ val email = mailer.createEmail(Email(
+ subject = "Subject",
+ from = "James Roper "
+ ))
+ email.getSmtpPort mustEqual "5678"
+ // Default value
+ email.getSslSmtpPort mustEqual "465"
+ email.getMailSession.getProperty("mail.smtp.auth") must beNull
+ email.getMailSession.getProperty("mail.smtp.host") mustEqual "playframework.com"
+ email.getMailSession.getProperty("mail.smtp.starttls.enable") mustEqual "true"
+ email.getMailSession.getProperty("mail.debug") mustEqual "false"
+ }
+
"configure the SMTP timeouts if configured" in {
val mailer = new MockSMTPMailerWithTimeouts(Some(10), Some(99))
val email = mailer.createEmail(Email(