ar_mailer

A two-phase delivery agent for ActionMailer

GitHub Project:

rubyforge.org/projects/seattlerb

Documentation:

seattlerb.rubyforge.org/ar_mailer/

About ar_mailer

Even delivering email to the local machine may take too long when you have to send hundreds of messages. ar_mailer allows you to store messages into the database for later delivery by a separate process, ar_sendmail.

About this fork

GitHub Project:

github.com/artemv/ar_mailer

We didn’t really needed ar_mailer - instead we wanted to digest error email notifications sent by ExceptionNotifier. Sometimes Prod can face some issue that make it error like hell. There’s no need to receive these errors one by one - we wanted them to be combined into digest periodically - in our case SMTP provider’s tariff plan limits outgoing messages number. So we used adzap-ar_mailer for error messages buffering and then made it combine them to digests based on To field. Also we already had BackgrounDRB so we didn’t need separate ar_sendmail process. So, what does this fork do out of the box:

  • ARMailer messages don’t get send until they are combined into digests

  • all messages to same addressee are combined into one digest email

  • it only supports text/plain messages

  • if the digest mail is too big it gets truncated, and full digest is dumped to a file on server; truncated digest will tell about it

  • the sending itself can be triggered by method call, so now you have options to use ar_sendmail process or smth else, e.g. BackgrounDRB job

  • you can specify :smtp_settings to be used when sending digests: we needed it to be other than default ActionMailer::Base.smtp_settings

Usage example:

ActionMailer::ARSendmail.digest_error_emails :dump_path => '/var/log/myapp',
                                             :subj_prefix => ExceptionNotifier.email_prefix,
                                             :smtp_settings =>   {:address =>     "localhost",
                                                  :port =>        25,
                                                  :domain =>      'my_domain.com',
                                                  :tls =>          false,}

Adzap’s fork is great because you can use ar_mailer for just one class with it - just what we needed. So we decided to opensource our tweaks in hope that it will be helpful for someone. The code is quite limited but it’s fine for our needs, and if you need more you have smth to start with. E.g. it could be improved to support text/html messages or to make certain classes bypass digesting when sending emails with ARMailer.

The fork is contributed by Your Net Works, Inc.

Installing ar_mailer (forked)

Before installing you will need to make sure the original gem is uninstalled as they can’t coexist:

$ sudo gem uninstall ar_mailer

Install the gem from Gemcutter gems server:

First, if you haven’t already:

$ sudo gem sources -a http://gemcutter.org

Then

$ sudo gem install ynw-ar_mailer

For Rails >= 2.1, in your environment.rb:

config.gem "ynw-ar_mailer", :lib => 'action_mailer/ar_mailer', :source => 'http://gemcutter.org'

For Rails 2.0, in an initializer file:

require 'action_mailer/ar_mailer'

Usage

Go to your Rails project:

$ cd your_rails_project

Create the migration and model:

This shows the options which are only the model name, which defaults to Email

./script/generate ar_mailer -h

Then run with defaults

./script/generate ar_mailer

Or specify a custom model name

./script/generate ar_mailer Newsletter

See Alternate Mail Storage if you use a custom model name

In your mailer class methods you must be sure to set the From address for your emails. Something like:

def list_send(recipient)
  from '[email protected]'
  # ...

Edit config/environments/production.rb and set the delivery method:

config.action_mailer.delivery_method = :activerecord

Or if you need to, you can set each mailer class delivery method individually:

class MyMailer < ActionMailer::Base
  self.delivery_method = :activerecord
end

This can be useful when using plugins like ExceptionNotification. Where it might be foolish to tie the sending of the email alert to the database when the database might be causing the exception being raised. In this instance you could override ExceptionNofitier delivery method to be smtp or set the other mailer classes to use ARMailer explicitly.

Then to run it:

$ ar_sendmail

You can also run it from cron with -o, or as a daemon with -d.

See ar_sendmail -h for full details.

Alternate Mail Storage

By default ar_mailer assumes you are using an ActiveRecord model called Email to store the emails created before sending. If you want to change this you alter it in an intializer like so:

ActionMailer::Base.email_class = Newsletter

A Word on TLS

If you are using Ruby >= 1.8.7, TLS will be enabled automatically if your SMTP server supports it. If you do not want it to automatically enabled then set the :tls option to false in your smtp_settings.

If you are on Ruby <= 1.8.6, then the TLS patch included in this plugin will be loaded, so you don’t need another TLS plugin to add the capability. This patch allows you to explicit set if the server supports TLS by setting the :tls option to true in your smtp_settings.

Help

See ar_sendmail -h for options to ar_sendmail.

NOTE: You may need to delete an smtp_tls.rb file if you have one lying around. ar_mailer supplies it own.

Run as a service (init.d/rc.d scripts)

For Linux both script and demo config files are in share/linux. See ar_sendmail.conf for setting up your config. Copy the ar_sendmail file to /etc/init.d/ and make it executable. Then for Debian based distros run ‘sudo update-rc.d ar_sendmail defaults’ and it should work. Make sure you have the config file /etc/ar_sendmail.conf in place before starting.

For FreeBSD or NetBSD script is share/bsd/ar_sendmail. This is old and does not support the config file unless someone wants to submit a patch.