Rails + MailGun API: Send emails without ActionMailer

Sending emails with Ruby on Rails is great. The ActionMailer class makes it easy to link your application up to any SMTP service to send emails - but sometimes it's not what your application needs. In this tutorial I'll show you an alternative (and faster) way of sending emails out by avoiding ActionMailer and the SMTP protocol altogether.

You'll need a free account at MailGun to take full advantage of this tutorial. You can signup here: https://mailgun.com/ (no credit card needed) and at the time of this tutorial you can send out 10,000 emails per month before paying.

If you'd like to skip over the tutorial - I've provided the final code below. If you're interested in how it's done - keep reading!

class Emailer < ActiveRecord::Base  
  def self.transaction(email_template,subject,email) 

    # get email template
    template_file = File.join(Rails.root, 'emails', 'template.html')
    template_contents = File.read(template_file)

    # get email file 
    email_file = File.join(Rails.root, 'emails', email_template + '.html')
    email_contents = File.read(email_file)

    #replace email content with email
    template_contents.sub! '*|EMAILCONTENTS|*', email_contents

    # save var as email_contents
    email_contents = template_contents

    # send out email (via mailgun)
    RestClient.post("https://api:[email protected]/v3/mail.zachalam.com/messages",
    :from => "zach alam <[email protected]>",
    :to => email,
    :subject => subject,
    :html => email_contents)      
  end
end # end class  

Before we can go into any of the code we'll need to do a couple things first.
First we'll need to create a new Model, in this case we called ours "Emailer". From the command line you can run the following rails command:

rails g model Emailer  

Next we need to obtain our MailGun access point. This is a URL that can be found in your dashboard at http://mailgun.com. Here's ours:

https://api:[email protected]/v3/mail.zachalam.com/messages  

Then we need to create folder somewhere within your rails project titled "emails". In our example - we did this in the rails project root directory. And then create a template file (to hold our email template) and a welcome file (to hold our sample email) in our new directory.

mkdir emails  
cd emails  
touch template.html  
touch welcome.html  

Within our "template.html" we add the following contents.

<html>  
<head></head>  
<body style="background-color:#eee; padding:3em;">  
<div style="background-color:white; text-align:center;">  
<!-- EMAIL CONTENTS HERE -->  
*|EMAILCONTENTS|*
<!-- EMAIL CONTENTS HERE -->  
</div><!-- end div -->  
</body>  
</html>  

And within our "welcome.html" we add the following contents.

<h3>Hello There</h3>  
This is a sample email sent from our rails application via the mailgun API.  
Thanks for signing up!  

Now that we have our structure setup, we can go back to the model we created in the first step. Open up your model and add the following contents. This code is fairly straightforward. Here's how it works:

1) We get the contents of the template file.
2) We get the contents of the email file.
3) We replace *|EMAILCONTENTS|* in the template file with our email file - to make one final email file.
4) Finally we use the RestClient class to make a POST request to our mailgun API access point with all the necessary email parameters. I would suggest implementing the mailgun access point as an Environment Variable - however for this tutorial I have implemented it in the codebase.

class Emailer < ActiveRecord::Base  
  def self.transaction(email_template,subject,email) 

    # get email template
    template_file = File.join(Rails.root, 'emails', 'template.html')
    template_contents = File.read(template_file)

    # get email file 
    email_file = File.join(Rails.root, 'emails', email_template + '.html')
    email_contents = File.read(email_file)

    #replace email content with email
    template_contents.sub! '*|EMAILCONTENTS|*', email_contents

    # save var as email_contents
    email_contents = template_contents

    # send out email (via mailgun)
    RestClient.post("https://api:[email protected]/v3/mail.zachalam.com/messages",
    :from => "zach alam <[email protected]>",
    :to => email,
    :subject => subject,
    :html => email_contents)      
  end
end # end class  

We can now send an email to anyone throughout our rails application simply by writing the following code:

Emailer::transaction("welcome","Thanks for signing up!","[email protected]")  

And that's that! Now we can send emails extremely fast. According to a cool blog post written by Sergio Costa (http://www.sergiocosta.me/sending-emails-using-sendgrid-smtp-or-web-api/) his tests resulted in a 3.8x increase in mail delivery speed when using API over SMTP.