How to handle UTF-8 email headers (like Subject:) using Ruby?

前端 未结 3 776
旧时难觅i
旧时难觅i 2021-01-05 04:04

I\'m an email n00b but I am working on an application that sends HTML email with Unicode characters (as my friend noted \"enjoy encoding hell\").

The Subject:<

相关标签:
3条回答
  • 2021-01-05 04:10

    Ahah! ActionMailer::Quoting has a quoted_printable method.

    So here's what I did:

    def my_email(foo)
      ...
      @subject = quoted_printable(foo.some_subject_with_accented_chars, 'utf-8')
      ...
    end
    

    Doing this convinced Mail.app to display the rest of the email using UTF-8. Now to test the rest!

    0 讨论(0)
  • 2021-01-05 04:27

    Since none of the answers tells about whole message with pure Ruby, here it is.

    Net::SMTP.start("localhost") do |smtp|
        smtp.open_message_stream opts[:sender_address], opts[:receiver_address] do |f|
    
            f.puts "Content-type: text/plain; charset=UTF-8"
            f.puts from
            f.puts to
            f.puts subject
            f.puts message
        end
    end
    

    Here you open connection to localhost. Using external SMTP server is also possible, refer to documentation of net/smtp.

    First line sets character set used in the message. Rest of the lines are variables defined separately:

    from is an address in form of From: Name here <address@here.fi>. If no name is wanted, only address can be specified, like From: address@here.fi.

    to uses same syntax, with exception From: changed to To:.

    subject is in form of Subject: subject here. For UTF-8, it needs to be Base64-encoded to be shown correctly for clients.

    subject = "Subject: =?UTF-8?B?" + Base64.strict_encode64(subject) + "?="
    

    Message is plain text message encoded in UTF-8, without any prefix. net/smtp will take care of forming proper mail.

    0 讨论(0)
  • 2021-01-05 04:31

    Your can optionally do the same using Base64 encoding:

    require "base64"
    
    value  = Base64.encode64("Your UTF-8 string")
    header = "=?UTF-8?B?" + value + "?="
    

    Note the "B", that marks Base64 encoded payload, as opposed to the "Q" which marks "Q-encoded" payload. The latter could be faked by URL-encoding the string and replacing all "%" characters with "=".

    By "faking" I mean this: It would produce a valid result, but maybe more characters are encoded than would be necessary. The spec allows for encoding every character there is with "=" + ByteCodeAsHex, it merely impairs human readability of the raw headers. UrlEncode is + .gsub(/%/, "=") not a bad compromise when nothing else is available.

    0 讨论(0)
提交回复
热议问题