Mail

AdonisJs has first class support for sending emails. The mail provider comes with a handful of drivers to send emails, which includes.

  • Smtp ( smtp )

  • Spark Post ( sparkpost )

  • Mailgun ( mailgun )

  • Amazon SES ( ses )

Setup

The mail provider is not part of the default project structure and must be installed as defined in following steps.

adonis install @adonisjs/mail

Next, register the provider inside start/app.js file.

const providers = [
  '@adonisjs/mail/providers/MailProvider'
]

The configuration is saved inside config/mail.js file. Make sure to update the settings as per your needs.

Basic Example

Let’s start with the basic example of sending email on user registration.

Route.post('user', 'UserController.store')
const Mail = use('Mail')

class UserController {

  async store ({ request }) {
    const data = request.only(['email', 'username', 'password'])
    const user = await User.create(data)

    await Mail.send('emails.welcome', user.toJSON(), (message) => {
      message
        .to(user.email)
        .from('<from-email>')
        .subject('Welcome to yardstick')
    })

    return 'Registered successfully'
  }
}

module.exports = UserController

Finally, we need to create emails/welcome.edge view, which is the HTML body.

<h2> Hello {{ username }} </h2>
<p>
  Welcome to the yardstick club, here's your getting started guide
</p>

Mail API

Below is the list of methods you can use to send emails.

send(views, data, callback)

Send email using one or multiple Edge views.

await Mail.send('view', data, (message) => {
  message
    .from('')
    .to('')
})

The views can be a single view or an array of views for a specific content type.

await Mail.send(['welcome', 'welcome.text'])

The view ending with .text is used as the plain text body of the email. In the same way, you can set the mail body for Apple watch.

await Mail.send(['welcome', 'welcome.text', 'welcome.watch'])

raw(body, callback)

Use raw string to send the mail. The body value is considered as the plain text email.

await Mail.raw('... everyone who got this message.', (message) => {
  message.subject('Hello ...')
  message.from('[email protected]')
  message.to('[email protected]')
})

Message API

Below is the list of methods you can use to build message using fluent message API.

to(address, [name])

Set to address.

message.to(user.email)

// with email and name both
message.to(user.email, user.name)

from(address, [name])

Set from address.

message.from('[email protected]')

// with email and name both
message.from('[email protected]', 'Yardstick')

cc(address, [name])

Add cc address on the email

message.cc(user.email)

// with email and name both
message.cc(user.email, user.name)

bcc(address, [name])

Add bcc address on the email.

message.bcc(user.email)

// with email and name both
message.bcc(user.email, user.name)

Also, you can call the above methods for multiple times to defined multiple addresses.

replyTo(address, [name])

Set replyTo email address

message.replyTo('[email protected]')

inReplyTo(messageId)

Set email message id

message.inReplyTo(someThread.id)

subject(value)

Set email subject

message.subject('Welcome to yardstick')

text(value)

Manually set the plain text body for the email.

message.text('Email plain text version')

attach(filePath, options)

Attach file(s) with email.

message
  .attach(Helpers.tmpPath('guides/getting-started.pdf'))

Set custom file name

message
  .attach(Helpers.tmpPath('guides/getting-started.pdf'), {
    filename: 'Getting-Started.pdf'
  })

attachData(data, filename, options)

Attach raw data as a String, Buffer or Stream.

message.attachData('hello', 'hello.txt')

// buffer
message.attachData(new Buffer('hello'), 'hello.txt')

// stream
message.attachData(fs.createReadStream('hello.txt'), 'hello.txt')

embed(filePath, cid, options)

Embed image into HTML body using content id. Make sure the cid is unique for each image for a given email.

message.embed(Helpers.publicPath('logo.png'), 'logo')

Later inside the template, you can say

<img src="cid:logo" />

driverExtras(extras)

Pass an object of values to the current driver. The mail provider passes the object to the driver, and it is up to the driver to consume these values.

message.driverExtras({ campaign_id: 20 })

Switching connections

Mail provider allows defining multiple connections inside config/mail.js file. Connections can be for same or a different driver.

config/mail.js
{
  connection: 'smtp',

  smtp: {},

  sparkpost: {
    driver: 'sparkpost',
    apiKey: Env.get('SPARKPOST_API_KEY'),
    extras: {}
  }
}

Using the above config, you can switch to sparkpost connection using the connection method.

await Mail
  .connection('sparkpost')
  .send('view', data, (message) => {
  })

Drivers

Below sections are instructions related to specific drivers.

SES

The ses driver relies on aws-sdk. Make sure to install the dependencies from npm, since it is installed by default.

npm i aws-sdk

SparkPost

You can pass following extra options when using sparkpost as the driver.

Via config

{
  extras: {
    campaign_id: '',
    options: {}
  }
}

Check out sparkpost options attributes docs to learn more about available options.

Also, you can pass extras at runtime using the driverExtras method.

await Mail.send('view', data, (message) => {
  message.driverExtras({
    campaign_id: '',
    options: {}
  })
})

Mailgun

You can pass following extra options when using mailgun as the driver.

Via config

{
  extras: {
    'o:tag': '',
    'o:campaign': '',
    ....
  }
}

Check out mailgun docs to learn more about available options.

Also, you can pass extras at runtime using the driverExtras method.

await Mail.send('view', data, (message) => {
  message.driverExtras({
    'o:tag': '',
    'o:campaign': ''
  })
})