I recently had to convert a Rails application that I work
with from Mandrill to SendGrid. The application
was fully functional and live in production.
All of the messages sent by the system were using templates.
The steps that I took included:
1)
Create a new account at SendGrid
2)
Go to Templates -> Transactional and Create
Template
3)
I then cut and pasted each template from
Mandrill to SendGrid
a.
Mandrill was using *|variable_name|* syntax for
replacement variables and I was able to make this work with SendGrid as well.
4)
The one quirk about SendGrid that is worth
mentioning is that I had to add a <%body%> tag to each message even
though I don’t have a payload for <%body%>. I found that the easiest way
to deal with that was to delete it out, switch to code mode, paste in my
complete html and then paste the <%body%> tag as the last thing in my template. SendGrid then did some minor formatting but
left it out of my way.
5)
Each template gets an ID shown at the top of its
information on the Transactional Template Engine page in SendGrid. They look
like: 45ef9876-4321-1cd1-ab1c-d12a123a1234
6)
Go to Settings, API Keys.
a.
Click “Create API Key”.
b.
Save the giant key string that they display.
This is important because they really won’t ever show it to you again.
c.
Edit details for the key you just created and
set security for the functionality you want that key to be able to access. In my case I just set Mail Send = full
access.
7)
Over on the Rails side I create a new class for
SendGrid. Fortunately I had isolate the
email send functionality in my application to one routine so I only had to
create a new sendtemplate method.
8)
I used the sendgrid-ruby gem that is officially supported
by SendGrid. Available here: https://github.com/sendgrid/sendgrid-ruby
Here is the entire file with comments added. In general the
documentation from the gem was very clear and I had only one minor problem
leveraging the API which I’ve referenced in line.
# Begin Code
module RDSendGrid
# I use this to return a
standard result from the class no matter what I get back from the vendor
class FakeRes
attr_accessor :code
attr_accessor :body
end
class RDSendGrid
require "uri"
require 'sendgrid-ruby'
def initialize
end # initialize
##########################################################################
# audit_id: the id of my
internal record for this email
# template_id: the template
id provided by SendGrid for the template I want to send
# from_email: the address to
use as the sender’s email
# from_name: name to show instead of the address in the
recipient’s mail client
# to_email: The address to
send the message to
# to_name: The name of the
person to send the message to
# subject: the subject of the
email message
# merge_vars: an array of attribute
value pairs of replacement variables
# these get sent en-mas to the template engine and are specific to each template
#
the pairs are “name” and “content”
# bcc: provide an email
address here if I want to bcc someone on this message
##########################################################################
def sendtemplate(audit_id,
template_id, from_email, from_name, to_email, to_name, subject, merge_vars, bcc
="")
# defined in my environment
sendgridkey = Rails.configuration.sendgridkey
# This flag allows me to do
email testing without pushing the message to SendGrid
if Rails.configuration. sendmail
# This was the only part that wasn’t crystal
clear to me in the gem documentation
# See my note at the end
# Create an SMTPAPI
header and put settings into it
header =
Smtpapi::Header.new
header.add_unique_arg("rd_audit_number", audit_id)
# Create a SendGrid
recipient to add to the list
# At this time my
sendtemplate function only sends a single message but SendGrid can
# process a list of
recipients so I’ve allowed for that expansion in the future
# Create a sendgid
recipient list
recipients = []
recipient =
SendGrid::Recipient.new(to_email)
merge_vars.each do |mv|
# note that I used *||*
as variable delimiters because they were that way in mandril
recipient.add_substitution('*|' + mv["name"] + '|*',
mv["content"])
end
# Put our one and only
recipient into the array of recpients
recipients <<
recipient
# Create a sendgrid
template
puts(template_id)
template =
SendGrid::Template.new(template_id)
# Create a client
# Note that because I don’t have a body to send I’ve made html and text blank
# However, an empty
string wouldn’t work for me so I used one space
# Adding the smtpapi
header here, this was the second half of the unclear part for me
client =
SendGrid::Client.new(api_key:
sendgridkey)
mail_defaults = {
smtpapi: header,
from: from_email,
from_name: from_name,
to: to_email,
to_name: to_name,
bcc: bcc,
html: ' ',
text: ' ',
subject: subject
}
# Create a new
TemplateMailer
mailer =
SendGrid::TemplateMailer.new(client, template, recipients)
# send it
lres =
mailer.mail(mail_defaults)
# return the result
res = FakeRes.new
res.code = lres.code
res.body =
lres.body["message"]
else
#
Rails.configuration.sendmail was set to false so fake a success return
res = FakeRes.new
res.code =
"200"
res.body =
"success"
end
return res
end #sendtemplate
end
end
# End code
Now about my notes on the SMTPAPI Header. In order to get email events
back from SendGrid, and update my email history with the data, I needed to send
a unique ID for each message to them. The documentation is actually quite clear
on how to do that and how to create an api header for that purpose. The only
thing that was unclear (to me personally) was how exactly to associate that
header with the TemplateMailer call. In the end, it was just a question of
creating the header -- header = Smtpapi::Header.new --, populating it -- header.add_unique_arg("rd_audit_number",
audit_id) -- and then assigning the header to the mail_deafulats -- mail_defaults
= { smtpapi: header … --
So, once again I’ve managed to do something that thousands
have done before me and yet find the need to share it with others anyway. Next time I’ll share how I processed the mail
event updates from SendGrid.
This comment has been removed by a blog administrator.
ReplyDeleteThank you.Well it was nice post and very helpful information on Ruby on Rails Online Course Bangalore
ReplyDelete