Skip to content

Instantly share code, notes, and snippets.

@HendrikPetertje
Last active February 13, 2023 22:59
Show Gist options
  • Save HendrikPetertje/71c6cb16b66ad900e9b6c4c41ebac94e to your computer and use it in GitHub Desktop.
Save HendrikPetertje/71c6cb16b66ad900e9b6c4c41ebac94e to your computer and use it in GitHub Desktop.
How to Make your own delivery methods in rails 4.+

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.

1. Creating a custom method to send mails.

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. the mail 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.

2. telling rails there is a new ActionMailer delivery method

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}  

3. add your brand new mail delivery method to your working env.

open config/environments/development.rb and add or replace the following line:

config.action_mailer.delivery_method = :mail_to_txt  

4. Send yourself an email

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment