开发者

Rails 3 ActionMailer and Wicked_PDF

开发者 https://www.devze.com 2023-02-19 18:06 出处:网络
I\'m trying to generate emails with rendered PDF attachements using ActionMailer and wicked_pdf. On my site, I\'m using already both wicked_pdf and actionmailer separately. I can use wicked_pdf to se

I'm trying to generate emails with rendered PDF attachements using ActionMailer and wicked_pdf.

On my site, I'm using already both wicked_pdf and actionmailer separately. I can use wicked_pdf to serve up a p开发者_Go百科df in the web app, and can use ActionMailer to send mail, but I'm having trouble attaching rendered pdf content to an ActionMailer (edited for content):

class UserMailer < ActionMailer::Base
  default :from => "webadmin@mydomain.com"

  def generate_pdf(invoice)
    render :pdf => "test.pdf",
     :template => 'invoices/show.pdf.erb',
     :layout => 'pdf.html'
  end

  def email_invoice(invoice)
    @invoice = invoice
    attachments["invoice.pdf"] = {:mime_type => 'application/pdf',
                                  :encoding => 'Base64',
                                  :content => generate_pdf(@invoice)}
    mail :subject => "Your Invoice", :to => invoice.customer.email
  end
end

Using Railscasts 206 (Action Mailer in Rails 3) as a guide, I can send email with my desired rich content, only if I don't try to add my rendered attachment.

If I try to add the attachment (as shown above), I get an attachement of what looks to be the right size, only the name of the attachment doesn't come across as expected, nor is it readable as a pdf. In addition to that, the content of my email is missing...

Does anyone have any experience using ActionMailer while rendering the PDF on the fly in Rails 3.0?

Thanks in advance! --Dan


WickedPDF can render to a file just fine to attach to an email or save to the filesystem.

Your method above won't work for you because generate_pdf is a method on the mailer, that returns a mail object (not the PDF you wanted)

Also, there is a bug in ActionMailer that causes the message to be malformed if you try to call render in the method itself

http://chopmode.wordpress.com/2011/03/25/render_to_string-causes-subsequent-mail-rendering-to-fail/

https://rails.lighthouseapp.com/projects/8994/tickets/6623-render_to_string-in-mailer-causes-subsequent-render-to-fail

There are 2 ways you can make this work,

The first is to use the hack described in the first article above:

def email_invoice(invoice)
  @invoice = invoice
  attachments["invoice.pdf"] = WickedPdf.new.pdf_from_string(
    render_to_string(:pdf => "invoice",:template => 'documents/show.pdf.erb')
  )
  self.instance_variable_set(:@lookup_context, nil)
  mail :subject => "Your Invoice", :to => invoice.customer.email
end

Or, you can set the attachment in a block like so:

def email_invoice(invoice)
  @invoice = invoice
  mail(:subject => 'Your Invoice', :to => invoice.customer.email) do |format|
    format.text
    format.pdf do
      attachments['invoice.pdf'] = WickedPdf.new.pdf_from_string(
        render_to_string(:pdf => "invoice",:template => 'documents/show.pdf.erb')
      )
    end
  end
end


I used of Unixmonkey's solutions above, but then when I upgraded to rails 3.1.rc4 setting the @lookup_context instance variable no longer worked. Perhaps there's another way to achieve the same clearing of the lookup context, but for now, setting the attachment in the mail block works fine like so:

  def results_email(participant, program)
    mail(:to => participant.email,
         :subject => "my subject") do |format|
      format.text
      format.html
      format.pdf do
        attachments['trust_quotient_results.pdf'] = WickedPdf.new.pdf_from_string(
          render_to_string :pdf => "results",
               :template => '/test_sessions/results.pdf.erb',
               :layout => 'pdf.html')
      end
   end
  end


Heres' how I fixed this issue:

  1. Removed wicked_pdf
  2. Installed prawn (https://github.com/sandal/prawn/wiki/Using-Prawn-in-Rails)

While Prawn is/was a bit more cumbersome in laying out a document, it can easily sling around mail attachments...


Better to use PDFKit, for example:

class ReportMailer < ApplicationMailer

  def report(users:, amounts:)
    @users = users
    @amounts = amounts

    attachments["proveedores.pdf"] = PDFKit.new(
      render_to_string(
        pdf: 'bcra',
        template: 'reports/users.html.haml',
        layout: false,
        locals: { users: @users }
      )
    ).to_pdf

    mail subject: "Report - #{Date.today}"
  end
end
0

精彩评论

暂无评论...
验证码 换一张
取 消