Rails遗留项目邮件中二维码无法显示问题求助
Rails邮件嵌入二维码失效的解决方法
问题回顾
- 用QRCode.js生成二维码:网站端正常,但Gmail会修改元素ID前缀、Outlook篡改ID并丢失类名,且邮件客户端普遍禁用JS,导致二维码无法渲染
- 用RQRCode:网站端正常,邮件中显示
<u></u>,因生成的HTML/SVG标签被邮件客户端过滤 - 用Google Chart QR:网站端正常,邮件中图片损坏,因外部图片链接被邮件客户端拦截或API访问限制
可行解决方案
邮件客户端对JS和外部资源的限制严格,必须采用服务器端生成图片并直接嵌入邮件的方式,以下是两种可靠方案:
方案1:生成Base64编码图片嵌入
直接将二维码图片转为Base64字符串,嵌入到邮件的<img>标签中,无需依赖外部资源。
- 在邮件处理类中生成Base64编码:
# 示例:邮件类中的方法 def tire_qr_notification(tires) @tires = tires @tires.each do |tire| # 生成二维码对象 qr_code = RQRCode::QRCode.new("https://your-domain.com/tires/#{tire.id}") # 生成PNG图片 png = qr_code.as_png( size: 128, border_modules: 4, color: 'black', fill: 'white' ) # 转Base64编码 tire.qr_base64 = Base64.encode64(png.to_s) end mail(to: 'user@example.com', subject: '轮胎二维码通知') end
- 在邮件ERB模板中引用:
<% @tires.each do |tire| %> <h3>TIRE <%= tire.id %> QR CODE</h3> <img src="data:image/png;base64,<%= tire.qr_base64 %>" width="128" height="128" alt="轮胎<%= tire.id %>的二维码"> <% end %>
方案2:生成内嵌附件通过CID引用
如果二维码数量多导致Base64邮件体积过大,可将图片作为内嵌附件,通过CID(Content-ID)引用。
- 在邮件类中添加内嵌附件:
def tire_qr_notification(tires) @tires = tires @tires.each do |tire| qr_code = RQRCode::QRCode.new("https://your-domain.com/tires/#{tire.id}") png = qr_code.as_png(size: 128) # 生成唯一CID cid = "qr_tire_#{tire.id}@your-domain.com" # 添加为内嵌附件 attachments.inline[cid] = { mime_type: 'image/png', content: png.to_s } tire.qr_cid = cid end mail(to: 'user@example.com', subject: '轮胎二维码通知') end
- 在邮件模板中引用CID:
<% @tires.each do |tire| %> <h3>TIRE <%= tire.id %> QR CODE</h3> <img src="cid:<%= tire.qr_cid %>" width="128" height="128" alt="轮胎<%= tire.id %>的二维码"> <% end %>
失效原因说明
- QRCode.js:邮件客户端默认禁用JavaScript,客户端生成逻辑无法执行,且邮件系统会修改HTML的ID/类名,进一步破坏JS选择器
- RQRCode(HTML/SVG输出):邮件客户端对复杂HTML/SVG标签支持有限,多数会过滤此类内容,导致渲染异常
- Google Chart QR:外部图片链接易被邮件客户端当作不安全资源拦截,且Google Chart API存在访问限制,易导致图片加载失败
内容的提问来源于stack exchange,提问作者daveasdf_2
相关产品推荐
相关产品推荐

