Rails ActionMailer附件留空主体

3
我正在尝试通过ActionMailer生成的电子邮件发送内联附件(图像)。但是,每次添加附件时,我都会收到一个空白的电子邮件正文。我尝试创建一个基本的测试电子邮件来消除其他可能存在的变量,但我仍然遇到同样的问题。
我正在使用Rails 3.2.13,以下是我的代码和失败的规范:
app/mailers/contact_mailer.rb
class ContactMailer < ActionMailer::Base
  default from: "support@example.com"

  def test
    attachments.inline['logo.png'] = File.read Rails.root.join('app/assets/images/emails/logo.png').to_s
    mail(to: 'my_email@gmail.com', subject: 'Testing, Testing')
  end

  def test_no_attachment
    mail(to: 'my_email@gmail.com', subject: 'Testing, Testing')
  end

app/views/contact_mailer/test.html.erb

<p>This is a test.</p>
<p>This is only a test.</p>
<%= image_tag attachments['mhbo_logo.png'].url %>

app/views/contact_mailer/test_no_attachment.html.erb

<p>This is a test.</p>
<p>This is only a test.</p>

spec/mailers/contact_mailer_spec.rb

require 'spec_helper'

describe ContactMailer do
  describe 'test' do
    it 'should send' do
      ContactMailer.test.deliver
      ActionMailer::Base.deliveries.count.should eq 1
      ActionMailer::Base.deliveries.last.body.should match /This is a test./
    end
  end

  describe 'test_no_attachment' do
    it 'should send' do
      ContactMailer.test_no_attachment.deliver
      ActionMailer::Base.deliveries.count.should eq 1
      ActionMailer::Base.deliveries.last.body.should match /This is a test./
    end
  end
end

第二个测试通过了,但第一个测试失败并显示如下内容:
 Failure/Error: ActionMailer::Base.deliveries.last.body.should match /This is a test./
   expected  to match /This is a test./
 # ./spec/mailers/contact_mailer_spec.rb:8:in `block (3 levels) in <top (required)>'

因此,此电子邮件的正文为空。
我的代码有什么问题?还是我测试的方式有问题?我已经测试了许多其他具有相同语法的电子邮件,尽管没有附件。我也感到困惑,因为我认为添加附件会发送多部分电子邮件,这样ActionMailer :: Base.deliveries.count将大于1。我错了吗?
我有点迷失方向,所以任何帮助都将不胜感激。
1个回答

6
原来是我错误地测试了邮件内容。多部分邮件(例如带附件的邮件)会作为单个邮件发送,但包含多个部分,可以通过以下方式访问:
ActionMailer::Base.deliveries.last.body.parts

因此,为了找到与HTML body相对应的部分,我编写了这个测试:
ActionMailer::Base.deliveries.last.body.parts.detect{|p| p.content_type.match(/text\/html/)}.body.should match /This is a test./

我把这段代码重构成宏,以使我的测试更易读:

spec/macros/testing_macros.rb

module TestingMacros
  def last_email_html_body
    ActionMailer::Base.deliveries.last.body.parts.detect{|p| p.content_type.match(/text\/html/)}.body
  end
end

spec/mailers/contact_mailer_spec.rb

…
last_email_html_body.should match /This is a test./
…

1
因为这让我明白,如果有附件,我需要处理电子邮件的body.parts而不仅仅是将电子邮件的body直接呈现为HTML blob。感谢您引领我到那里。 - Mark Judd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接