How to test email headers using RSpec
Asked Answered
R

2

19

I'm using SendGrid's SMTP API in my Rails application to send out emails. However, I'm running into troubles testing the email header ("X-SMTPAPI") using RSpec.

Here's what the email looks like (retrieving from ActionMailer::Base.deliveries):

#<Mail::Message:2189335760, Multipart: false, Headers: 
<Date: Tue, 20 Dec 2011 16:14:25 +0800>, 
<From: "Acme Inc" <[email protected]>>, 
<To: [email protected]>, 
<Message-ID: <[email protected]>>, 
<Subject: Your Acme order>, <Mime-Version: 1.0>, 
<Content-Type: text/plain>, <Content-Transfer-Encoding: 7bit>, 
<X-SMTPAPI: {"sub":{"|last_name|":[Foo],"|first_name|":[Bar]},"to":["[email protected]"]}>> 

Here's my spec code (which failed):

ActionMailer::Base.deliveries.last.to.should include("[email protected]")

I've also tried various method to retrieve the header("X-SMTPAPI") and didn't work either:

mail = ActionMailer::Base.deliveries.last
mail.headers("X-SMTPAPI") #NoMethodError: undefined method `each_pair' for "X-SMTPAPI":String

Help?

Update (answer)

Turns out, I can do this to retrieve the value of the email header:

mail.header['X-SMTPAPI'].value

However, the returned value is in JSON format. Then, all I need to do is to decode it:

sendgrid_header = ActiveSupport::JSON.decode(mail.header['X-SMTPAPI'].value)

which returns a hash, where I can do this:

sendgrid_header["to"] 

to retrieve the array of email addresses.

Rosewood answered 20/12, 2011 at 8:25 Comment(0)
K
12

The email_spec gem has a bunch of matchers that make this easier, you can do stuff like

mail.should have_header('X-SMTPAPI', some_value)
mail.should deliver_to('[email protected]')

And perusing the source to that gem should point you in the right direction if you don't want to use it e.g.

mail.to.addrs

returns you the email addresses (as opposed to stuff like 'Bob ')

and

mail.header['foo']

gets you the field for the foo header (depending on what you're checking you may want to call to_s on it to get the actual field value)

Kp answered 20/12, 2011 at 10:14 Comment(1)
Thanks. I've checked out email_spec gem. The "deliver_to" matcher is similar to the "to" matcher (which returns "[email protected]" instead of "[email protected]") and the "have_header" matcher simply returns the full header. Anyway, I've found out a solution to this and will post it up now. Thanks!Rosewood
K
0

Repeating some of the other advice here, in more modern rspec syntax:

RSpec.describe ImportFile::Mailer do
  describe '.file_error' do
    let(:mail) { described_class.file_error('daily.csv', 'missing header') }

    it { expect(mail.subject).to eq("Import error: missing header in daily.csv") }
    it { expect(mail.header['X-source-file'].to_s).to eq ('daily.csv') }
  end
end
Kummerbund answered 8/10, 2020 at 13:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.