A journey on sending emails - the Mail gem
Yesterday I took a look at sending emails using ActionMailer. Today I want to go through the same exercise, but this time we will use the Mail gem. ActionMailer uses Mail internally; you will see some similarity in the code we wrote in yesterday’s post.
Some history on the Mail library. Mail was designed to handle email generation, parsing and sending in the Ruby way. Mail is from the same author that gave us TMail. Based on his experience on TMail he built Mail from the ground up to make generating, sending and parsing emails a no-brainer. Mail has been designed to work with Ruby > 1.9; it works with Ruby 1.8.x but it’s not as easy.
Awesome thanks for the history lesson Deon, let’s get down to business. Go ahead and create a new Ruby file creatively called mailer2.rb, you will need two requires. In no particular order, you will need to require ‘mail’ and ‘erb’. Why do you need ERB you might ask, we are going to use a template for our email body and ERB is going to do the heavy lifting for us. If you didn’t know you can use ERB for your templating needs, how awesome is that? Also at this point we can also declare our class called Mailer but before we do that let’s just install the Mail gem:
gem install mail
Just like the code for ActionMailer there are certain properties we must set in order to send emails successfully. This time around we are going to set these properties in our initialize method, with the addition of this code our file should look like so:
Next thing we are going to do is write the code that will set the variables needed in our template, create our Mail object, set the necessary properties on our mail object and do the sending, sounds like quite a bit of work but it isn’t really.
The awesome_email method is expecting a details hash. The details Hash will contain the addresses for the to and from addresses, the subject and the path to the template for the body of our email.
The code is very straightforward until this line:
b = binding
Binding captures the execution context at this point of the code, and this is crucial as without the context your variables will not be visible to ERB when generating the email body for your message. In hindsight, a better name for the b variable might have been ‘context’ but it’s not such a big issue.
The next interesting part of this method is how we create the body of our email. Here we are using ERB, which works by building a chunk of Ruby code that will output the completed template when run. The whole body of our email is magically created within a single line of code:
mail.body = ERB.new(File.read(template_path)).result(b)
The template for our email looks as follows:
Hello this email has been sent to <%= @to %> from <%= @from %>
The last line of code might look very familiar, it is the same code we used in the ActionMailer implementation to do the actually sending of our code.
We are now in a good place to send an actual email. We are going to create a Hash with the necessary setting for Mail, what you will notice again is how similar it is compared to the code for ActionMailer, and again that is because internally ActionMailer uses Mail.
With our options in place, we can now create a new Mailer object and pass in our options. Next we require the details Hash that will be necessary for the email, in our case we have an email template in the mailer folder called ‘awesome_email.html.erb’ you could have called this template whatever you wanted ERB would not have cared. We can now call the ‘awesome_email’ method passing in our details Hash to send our email. Here is the full code listing:
Compared to the first attempt at sending email this implementation hides us from the complexity of sending an email when using the Standard Library. If we compare the ActionMailer implementation to this, it seems we are in a better place with this code. We are abstracted away from the Standard Library so no matter if we need to send an email via SMTP or POP3 we just flip a flag and change a few settings. This implementation doesn’t pull all of the dependencies that ActionMailer requires, and we still get templating via ERB (also noting we could have used ERB in previous implementations without an issue).
ActionMailer is perfect for your Rails applications, and you should use Mail in your other Ruby applications. There are still a few more mail sending gems to go so right now I am not going to declare a winner.