Jenny
Jenny

Reputation: 333

scala Play Framework 2.4: sending email

I trying to send an email from scala Play framework 2.4 while using play-mailer, I have followed the instruction from their sample page but with no success.

I have added the dependency to build.sbt:

libraryDependencies ++= Seq(
  "com.typesafe.play" %% "play-mailer" % "3.0.1"
)

In application.conf the I have added the following:

play.mailer {
    host=smtp.gmail.com
    port=465 
    ssl=true
    tls=true
    user="[email protected]"
    password=abracadabra
}

And finally, the Mailing Class:

package controllers

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._

class Mail(mailer: MailerClient) {
  def send = {
    val cid = "1234"
    val email = Email(
      "Simple email",
      "Mister FROM <[email protected]>",
      Seq("Miss TO <[email protected]>"),
      bodyText = Some("A text message"),
      bodyHtml = Some("some data....")
    )
    mailer.send(email)
  }
}

So far without compilation errors, however I don't understand how to initialize this class.. how should I get the "MailerClient" instance?

In the documentation it is written "Then in your router definition, use the trait MailerComponents", with the following code example:

import play.api._
import play.api.ApplicationLoader.Context
import router.Routes
import play.api.libs.mailer._

class MyApplicationLoader extends ApplicationLoader {
  def load(context: Context) = {
    new ApplicationComponents(context).application
  }
}

class ApplicationComponents(context: Context) extends BuiltInComponentsFromContext(context) with MailerComponents {
  lazy val myComponent = new MyComponent(mailerClient)
  // create your controllers here ...
  lazy val router = new Routes(...) // inject your controllers here
}

(I have added "play.application.loader=SimpleApplicationLoader" in application.conf)

but I get the following compilation errors:

D:\myApp\app\SimpleApplicationLoader.scala:12: not found: type MailerComponents

[error] class ApplicationComponents(context: Context) extends BuiltInComponentsFromContext(context) with MailerComponents {
[error]                                                                                                  ^
[error] D:\myApp\app\SimpleApplicationLoader.scala:13: not found: value mailerClient
[error]   lazy val applicationController = new controllers.Mail(mailerClient)
[error]                                                         ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed

Any ideas?

Upvotes: 2

Views: 2289

Answers (2)

Bhashit Parikh
Bhashit Parikh

Reputation: 3131

You can go with the run-time dependency injection, as the other answer has suggested. But if you want to go with your current approach, read on...

The problem is, the MailerComponents trait doesn't exist in the 3.x branch. it does seem to exist in the master branch, but not in their next branch. I am not sure what they are doing there.

If you want to continue with the example, you'll need to do a bit of fiddling and figure out how to make it compile. For ex. with a bit of looking around, I came up with the following.

import play.api._
import play.api.ApplicationLoader.Context
import router.Routes
import play.api.libs.mailer._

class SimpleApplicationLoader extends ApplicationLoader {
  def load(context: Context) = {
    new ApplicationComponents(context).application
  }
}

class ApplicationComponents(context: Context) extends BuiltInComponentsFromContext(context) {
  val mailerClient = new CommonsMailer(configuration)
  lazy val applicationController = new controllers.ApplicationScala(mailerClient)
  lazy val assets = new controllers.Assets(httpErrorHandler)
  lazy val router = new Routes(httpErrorHandler, applicationController)
}

Basically, instead of relying on the non-existent MailerComponent to create a mailerClient for me, I just did it myself.

If you have the following line in controllers.ApplicationScala

val id = mailer.configure(Configuration.from(Map("host" -> "typesafe.org", "port" -> 1234))).send(email)

Replace it with:

val id = mailer.send(email)

And it will compile. Meanwhile, I think I should raise an issue on github about this. And maybe you should.

Upvotes: 2

Łukasz
Łukasz

Reputation: 8673

I believe you could simply let play framework inject the mail client. Setting up the configuration and annotating your constructor with @Inject() should work. Declaration of your Mail controller would look like this:

class Mail @Inject() (mailer: MailerClient) {

Upvotes: 0

Related Questions