如何在 Rails Mailer 中添加任意内联图像?

How to add arbitrary inline images in Rails Mailer?

提问人:duhaime 提问时间:7/9/2022 最后编辑:duhaime 更新时间:7/12/2022 访问量:413

问:

我正在开发一个 Rails 应用程序,它可以发送包含任意 HTML 内容的电子邮件。在邮件中,我们有:

class YeetMailer < ActionMailer::Base
  def welcome_email(html)
    
    # custom method that returns string[] where each string is an image src attribute
    @images = get_images_for_yeet_email(html)

    # add image attachments / Content-ID headers
    @images.map { |i|
      attachments.inline[i] = URI.open(i).read
    }

    # pass the html to the view
    @html = html
  end
end

然后在视图中:yeet_mailer/welcome_email.slim

= @html

我看过的所有指南(例如这个 Rails 指南)都建议应该使用带有 cid 内容的图像在电子邮件中呈现,但我还没有弄清楚在任意数量的图像的情况下如何做到这一点。<%= image_tag attachments['image_name.jpg'].url %>

我想我能做到:

@images.map { |i|
  attachments.inline[i] = URI.open(i).read
  html = html.sub(i, attachments.inline[i])
}

进行替换,但这会抛出.我添加了一行来进入方法内部的调试器并提供了一些见解(这是输出),所以我越来越近了......no implicit conversion of Mail::Part into Stringbyebugwelcome_emailputs(attachments.first)

有人知道我应该如何进行吗?任何提示都会非常有帮助!

Ruby-on-Rails 电邮 Ruby-on-Rails-5 Slim

评论

0赞 Maxence 7/10/2022
我认为问题出在这里:您使用网址而不是名称。也许创建一个带有 name 和 url 的数组并显示文件名并在视图中调用相同的名称(我不再内联了,所以我检查了一些旧代码,所以不能保证)@images.map { |i| attachments.inline[i] = URI.open(i).read }.inline["my-file.png"]
0赞 duhaime 7/10/2022
恐怕您可能误解了我的问题 - 我相信图像已正确附加到电子邮件标题中;我真的只是在问如何将帮助程序合并到我已经拥有的完整 HTML 字符串中。就像我如何将该逻辑放入 html 中一样,因为邮件操作函数中的标准调用会抛出......img_tag<%= img_tag ... %>sub
0赞 Maxence 7/10/2022
好的,我明白了。我的理解是,您想将图像添加为附件并显示它们。我认为您可以在原始 HTML 中添加自己的元标记,例如,然后将此自定义标记替换为 不要在此位中实际包含附件声明。将<<<hereimages>>>@images.map {|i| "<img src=#{i} >"}.joinattachments.inline[i]= etc..
0赞 Maxence 7/10/2022
我的坏可能你必须使用附件URL而不是普通URL:这里不太确定。如果它会导致某些事情,现在让我知道。如果您仍然有错误,我可能会在实际代码上尝试一些事情。@images.map {|i| "<img src=#{attachments[i].url} >"}.join
0赞 duhaime 7/10/2022
@Maxence您介意将其中一些评论转换为答案,然后删除评论?SO 对问题的长评论线程感到不安......

答:

0赞 duhaime 7/12/2022 #1

事实证明,您可以:

   @images.each_with_index { |i, idx|
      attachments.inline[i] = URI.open(i).read
      cid = attachments[idx].header.find { |h| h.name == 'Content-ID' }.field.value
      html = html.sub(i, "cid:#{cid}")
   }