← Blog • Published: Saturday, 21 Oct 2023

ActionMailer console script for bulk-testing mailers

Testing individual ActionMailer mailers is a pain! You have to test them one by one, typing MyMailer.deliver_now! into the Rails console over and over.

To help, I've put together a console script (technically a rake task) to bulk send mailers for testing. I use this script to test emails for RailsNotes UI and it's super handy!

To make it easier for you to test your mailers too, I'm sharing the script in this article, and walking you through how to use it in your Ruby on Rails app.

Here's a handy ActionMailer console script for sending test emails locally (packaged up as a rake task).

I use this script when I'm building mailer templates for RailsNotes UI, for two main things —

  1. Bulk Testing — The main use for this script; I add mailers into the mailers array, then automatically trigger each mailer method. This lets me send 20-30 emails at a time to myself for testing.
  2. Single Mailer Testing — Sometimes I might only test a single mailer! In that case, I set the mailers array to only include a single mailer (the one I'm interested in).

Inbox testing ActionMailer templates is annoying to do one by one. You end up typing commands like PrimaryActionMailer.basic.deliver_now again and again into the Rails console (or with rails runner). To help, I've put together a handy console script.

ActionMailer console testing script

To make testing ActionMailer mailers easier, I wrote this script. This rake task lets you call all the methods on the ActionMailer mailers you provide. It uses #public_instance_methods to call each mailer method, for each provided mailer.

# lib/tasks/send_emails.rake
#
namespace :mailers do
  desc 'Send emails using all methods of an array of mailers'
  task :send_emails, [:email] => :environment do |t, args|

    # set a default email address to deliver to
    args.with_defaults(email: '[email protected]')

    # Override the delivery method to use a live ESP
    ActionMailer::Base.delivery_method = :resend

    # Array of mailers we want to test
    mailers = [
      ExampleMailer,
      PrimaryActionMailer,
      ...
    ]

    # send each email from each mailer
    mailers.each do |mailer|
      # iterate over each mailer method and call it
      mailer.public_instance_methods(false).each do |method|
        mailer.send(method, to: args[:email]).deliver_now!
        puts "sent #{mailer.name} (#{method})"
      end
    end
  end
end

A couple of things to note —

  • This script overrides ActionMailer::Base.delivery_method to use Resend, a production email service. My default delivery method is a local SMTP server for testing. However, this script is for sending live emails, so we override the default method to use a proper ESP. Adjust this to use your own ESP.
  • All my ActionMailer methods take a to: argument, like this —
  def basic(to: "Harrison")
    mail(to:, subject: "Basic Invoice")
  end

This script sets a default value for to:, defaulting to a test address. You should adjust this! Set it to your own email address.

I run the rake task similar to a console script, like this —

# In your console/terminal
RAILS_ENV=production rake mailers:send_emails

Calling RAILS_ENV=production is really important! This sends your emails with the production configuration for your Rails app, which can help you catch bugs and Zeitwerk errors. Without this, Rails will send emails using your development configuration, which can let bugs/errors go unnoticed until you try to deploy your emails to production.

Passing a different email address to the script

This rake task also accepts a value for args[:email], to override the default value for email. We can pass that value to the script when we run it from the console, like so —

# In your console/terminal
RAILS_ENV=production rake mailers:send_emails\['[email protected]'\]

Note: in a ZSH shell, we have to escape square brackets like \[. In other shells, you should be able to remove the backslashes.

This can be handy for sending test emails to a 3rd party service (like Litmus) for testing. Rather than editing the script, you can just pass in a different email address.

Conclusion

Thanks for reading, I hope you found this useful.

If you send a lot of emails with Rails and ActionMailer, you'll probably love my ActionMailer email templates and components.