题
显然,对日语电子邮件进行编码有些挑战性,这是我自己慢慢发现的。如果有任何专家(即使是经验有限的专家也可以),我可以提供一些关于如何做、如何测试和验证的指南吗?
请记住,我从未涉足日本附近的任何地方,只是我正在开发的产品在那里以及其他地方使用。
到目前为止我所知道的(我认为)如下:
- 日语电子邮件应使用 ISO-2022-JP、日语 JIS 代码页 50220 或可能使用 SHIFT_JIS 代码页 932 进行编码
- 电子邮件传输编码应设置为 Base64(纯文本)和 7Bit(Html)
- 电子邮件主题应分别编码为“ =?iso-2022-jp?b?”。 (不知道这应该是什么意思)。我尝试过对主题进行编码
"=?ISO-2022-JP?B?" + Convert.ToBase64String(Encoding.Unicode.GetBytes(subject))
这基本上给出了预期的编码字符串,但它不会在电子邮件程序中显示为任何日语文本
- 我已经在 Outlook 2003、Outlook Express 和 GMail 中进行了测试
任何帮助将不胜感激
好的,所以发布一个简短的更新,感谢两个有用的答案,我已经设法获得正确的格式和编码。现在,Outlook 会给出类似于正确主题的内容:
=?iso-2022-jp?B?6 Japanese test に各々の視点で語ってもらった。 6相当の防水?=
然而,Outlook Express 中的同一封电子邮件的主题如下:
=?iso-2022-jp?B?6 Japanese test 縺ォ蜷・・・隕也せ縺ァ隱槭▲縺ヲ繧ゅi縺」縺溘・ 6逶ク蠖薙・髦イ豌エ?=
此外,当在 Outlook Express 的收件箱视图中查看时,电子邮件主题更加奇怪,如下所示:
=?iso-2022-jp?B?6 Japanese test ??????????????? 6???????=
Gmail 的工作方式似乎与 Outlook 类似,看起来是正确的。
我就是无法理解这个问题。
解决方案
我已经处理日语编码近 20 年了,所以我可以理解你的困难。我工作过的网站每天都会向日本客户发送数百封电子邮件,以便我可以与您分享对我们有用的内容。
首先,不要使用Shift-JIS。我个人收到了大量的日语电子邮件,但它们几乎从未使用 Shift-JIS 进行编码。我认为 Outlook Express 的旧版本(大约是 Win 98?)使用 Shift-JIS 编码外发邮件,但现在您只是看不到它。
正如您所发现的,您至少需要使用 ISO-2022-JP 作为邮件标头中的任何内容的编码。这包括主题、收件人行和抄送行。UTF-8 在大多数情况下也可以工作, 但 它不适用于雅虎日本邮件,正如您可以想象的那样,许多日本用户使用雅虎日本邮件。
您可以在电子邮件正文中使用 UTF-8,但建议您对 UTF-8 编码的日语文本进行 Base64 编码,并将其放入正文中,而不是原始 UTF-8 文本。然而,在实践中,我相信现在对于电子邮件正文来说,原始 UTF-8 文本可以正常工作。
正如我上面提到的,您至少需要在 Outlook (Exchange)、Outlook Express (IMAP/POP3) 和 Yahoo Japan Web 邮件上进行测试。雅虎日本是最棘手的,因为我相信他们使用 EUC 对其网页进行编码,因此您需要遵循正确的电子邮件标准,否则它们将无法工作(ISO-2022-JP 是发送日语电子邮件的标准)。
此外,您的主题行每行不应超过 75 个字符。即75个字符 后 您已在转换前以 ISO-2022-JP 和 base64 进行编码,而不是 75 个字符。如果您超过75个字符,则需要将编码的主体分成多行,从“ =?iso-2022-JP?b?”开始。并在每行上以“?=”结尾。如果您不这样做,您的主题可能会被截断(取决于电子邮件阅读器以及主题文本的内容)。根据 RFC 2047:
“‘编码字’的长度不得超过 75 个字符,包括‘字符集’、‘编码’、‘编码文本’和分隔符。如果需要编码的文本多于 75 个字符的“编码字”,则可以使用多个“编码字”(用 CRLF 空格分隔)。
- 以下是一些用于对主题进行编码的示例 PHP 代码:
// Convert Japanese subject to ISO-2022-JP (JIS is essentially ISO-2022-JP)
$subject = mb_convert_encoding ($subject, "JIS", "SJIS");
// Now, base64 encode the subject
$subject = base64_encode ($subject);
// Add the encoding markers to the subject
$subject = "=?iso-2022-jp?B?" . $subject . "?=";
// Now, $subject can be placed as-is into the raw mail header.
- 有关如何对电子邮件标头进行编码的完整说明,请参阅 RFC 2047。
其他提示
检查 http://en.wikipedia.org/wiki/MIME#Encoded-Word 有关如何对符合MIME的邮件中的标头字段进行编码的说明。你似乎错过了一个“?=”在你的主题结束时。
=?ISO-2022-JP?B?TEXTTEXT ......
ISO_2022-JP表示字符串在ISO-2022-JP代码页中编码(例如,不是Unicode) B表示字符串是bese64编码的
在您的示例中,您应该只使用ISO-2022-JP而不是Unicode来提供字符串。
我有一些使用日语编写和发送电子邮件的经验...通常,您必须要注意用于操作系统的编码以及如何存储日语字符串! 我的邮件对象通常编码如下:
string s = "V‚µ‚¢ŠwK–@‚Ì‚²’ñˆÄ"; // Our japanese are shift-jis encoded, so it appears like garbled
MailMessage message = new MailMessage();
message.BodyEncoding = Encoding.GetEncoding("iso-2022-jp");
message.SubjectEncoding = Encoding.GetEncoding("iso-2022-jp");
message.Subject = s.ToEncoding(Encoding.GetEncoding("Shift-Jis")); // Change the encoding to whatever your source is
message.Body = s.ToEncoding(Encoding.GetEncoding("Shift-Jis")); // Change the encoding to whatever your source is
然后我有一个扩展方法,为我转换:
public static string ToEncoding(this string s, Encoding targetEncoding)
{
return s == null ? null : targetEncoding.GetString(Encoding.GetEncoding(1252).GetBytes(s)); //1252 is the windows OS codepage
}
这样的事情应该在python中完成工作:
#!/usr/bin/python
# -*- mode: python; coding: utf-8 -*-
import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate
def send_from_gmail( from_addr, to_addr, subject, body, password, encoding="iso-2022-jp" ):
msg = MIMEText(body.encode(encoding), 'plain', encoding)
msg['Subject'] = Header(subject.encode(encoding), encoding)
msg['From'] = from_addr
msg['To'] = to_addr
msg['Date'] = formatdate()
s = smtplib.SMTP('smtp.gmail.com', 587)
s.ehlo(); s.starttls(); s.ehlo()
s.login(from_addr, password)
s.sendmail(from_addr, to_addr, msg.as_string())
s.close()
return "Sent mail to: %s" % to_addr
if __name__ == "__main__":
import sys
for n,item in enumerate(sys.argv):
sys.argv[n] = sys.argv[n].decode("utf8")
if len(sys.argv)==6:
print send_from_gmail( sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5] )
elif len(sys.argv)==7:
print send_from_gmail( sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], encoding=sys.argv[6] )
else:
raise "SYNTAX: %s <from_addr> <to_addr> <subject> <body> <password> [encoding]"
**公然被盗/改编自:
首先你应该使用:
Encoding.GetEncoding(&quot; ISO-2022-JP&quot;)
将主题行转换为将由Convert.ToBase64String()处理的字节。
=?ISO-2022-JP?B?TEXTTEXT ...?=告诉接收邮件客户端在发送方侧使用哪种编码来转换日语“字母”。进入字节流。
目前您正在使用UTF-16进行编码,但指定ISO-2022-JP进行解码。这些显然是两种不同的编码,我想,就像ISO-8859-1与Unicode不同(大多数扩展的西欧字符在ISO-XXX中用一个字节表示,但在Unicode中用两个字节表示)。
我不确定你对UTF-8是二等公民的意思。只要接收邮件客户端理解UTF-8并且能够将其转换为当前的日语语言环境,一切都很好。
<?php
function sendMail($to, $subject, $body, $from_email,$from_name)
{
$headers = "MIME-Version: 1.0 \n" ;
$headers .= "From: " .
"".mb_encode_mimeheader (mb_convert_encoding($from_name,"ISO-2022-JP","AUTO")) ."" .
"<".$from_email."> \n";
$headers .= "Reply-To: " .
"".mb_encode_mimeheader (mb_convert_encoding($from_name,"ISO-2022-JP","AUTO")) ."" .
"<".$from_email."> \n";
$headers .= "Content-Type: text/plain;charset=ISO-2022-JP \n";
/* Convert body to same encoding as stated
in Content-Type header above */
$body = mb_convert_encoding($body, "ISO-2022-JP","AUTO");
/* Mail, optional parameters. */
$sendmail_params = "-f$from_email";
mb_language("ja");
$subject = mb_convert_encoding($subject, "ISO-2022-JP","AUTO");
$subject = mb_encode_mimeheader($subject);
$result = mail($to, $subject, $body, $headers, $sendmail_params);
return $result;
}
90年代早期,JUNET(基于UUCP的全国性网络)引入了日语编码电子邮件。
那时,定义了RFC1468。 如果您在纯文本邮件中遵循RFC1468,则没有问题。
如果你想处理html邮件,除了标题部分外,RFC1468是无用的。
这是我用来发送日语电子邮件的内容。主题行在Outlook 2010,gmail和iPhone上看起来很好。
Encoding encoding = Encoding.GetEncoding("iso-2022-jp");
byte[] bytes = encoding.GetBytes(subject);
string uuEncoded = Convert.ToBase64String(bytes);
subject = "=?iso-2022-jp?B?" + uuEncoded + "?=";
// not sure this is actually necessary...
mailMessage.SubjectEncoding = Encoding.GetEncoding("iso-2022-jp");