← 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 —
- 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. - 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.