Make sending mail great again.


For most projects, you want to know when you mailed a user, and what you mailed to them. Additionally, you don't want to have to do a push every time you want to change something in your mailer.


Add this line to your application's Gemfile:

gem 'mailtime'


$ bundle

And copy over the initializer and migration:

$ rails g mailtime:install

Migrate it.

$ rake db:migrate


Using Mailtime is simple. Just add acts_as_mailtime_loggable to each class you want to associate a Mailtime::MailLog to.

acts_as_mailtime_loggable options

class User < ActiveRecord::Base

will tell Mailtime::MailLog to find an instance variable of class User where attribute #email (email is default) that matches an ActionMailer#mail's #to (again, default) attribute.

Need to customize? Sure.

class User < ActiveRecord::Base
  acts_as_mailtime_loggable :email_address, :fields => [:to, :cc, :bcc] 

will tell Mailtime::MailLog to find an instance variable of class User where attribute email_address matches an ActionMailer#mail's #to, #cc, or #bcc attribute.


The default initializer that's installed when you run rails g mailtime:install is self-documented.

How it works

Mailtime hooks into ActionMailer#mail. It injects a some methods in order to extract metadata, such as the mailer class (like UserMailer) and the action (like password_reset). Once it knows what it's working with, it looks to the database for the corresponding MailTemplate. If it finds the MailTemplate, it renders the template against the mail and merges the result with some of the mail's attributes (like body).

It then logs the mail and sends it away.

Mailtime aims to be highly flexible and tries not to dictate your setup. For example, you can render a MailTemplate's contents however you want. Just specify in the initializer what renderer you want to use. And because Mailtime simply hooks into ActionMailer, it doesn't care how you're delivering mail (via config.action_mailer.delivery_method).

Additional Setup

Mailtime doesn't ship with views. You want views.


You'll want somewhere to view your logs and manage your templates. Basic scaffolding will do just fine.

def index
  @mail_templates = Mailtime::MailTemplate.all

For MailTemplate, you'll want to permit the params klass, action, subject, mail_layout_id, format, extension, and content

Here's an example using SimpleForm:

  simple_form_for @mail_template do |f| 
    f.input :action, :as => :select, :collection => MailTemplate.mail_actions, :onchange => '$("#mail_template_klass").val($("#mail_template_action option:selected").closest("optgroup").attr("label"));'
    f.input :klass, :as => :hidden
    f.input :subject
    f.input :mail_layout
    f.input :format, :as => :select, :collection => Mailtime.configuration.valid_formats
    f.input :extension, :as => :select, :collection => Mailtime.configuration.valid_extensions
    f.input :content, :as => :text

MailTemplate.mail_actions is an array of mailer classes and their public instance methods, e.g. ['UserMailer' => ['password_reset_email']]

Note: If subject is present, it will override the mail's subject.


A MailLog stores the MailTemplate, action (from the mailer), klass (from the mailer), field (such as to, cc, bcc), loggable (from acts_as_mailtime_loggable), headers (from ActionMailer#mail), and scope (the instance variables defined in the action)

You'll probably want somewhere to look at these.


Has a name, content, format, and extension. format should be one of Mailtime.configuration.valid_formats, and extension should be one of Mailtime.configuration.valid_extensions


  • Tests. Like, way better tests.
  • Attachments
  • Support MySQL (uses jsonb as datatypes for storing things right now)

Maybe todo

  • Dump for production?
  • Versioning for templates?
  • A hell of a lot better rake import task.


Bug reports and pull requests are welcome on GitHub at