27

次のコードを使用して、Railsでメールを送信しています。

class InvoiceMailer < ActionMailer::Base

  def invoice(invoice)
    from          CONFIG[:email]
    recipients    invoice.email
    subject       "Bevestiging Inschrijving #{invoice.course.name}"
    content_type  "multipart/alternative"

    part "text/html" do |p|
      p.body = render_message 'invoice_html', :invoice => invoice
    end

    part "text/plain" do |p|
      p.body = render_message 'invoice_plain', :invoice => invoice
    end

    pdf = Prawn::Document.new(:page_size => 'A4')
    PDFRenderer.render_invoice(pdf, invoice)
    attachment :content_type => "application/pdf", :body => pdf.render, :filename => "factuur.pdf"

    invoice.course.course_files.each do |file|
      attachment :content_type => file.content_type, :body => File.read(file.full_path), :filename => file.filename
    end
  end

end

私には問題ないようです。メールもGmailのウェブインターフェースに表示されるように表示されます。しかし、Mail(Appleプログラム)では、添付ファイルが1つだけ(2つあるはずです)、テキストがありません。何が原因なのかわからないようです。

ログからメールをコピーしました。

xxx@gmail.comにメールを送信しました

差出人:yyy@gmail.com
宛先:xxx@gmail.com
件名:InschrijvingAuthentiekSprekenの調査
Mime-バージョン:1.0
コンテンツタイプ:マルチパート/代替; border = mimepart_4a5b035ea0d4_769515bbca0ce9b412a


--mimepart_4a5b035ea0d4_769515bbca0ce9b412a
コンテンツタイプ:text / html; charset = utf-8
Content-Transfer-Encoding:Quoted-printable
コンテンツ-配置:インライン



  
  
  
    

拝啓

= --mimepart_4a5b035ea0d4_769515bbca0ce9b412a コンテンツタイプ:テキスト/プレーン; charset = utf-8 Content-Transfer-Encoding:Quoted-printable コンテンツ-配置:インライン 拝啓 * Foo = --mimepart_4a5b035ea0d4_769515bbca0ce9b412a コンテンツタイプ:application / pdf; name = factuur.pdf コンテンツ転送エンコーディング:Base64 コンテンツ-処分:添付ファイル; filename = factuur.pdf JVBERi0xLjMK ///// woxIDAgb2JqCjw8IC9DcmVhdG9yIChQcmF3bikKL1By b2R1Y2VyIChQcmF3bikKPj4KZW5kb2JqCjIgMCBvYmoKPDwgL0NvdW50IDEK .........。 MCBuIAp0cmFpbGVyCjw8IC9JbmZvIDEgMCBSCi9TaXplIDExCi9Sb290IDMg MCBSCj4 + CnN0YXJ0eHJlZgo4Nzc1CiUlRU9GCg == --mimepart_4a5b035ea0d4_769515bbca0ce9b412a コンテンツタイプ:application / pdf; name = Spelregels.pdf コンテンツ転送エンコーディング:Base64 コンテンツ-処分:添付ファイル; filename = Spelregels.pdf JVBERi0xLjQNJeLjz9MNCjYgMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgMjEx NjYvTyA4L0UgMTY5NTIvTiAxL1QgMjEwMDAvSCBbIDg3NiAxOTJdPj4NZW5k .........。 MDIwNzQ4IDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgNj4 + DQpzdGFydHhy ZWYNCjExNg0KJSVFT0YNCg == --mimepart_4a5b035ea0d4_769515bbca0ce9b412a--
4

8 に答える 8

23

問題は、メール全体をマルチパート/代替として定義していることであると思われます。これは、各パートが同じメッセージの単なる代替ビューであることを示唆しています。

次のようなものを使用して、添付ファイル付きのhtml / plainの混合メールを送信しますが、問題なく機能しているようです。

class InvoiceMailer < ActionMailer::Base

  def invoice(invoice)
    from          CONFIG[:email]
    recipients    invoice.email
    subject       "Bevestiging Inschrijving #{invoice.course.name}"
    content_type  "multipart/mixed"

    part(:content_type => "multipart/alternative") do |p|
      p.part "text/html" do |p|
        p.body = render_message 'invoice_html', :invoice => invoice
      end

      p.part "text/plain" do |p|
        p.body = render_message 'invoice_plain', :invoice => invoice
      end
    end

    pdf = Prawn::Document.new(:page_size => 'A4')
    PDFRenderer.render_invoice(pdf, invoice)
    attachment :content_type => "application/pdf", :body => pdf.render, :filename => "factuur.pdf"

    invoice.course.course_files.each do |file|
      attachment :content_type => file.content_type, :body => File.read(file.full_path), :filename => file.filename
    end
  end

end
于 2009-07-15T06:06:05.867 に答える
17

@jcolemanは正しいですが、彼の宝石を使用したくない場合は、これがより良い解決策になる可能性があります。

class MyEmailerClass < ActionMailer::Base
  def my_email_method(address, attachment, logo)

    # Add inline attachments first so views can reference them
    attachments.inline['logo.png'] = logo

    # Call mail as per normal but keep a reference to it
    mixed = mail(:to => address) do |format|
      format.html
      format.text
    end

    # All the message parts from above will be nested into a new 'multipart/related'
    mixed.add_part(Mail::Part.new do
      content_type 'multipart/related'
      mixed.parts.delete_if { |p| add_part p }
    end)
    # Set the message content-type to be 'multipart/mixed'
    mixed.content_type 'multipart/mixed'
    mixed.header['content-type'].parameters[:boundary] = mixed.body.boundary

    # Continue adding attachments normally
    attachments['attachment.pdf'] = attachment
  end
end

このコードは、次のMIME階層を作成することから始まります。

  • multipart/related
    • multipart/alternative
      • text/html
      • text/plain
    • image/png

の呼び出し後、mail新しいmultipart/relatedパーツを作成し、既存のパーツの子を追加します(必要に応じて削除します)。次に、を強制しContent-Typemultipart/mixed添付ファイルを追加し続け、結果としてMIME階層を作成します。

  • multipart/mixed
    • multipart/related
      • multipart/alternative
        • text/html
        • text/plain
      • image/png
    • application/pdf
于 2012-07-03T15:22:47.673 に答える
13

メーラーを正しく機能させるのに役立ったので、これについてジェームズにうなずきます。

これを少し改良します。まず、ブロック内のブロック引数を使用してパーツを追加します(追加しなかったときに問題が発生しました)。

また、レイアウトを使用する場合は、#renderを直接使用する必要があります。これは、両方の原則が機能している例です。上に示したように、html部分を最後に保持することを確認する必要があります。

  def message_with_attachment_and_layout( options )
    from options[:from]
    recipients options[:to]
    subject options[:subject]
    content_type    "multipart/mixed"
    part :content_type => 'multipart/alternative' do |copy|
      copy.part :content_type => 'text/plain' do |plain|
        plain.body = render( :file => "#{options[:render]}.text.plain", 
          :layout => 'email', :body => options )
      end
      copy.part :content_type => 'text/html' do |html|
        html.body = render( :file => "#{options[:render]}.text.html", 
          :layout => 'email', :body => options )
      end
    end
    attachment :content_type => "application/pdf", 
      :filename => options[:attachment][:filename],
      :body => File.read( options[:attachment][:path] + '.pdf' )
  end

この例では、オプションハッシュを使用して、添付ファイルとレイアウトの両方を含む一般的なマルチパートメッセージを作成します。これは、次のように使用します。

TestMailer.deliver_message_with_attachment_and_layout( 
  :from => 'a@fubar.com', :to => 'b@fubar.com', 
  :subject => 'test', :render => 'test', 
  :attachment => { :filename => 'A Nice PDF', 
    :path => 'path/to/some/nice/pdf' } )

(実際にはこれを行いません。各メーラーにこれらの詳細をたくさん記入してもらう方が良いですが、コードを理解しやすくなると思いました。)

お役に立てば幸いです。幸運を祈ります。

よろしく、ダン

于 2009-09-04T15:56:03.417 に答える
12

Rails 3はメールの処理方法が異なります。単純なケースの方が簡単ですが、代替コンテンツタイプと(インライン)添付ファイルの両方を含むマルチパートメールに正しいMIME階層を追加することは、かなり複雑です(主に必要な階層が非常に複雑であるため)。

Philの答えは機能しているように見えますが、MIME階層がまだ正しくないため、添付ファイルはiPhone(およびおそらく他のデバイス)には表示されません。

正しいMIME階層は、次のようになります。

  • multipart/mixed
    • multipart/alternative
      • multipart/related
        • text/html
        • image/png(たとえば、インライン添付ファイルの場合。pdfは別の良い例です)
      • text/plain
    • application/zip(例:添付ファイルの場合-インラインではありません)

正しい階層をサポートするのに役立つgemをリリースしました: https ://github.com/jcoleman/mail_alternatives_with_attachments

通常、ActionMailer 3を使用する場合は、次のコードでメッセージを作成します。

class MyEmailerClass < ActionMailer::Base
  def my_email_method(address)
    mail :to => address, 
         :from => "noreply@myemail.com",
         :subject => "My Subject"
  end
end

このgemを使用して、代替と添付ファイルの両方を含む電子メールを作成するには、次のコードを使用します。

class MyEmailerClass < ActionMailer::Base
  def my_email_method(address, attachment, logo)
    message = prepare_message to: address, subject: "My Subject", :content_type => "multipart/mixed"

    message.alternative_content_types_with_attachment(
      :text => render_to_string(:template => "my_template.text"),
      :html => render_to_string("my_template.html")
    ) do |inline_attachments|
      inline_attachments.inline['logo.png'] = logo
    end

    attachments['attachment.pdf'] = attachment

    message
  end
end
于 2011-12-24T17:40:54.620 に答える
6

Rails 3ソリューション、PDF添付ファイル付きのマルチパート代替メール(htmlおよびプレーン)、インライン添付ファイルなし

以前は、iOSまたはosxのmail.appで開いたときに、本文にpdf添付ファイルのみが表示され、本文にプレーンもhtmlも表示されないメールがありました。Gmailが問題になることはありません。

インラインアタッチメントは必要ありませんでしたが、Corinと同じソリューションを使用しました。それは私をかなり遠ざけました-1つの問題を除いて-mail.app/iOSメールはhtmlではなくプレーンテキストを示しました。これは(最終的に発生した場合)、代替部分が最初にhtmlで、次にテキストであるという順序のためでした(なぜそれが決定的である必要があるのか​​、とにかく)。

だから私はもう1つ変更を加える必要がありましたが、それはうまくいきました。.reverseを追加します!方法。

ので、私は持っています

def guest_notification(requirement, message)
 subject     = "Further booking details"
 @booking = requirement.booking
 @message = message

 mixed = mail(:to => [requirement.booking.email], :subject => subject) do |format|
   format.text
   format.html
 end

 mixed.add_part(
  Mail::Part.new do
   content_type 'multipart/alternative'
   # THE ODD BIT vv
   mixed.parts.reverse!.delete_if {|p| add_part p }
  end
 )

 mixed.content_type 'multipart/mixed'
 mixed.header['content-type'].parameters[:boundary] = mixed.body.boundary
 attachments['Final_Details.pdf'] = File.read(Rails.root + "public/FinalDetails.pdf")

end
于 2013-05-02T09:03:08.227 に答える
5

注:以下の私のテクニックは、場合によっては機能します。ただし、インライン画像と組み合わせると、添付ファイルがiPhoneメールや他のクライアントに表示されなくなります。完全な解決策については、以下のjcolemanの回答を参照してください。

少なくとも3.1rc4以降、Railsがこれを処理するようになったことは注目に値します。ActionMailerガイドから:

class UserMailer < ActionMailer::Base
  def welcome_email(user)
    @user = user
    @url  = user_url(@user)
    attachments['terms.pdf'] = File.read('/path/terms.pdf')
    mail(:to => user.email,
         :subject => "Please see the Terms and Conditions attached")
  end
end

秘訣は、を呼び出すに添付ファイルを追加することですmail。後に添付ファイルを追加すると、質問で言及されている3つの選択肢の問題が発生します。

于 2011-08-24T14:22:38.080 に答える
4

Rails4ソリューション

私たちのプロジェクトでは、会社のロゴ(インライン添付ファイル)とPDF(通常の添付ファイル)を含む電子メールを顧客に送信しています。実施した回避策は、@user1581404によってここで提供されたものと同様でした。

mailただし、プロジェクトをRails 4にアップグレードした後、コマンドを呼び出した後に添付ファイルを追加することができなくなったため、新しい解決策を見つける必要がありました。

私たちのメーラーにはベースメーラーがあります。この問題を修正するには、mailメソッドを次のようにオーバーライドします。

def mail(headers = {}, &block)
    message = super

    # If there are no regular attachments, we don't have to modify the mail
    return message unless message.parts.any? { |part| part.attachment? && !part.inline? }

    # Combine the html part and inline attachments to prevent issues with clients like iOS
    html_part = Mail::Part.new do
      content_type 'multipart/related'
      message.parts.delete_if { |part| (!part.attachment? || part.inline?) && add_part(part) }
    end

    # Any parts left must be regular attachments
    attachment_parts = message.parts.slice!(0..-1)

    # Reconfigure the message
    message.content_type 'multipart/mixed'
    message.header['content-type'].parameters[:boundary] = message.body.boundary
    message.add_part(html_part)
    attachment_parts.each { |part| message.add_part(part) }

    message
  end
于 2016-04-22T03:34:51.667 に答える
3

NBRails3.2ソリューション。

これらのマルチパートメールと同様に、この回答には複数のパートがあるため、それに応じて分析します。

  1. @Corinの「混合」アプローチでのplain/html形式の順序は重要です。テキストの後にhtmlが続くと、必要な機能が得られます。YMMV

  2. Content-Dispositionをnil(削除する)に設定すると、他の回答で表現されているiPhone/iOS添付ファイルの表示の問題が修正されました。このソリューションは、Outlook for Mac、Mac OS / Xメール、およびiOSメールで機能することがテストされています。他の電子メールクライアントも同様に機能すると思います。

  3. Railsの以前のバージョンとは異なり、添付ファイルの処理は宣伝どおりに機能しました。私の最大の問題は通常、私にとって問題を悪化させるだけの古い回避策を試みることによって引き起こされました。

これが誰かが私の落とし穴や袋小路を回避するのに役立つことを願っています。

作業コード:

def example( from_user, quote)
  @quote = quote

  # attach the inline logo
  attachments.inline['logo.png'] = File.read('./public/images/logo.png')

  # attach the pdf quote
  attachments[ 'quote.pdf'] = File.read( 'path/quote.pdf')

  # create a mixed format email body
  mixed = mail( to: @quote.user.email,
                subject: "Quote") do |format|
    format.text
    format.html
  end

  # Set the message content-type to be 'multipart/mixed'
  mixed.content_type 'multipart/mixed'
  mixed.header['content-type'].parameters[:boundary] = mixed.body.boundary

  # Set Content-Disposition to nil to remove it - fixes iOS attachment viewing
  mixed.content_disposition = nil
end
于 2013-12-31T17:04:22.790 に答える