如何使用Ruby处理UTF-8电子邮件标题(如Subject :)?

时间:2023-01-05 16:21:07

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").

我是一封电子邮件n00b,但我正在开发一个发送带有Unicode字符的HTML电子邮件的应用程序(正如我的朋友所说“享受编码地狱”)。

The Subject: header comes from user input and therefore may contain Unicode characters. Some mail clients (like GMail and Outlook 2007) are OK with this, but from my reading it seems the right way to do this is to use MIME Encoded-Word encoding for the headers.

Subject:标题来自用户输入,因此可能包含Unicode字符。一些邮件客户端(如GMail和Outlook 2007)可以正常使用,但从我的阅读中看来,正确的方法是对标头使用MIME编码字编码。

I cannot find a Ruby library to do this. Is there one?

我找不到一个Ruby库来做这件事。有吗?

Also, is there a header to add that will tell mail clients to use UTF-8 when displaying the message? We are sending multipart email so our Content-Type is multipart/mixed. Apple Mail.app in particular is not using the right encoding, even though it's specified in the individual parts as being UTF-8.

此外,是否有一个标题要添加,告诉邮件客户端在显示邮件时使用UTF-8?我们发送多部分电子邮件,因此我们的内容类型是多部分/混合。 Apple Mail.app特别没有使用正确的编码,即使它在各个部分中指定为UTF-8。

3 个解决方案

#1


9  

Your can optionally do the same using Base64 encoding:

您可以选择使用Base64编码执行相同操作:

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 "=".

注意标记Base64编码有效载荷的“B”,而不是标记“Q编码”有效载荷的“Q”。后者可以通过对字符串进行URL编码并用“=”替换所有“%”字符来伪造。

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.

通过“伪造”我的意思是:它会产生一个有效的结果,但可能编码的字符比必要的多。规范允许使用“=”+ ByteCodeAsHex对每个字符进行编码,它只会损害原始标头的人类可读性。当没有别的东西可用时,UrlEncode是+ .gsub(/%/,“=”)并不是一个糟糕的妥协。

#2


5  

Ahah! ActionMailer::Quoting has a quoted_printable method.

啊啊! ActionMailer :: Quoting有一个quoted_printable方法。

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!

这样做确信Mail.app使用UTF-8显示其余的电子邮件。现在来测试剩下的!

#3


3  

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

由于没有一个答案讲述了纯Ruby的整个消息,所以它就是这样。

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.

在这里打开与localhost的连接。也可以使用外部SMTP服务器,请参阅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.

from是From:Name这里的地址

。如果不需要名称,则只能指定地址,例如From:address@here.fi。
@here.fi>

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

使用相同的语法,例外From:更改为To:。

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

主题是主语:主题在这里。对于UTF-8,它需要进行Base64编码才能正确显示给客户端。

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.

消息是以UTF-8编码的纯文本消息,没有任何前缀。 net / smtp将负责形成正确的邮件。

#1


9  

Your can optionally do the same using Base64 encoding:

您可以选择使用Base64编码执行相同操作:

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 "=".

注意标记Base64编码有效载荷的“B”,而不是标记“Q编码”有效载荷的“Q”。后者可以通过对字符串进行URL编码并用“=”替换所有“%”字符来伪造。

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.

通过“伪造”我的意思是:它会产生一个有效的结果,但可能编码的字符比必要的多。规范允许使用“=”+ ByteCodeAsHex对每个字符进行编码,它只会损害原始标头的人类可读性。当没有别的东西可用时,UrlEncode是+ .gsub(/%/,“=”)并不是一个糟糕的妥协。

#2


5  

Ahah! ActionMailer::Quoting has a quoted_printable method.

啊啊! ActionMailer :: Quoting有一个quoted_printable方法。

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!

这样做确信Mail.app使用UTF-8显示其余的电子邮件。现在来测试剩下的!

#3


3  

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

由于没有一个答案讲述了纯Ruby的整个消息,所以它就是这样。

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.

在这里打开与localhost的连接。也可以使用外部SMTP服务器,请参阅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.

from是From:Name这里的地址

。如果不需要名称,则只能指定地址,例如From:address@here.fi。
@here.fi>

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

使用相同的语法,例外From:更改为To:。

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

主题是主语:主题在这里。对于UTF-8,它需要进行Base64编码才能正确显示给客户端。

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.

消息是以UTF-8编码的纯文本消息,没有任何前缀。 net / smtp将负责形成正确的邮件。