Wednesday, July 28, 2010

Get Delivery Status from email sent using SendGrid API

Sometime when you send email to somebody, you want to know that the email sent or not right?

Sometime ago I use SendGrid for send email.

When using SendGrid for sending email, you can also add some custom variable that sent to your Event Listener file. So when receiver open that email or receive that email, you can have some variable that sent from that email to your Event Listener file. From that we can know the delivery status from email sent.

Let go to the practice.

First we need SendGrid account. You can register free in http://sendgrid.com/pricing.html.

When you already registered, then add some configuration to your environment using your SendGrid Username and Password.


ActionMailer::Base.smtp_settings = {
:address => "smtp.sendgrid.net",
:port => '25',
:domain => [your_domain],
:authentication => :plain,
:user_name => [your_sendgrid_username],
:password => [your_sendgrid_password]
}


Example


ActionMailer::Base.smtp_settings = {
:address => "smtp.sendgrid.net",
:port => '25',
:domain => 'example.com',
:authentication => :plain,
:user_name => 'username',
:password => 'password'
}


Now we need configure the email header. We need to download smtpapiheader.rb from http://wiki.sendgrid.com/doku.php?id=smtpapiheader.rb and save it to your model's folder.
On your mailer model.


class UserMailer < ActionMailer::Base

require 'smtpapiheader.rb'

def email(email)
setup_email(email)
@reply_to = "#{email.user.first_name} #{email.user.last_name} <#{email.user.email}>"
@from = "#{email.user.first_name} #{email.user.last_name} "
@subject = "A letter from #{email.user.first_name}"
content_type "text/html"
end

protected
def setup_email(email)
hdr = SmtpApiHeader.new()
receiver = email.email
hdr.addTo(receiver)
hdr.setUniqueArgs({:key => email.key})

header = hdr.asJSON()

@recipients = "#{email.email}"
@sent_on = Time.now
@headers["X-SMTPAPI"] = header
end

end


Now we need to create Event Listener file.
create some controller on your rails application.
I use email controller for this example.


class EmailController < ApplicationController

def receive_email_notification
if !params.blank? and !params[:key].blank? and !params[:email].blank? and !params[:event].blank?
email = Email.find_by_email_and_key(params[:email], params[:key])
if email
case params[:event]
when "open"
#add some logic when the listener receive notification
email.update_attribute(:send_status, params[:event])
when "click"
email.update_attribute(:send_status, params[:event])
when "unsubscribe"
email.update_attribute(:send_status, params[:event])
when "bounce"
email.update_attribute(:send_status, params[:event])
when "spamreport"
email.update_attribute(:send_status, params[:event])
end
end
@email = email
end
redirect_to :root unless email
end

end


Now add some line to your config/routes.rb


map.resources :emails,:collection => {:receive_email_notification => :post }


Now we need SendGrid to know the url our Event Listener. We need to log on to SendGrid.
On Home -> Developers -> Post Event URL (http://sendgrid.com/developer/postEventUrl).
On that page you can submit your url.
Example : http://example.com/emails/receive_email_notification

That's it. For more info about SendGrid http://sendgrid.com, for SendGrid API http://wiki.sendgrid.com/.

2 comments:

  1. Nice post.

    Anyway I think you don't need that case statement on EmailController instead email.update_attribute(:send_status, params[:event]) should sufficient.

    Let me know what you think?

    ReplyDelete
  2. Thanks for your comment Mr. William :) It's just for example if some status run different code, that's it :)

    ReplyDelete