日语电子邮件主题编码

14
显然,编码日语邮件有些具有挑战性,我自己正在慢慢发现。如果有任何专家(即使是经验有限的人),我能否请教一些关于如何进行编码、如何测试和如何验证的指导方针?
请注意,我从未踏足日本,只是我正在开发的产品在那里以及其他地方被使用。
我知道的(我觉得)如下: - 日语电子邮件应该使用ISO-2022-JP、50220日语JIS代码页或可能的SHIFT_JIS代码页进行编码 - 邮件传输编码应设置为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类似,看起来是正确的。

我只是无法弄清楚这个问题。


你的假设是正确的,但我不确定语法,抱歉。 - Robert Gould
1
我只是想知道,为什么你不能只使用UTF-8呢? - Tamas Czinege
你“可以”使用UTF-8,但在日本的现实情况是,UTF-8仍然远远不及SHIFT_JIS。我在日本政府机构、企业和学校遇到的大多数机器和文档仍然使用SHIFT_JIS编码。 - Robert Gould
我有一个疑问。为什么在电子邮件中不应该使用Quoted-printable编码(Q编码)与iso-2022-jp字符集?为什么我们必须坚持使用Base 64编码(B编码)?请澄清一下。 - Roshan
如果原始字节的ASCII字符少于5/6,Base64会更节省空间。 - dan04
9个回答

23

我已经处理日语编码近20年了,所以我能理解你的困难。我曾经参与的网站每天向日本客户发送数百封电子邮件,所以我可以和你分享我们所使用的方法。

  • 首先,不要使用Shift-JIS编码。我个人收到了大量的日语电子邮件,几乎从来没有使用Shift-JIS进行编码。我认为旧版(约Win 98?)的Outlook Express使用Shift-JIS编码传出邮件,但是现在你几乎看不到这样做。

  • 正如你已经发现的那样,您需要使用ISO-2022-JP作为您的编码方式,至少对于任何进入邮件头部的内容都是如此。这包括主题、收件人行和抄送行。UTF-8在大多数情况下也可以使用,但是它在Yahoo Japan邮件中无法使用,而且可以想象,许多日本用户使用Yahoo Japan邮件。

  • 您可以在电子邮件正文中使用UTF-8编码,但建议您将UTF-8编码的日文文本进行Base64编码,并将其放入正文中,而不是使用原始的UTF-8文本。然而,在实践中,我认为现在原始的UTF-8文本在电子邮件正文中也可以正常工作。

  • 如我上面所提到的,您需要至少在Outlook(Exchange)、Outlook Express(IMAP/POP3)和Yahoo Japan网络邮件上进行测试。 Yahoo Japan是最棘手的,因为我认为他们在其网页的编码中使用了EUC,因此您需要按照正确的标准发送电子邮件,否则它们将无法正常工作(ISO-2022-JP是发送日语电子邮件的标准)。

  • 另外,您的主题行不应超过每行75个字符。也就是说,在经过ISO-2022-JP和Base64转换后,75个字符不要被超过,而不是在转换前。如果超过了75个字符,则需要将编码的主题拆分为多行,每行以“=?iso-2022-jp?B?”开始,并以每行的"?=" 结束。如果不这样做,您的主题可能会被截断(取决于电子邮件阅读器以及主题文本的内容)。根据RFC 2047:

"一个'encoded-word'不能超过75个字符,包括'charset'、'encoding'、'encoded-text'和分隔符。如果需要编码更多文本而不适合于一个75个字符的'encoded-word'中,则可以使用多个'encoded-word'(由CRLF SPACE分隔)。

  • 以下是一些用于编码主题的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,了解如何编码您的电子邮件标题的完整说明。

1
很棒的回复!雅虎邮件不仅支持UTF-8存在问题,大多数日本手机仍然不支持以UTF-8接收电子邮件,所以你只能使用iso-2022-jp。 - Elijah
实际上,我发现网络邮件服务和手机都支持Shift-JIS编码。它是可用编码中最紧凑的,所以我们选择了它,并且到目前为止没有遇到任何问题。 - bobince
最好坚持使用 iso-2022-jp 编码,至少在主题方面是如此,因为这是迄今为止最广泛支持的编码方式,特别是在手机领域。在大多数情况下,新手机(尤其是 Softbank)现在支持 utf-8,但一年以上的手机几乎肯定不支持 utf-8。还要注意不要使用 iso-2022-jp-ext,它与 iso-2022-jp 几乎相同,但我的经验是许多手机往往不支持扩展字符。 - si28719e

5

2

=?ISO-2022-JP?B?TEXTTEXT...

ISO_2022-JP 表示该字符串是使用 ISO-2022-JP 编码的(例如,不是 Unicode) B 表示该字符串是 base64 编码的

在您的示例中,您应该提供使用 ISO-2022-JP 而非 Unicode 编码的字符串。


1

在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]"

**明目张胆地抄袭/改编自:

http://mtokyo.blog9.fc2.com/blog-entry-127.html


1

我有一些在日语中撰写和发送电子邮件的经验...通常你必须注意操作系统使用的编码方式以及如何存储你的日语字符串!我的邮件对象通常被编码如下:

    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            
        }

0
<?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;
}

0

首先,你应该使用:

Encoding.GetEncoding("ISO-2022-JP")

将您的主题行转换为字节,以便由Convert.ToBase64String()处理。

=?ISO-2022-JP?B?TEXTTEXT...?=告诉接收邮件客户端发送方使用了哪种编码将日语“字母”转换为字节流。

目前,您正在使用UTF-16进行编码,但指定ISO-2022-JP进行解码。这显然是两种不同的编码方式,就像ISO-8859-1与Unicode不同(大多数扩展西欧字符在ISO-XXX中用一个字节表示,而在Unicode中用两个字节表示)。

我不确定您所说的UTF-8是二等公民的意思。只要接收邮件客户端理解UTF-8并能够将其转换为当前的日语区域设置,一切都没问题。


2
UTF-8在日本绝对是二等公民,令人沮丧的是,他们自己的标准也非常糟糕。手机浏览器刚刚开始支持它,还有一些网络邮件提供商无法理解传入的UTF-8邮件。这真是太可悲了。 - bobince

0

在90年代初,日本编码的电子邮件被引入到JUNET(基于UUCP的全国性网络)中。

当时,RFC1468被定义。如果您在纯文本邮件中遵循RFC1468,则不会出现问题。

如果您想处理HTML邮件,则除了标题部分外,RFC1468是无用的。


0

这是我用来发送日语电子邮件的方法。主题行在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");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接