Writing your own delivery method in Rails (4.+)
Imagine, you got your rails server and you need to send out a bunch of mails to your recipients. no big deal, but SMTP is just very slow when compared with things like simple HTTP API calls.
I set out a few days to write my own delivery method, but found online sources somewhat lacking, outdated or completely skipping this part of sending mails in rails. So lets start making a simple mail_delivery method that outputs the mail to a file in your project home.
You can change the postman step in this tutorial to match your API, etc. instead.
First step is to make a custom module / class that will handle our mails.
make a new file in your rails project: lib/postman.rb
.
It should have content like this:
module MailToTxtSender
class Postman
attr_accessor :settings
def initialize(values)
self.settings = {}.merge!(values)
end
def deliver!(mail)
check_delivery_params(mail)
# IN REAL LIFE SITUATIONS NEVER USE THIS KIND OF COMMAND.
# SOMEONE COULD DO "Someone; rm -rf /" IN A NAMEFIELD AND WIPE YOUR HARD DISK
system("touch #{mail.Message-ID}.txt")
system("echo 'NEW EMAIL' >> #{mail.Message-ID}.txt")
system("echo 'from: #{mail.From}' >> #{mail.Message-ID}.txt")
system("echo 'to: #{mail.To}' >> #{mail.Message-ID}.txt")
system("echo 'subject: #{mail.subject}' >> #{mail.Message-ID}.txt")
system("echo 'encoded: #{mail.encoded}' >> #{mail.Message-ID}.txt")
end
private
def check_delivery_params(mail)
if mail.From.nil?
raise ArgumentError.new('A from address is required when sending an email')
end
end
end
end
what is happening here:
- The class allows to have an attribute called
settings
. here all the standard settings or mail specific settings can be parsed in, everything you would set on the action_mailer settings in your production environment. You can set defaults in the mailer between the{}
in initialize - The
deliver!(mail)
method is run when a new mail is going to be send out. themail
variable here contains the body and parameters of an individual mail. If you want to use an API to send your emails, this is the place to put the request.
Best practices: when doing validations raise Argument errors when an email is not correctly build. this gives you the best feedback.
make a new file called config/initializers/mail_sender.rb
and add the following content
require 'postman'
ActionMailer::Base.add_delivery_method :mail_to_txt, MailToTxtSender::Postman
Save the file and boot your rails console with rails c
.
When running the command ActionMailer::Base.delivery_methods
you should see:
{:smtp=>Mail::SMTP, :file=>Mail::FileDelivery, :sendmail=>Mail::Sendmail, :test=>Mail::TestMailer, :mail_to_txt=>MailToTxtSender::Postman}
open config/environments/development.rb
and add or replace the following line:
config.action_mailer.delivery_method = :mail_to_txt
that’s it, now send yourself an awesome mail using one of your existing mailers or check http://guides.rubyonrails.org/action_mailer_basics.html to create one quickly.