Sending email on behalf of users – Part 2 – Patching ActionMailer

Our application was developed using Ruby on Rails, and leveraged RoR’s ActionMailer class to send emails. If you’re not using Rails, you can easily ignore the following.

Unfortunately, when using rails, perform_deliver_smtp of ActionMailer simply use mail.from as the envelope-from when setting the SMTP header. As mentioned earlier, we would like to take into consideration mail.sender if it exists. So I had to patch up the ActionMailer base class to specify the envelope-from as well as the Message sender header:

Once these changes were made, and I restarted our mongrel instance, I was able to set both the message and envelope sender.

Here’s the diff file of the changes to the base class that were needed:

Index: lib/action_mailer/base.rb

===================================================================

— lib/action_mailer/base.rb (revision 6287)

+++ lib/action_mailer/base.rb (working copy)

@@ -36,6 +36,7 @@

# * from – Who the email you are sending is from. Sets the From: header.

# * cc – Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the Cc: header.

# * bcc – Takes one or more email address. These addresses will receive a blind carbon copy of your email. Sets the Bcc header.

+ # * sender – Takes just one email address. This address will be used to envelope-from of SMTP and appear in Sender: header.

# * sent_on – The date on which the message was sent. If not set, the header wil be set by the delivery agent.

# * content_type – Specify the content type of the message. Defaults to text/plain.

# * headers – Specify additional headers to be set for the message, e.g. headers 'X-Mail-Count' => 107370.

@@ -315,6 +316,9 @@

# header will be set by the delivery agent.

adv_attr_accessor :sent_on

+ # Specify the Sender address for the message

+ adv_attr_accessor :sender

+

# Specify the subject of the message.

adv_attr_accessor :subject

@@ -513,6 +517,7 @@

m.to, m.from = quote_any_address_if_necessary(charset, recipients, from)

m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil?

m.cc = quote_address_if_necessary(cc, charset) unless cc.nil?

+ m.sender = sender unless sender.nil?

m.mime_version = mime_version unless mime_version.nil?

m.date = sent_on.to_time rescue sent_on if sent_on

@@ -548,16 +553,19 @@

def perform_delivery_smtp(mail)

destinations = mail.destinations

+ sender = mail.sender(nil) || mail.from

mail.ready_to_send

Net::SMTP.start(smtp_settings[:address], smtp_settings[:port], smtp_settings[:domain],

smtp_settings[:user_name], smtp_settings[:password], smtp_settings[:authentication]) do |smtp|

smtp.sendmail(mail.encoded, mail.from, destinations)

+ smtp.sendmail(mail.encoded, sender, destinations)

end

end

def perform_delivery_sendmail(mail)

IO.popen(“#{sendmail_settings[:location]} #{sendmail_settings[:arguments]}”,”w+”) do |sm|

+ arguments = sendmail_settings[:arguments].dup

+ arguments += ” -f#{mail.sender(nil)}” if mail.sender(nil)

+ IO.popen(“#{sendmail_settings[:location]} #{arguments}”,”w+”) do |sm|

sm.print(mail.encoded.gsub(/\r/, ”))

sm.flush

end

Sending email on behalf of users – Part 1

Before delving into the details of sending email on behalf of users, I thought I’d provide a bit of background information.

For simplicities sake, I’ll just scratch the surface when describing the headers of interest when sending messages out on behalf of users of your application. In my next posts, further description of these headers will be provided as needed.

Envelope sender – The envelope sender (return-to) address is, for the most part hidden from the user. This address receives bounces, and is typically, the address used for Sender Policy Framework (SPF) lookups, as well as domain key records.

Message sender – The message sender is also hidden from users more often than not. As I’ll discuss later, SenderID will generally use the Sender message header to authenticate the message. MUA’s such as hotmail and outlook (and I recon any other SenderID/Microsoft supported agent) expose the sender to the user. If you’ve ever received a message in outlook where you see something like “From John on behalf of Jane,” you’re seeing the effect of a Sender header. Ie. An application or mailing list has sent mail on behalf of Jane; so the message sender = John and the message from = Jane.

Message from – The message from is what is most often exposed to the user receiving the message. Surprisingly, although this header is what is exposed to an end user, it’s simple to impersonate. I quote from one of the users in the thread:

It is therefore, our goal to set the following headers in an effort to have our users receive email from users of our application as opposed to our application itself.

Envelope sender: invites@ourapplication.com

Message sender: invites@ourapplication.com

Message from: user@theiractualdomain.com

If we successfully set these headers, SPF checks will pass (assuming we create SPF records for ourapplication.com), SenderID checks will pass (again assuming we create SPF records), and users will receive invitations from actual users as opposed to our application.

As I found out, setting these headers, and having email land in the inbox of users was easier said than done. I’ll start to describe the steps needed to accomplish setting these headers in my following