V1.3: Delivery


Multipart Delivery

By default a mailer delivers a multipart email, that has a HTML and a text part. This is the reason why the generator creates two templates.

To render both the templates and deliver them as a multipart message, we simply do:

Mailers::Welcome.deliver

Hanami mailers are flexible enough to adapt to several scenarios.

Single Part Delivery

Let’s say in our application users can opt for HTML or textual emails. According to this configuration, we want to selectively send only the wanted format:

Mailers::Welcome.deliver(format: :html)
# or
Mailers::Welcome.deliver(format: :txt)

By using only one format, it will render and deliver only the specified template.

Remove Templates

If in our application, we want only to deliver HTML templates, we can safely remove textual templates (.txt extension) and every time we will do Mailers::Welcome.deliver it will only send the HTML message.

The same principle applies if we want only to send textual emails, just remove HTML templates (.html extension).

At the delivery time, a mailer MUST have at least one template available.

Built-in Strategies

In order to specify the gateway to use for our email messages, we can use delivery configuration.

It accepts a symbol that is translated into a delivery strategy:

  • Exim (:exim)
  • Sendmail (:sendmail)
  • SMTP (:smtp, for local SMTP installations)
  • SMTP Connection (:smtp_connection, via Net::SMTP - for remote SMTP installations)
  • Logger (:logger, prints email details to the console - useful in development)
  • Test (:test, for testing purposes)

It defaults to SMTP (:smtp) for production environment, while :test is automatically set for development and test.

The second optional argument is a set of arbitrary configurations that we want to pass to the configuration:

# config/environment.rb
# ...
Hanami.configure do
  # ...

  mailer do
    root Hanami.root.join("lib", "bookshelf", "mailers")

    # See https://guides.hanamirb.org/mailers/delivery
    delivery :test
  end

  # ...

  environment :production do
    # ...

    mailer do
      delivery :smtp, address: ENV['SMTP_HOST'], port: ENV['SMTP_PORT']
    end
  end
end

For advanced configurations, please have a look at mail gem by Mikel Lindsaar. At the low level, Hanami::Mailer uses this rock solid library.

Because Hanami uses mail gem, which is a de facto standard for Ruby, we can have interoperability with all the most common gateways vendors. Sendgrid, Mandrill, Postmark and Mailgun just to name a few, use SMTP and have detailed setup guides.

Custom Strategy

If we need to a custom delivery workflow, we can pass a class to the configuration.

Here’s an example on how to use Mandrill API to deliver emails.

# config/environment.rb
# ...
require 'lib/mailers/mandrill_delivery_method'

Hanami.configure do
  # ...

  environment :production do
    # ...

    mailer do
      delivery MandrillDeliveryMethod, api_key: ENV['MANDRILL_API_KEY']
    end
  end
end

The object MUST respond to #initialize(options = {}) and to #deliver!(mail), where mail is an instance of Mail::Message.

class MandrillDeliveryMethod
  def initialize(options)
    @api_key = options.fetch(:api_key)
  end

  def deliver!(mail)
    send convert(mail)
  end

  private

  def send(message)
    gateway.messages.send message
  end

  def convert(mail)
    # Convert a Mail::Message instance into a Hash structure
    # See https://mandrillapp.com/api/docs/messages.ruby.html
  end

  def gateway
    Mandrill::API.new(@api_key)
  end
end

Please notice that this is only an example that illustrates custom policies. If you want to use Mandrill, please prefer SMTP over this strategy.