无法在Web浏览器中邮件正文显示日文(UTF-8)字符
我正在从两个不同的.txt文件中读取文本,并把它们合并在一起。然后通过使用webbrowser
把这些内容放到电子邮件的正文里。
其中一个文本文件是英文字符(ascii),另一个是日文(UTF-8)。如果我把文本写入一个文本文件,它显示得很好。但是如果我用webbrowser
把文本插入到电子邮件正文中,日文就显示成问号了。
我尝试在多台机器上运行这个脚本,这些机器的默认邮件客户端不同。起初我以为这可能是问题所在,但似乎并不是。Thunderbird和Mail(MacOSX)都显示问号。
Hello. Today is 2014-05-09
????????????????2014-05-09????
我查看了StackOverflow上类似的问题,但没有找到解决办法。
有没有办法让日文(UTF-8)在用webbrowser
创建的电子邮件正文中正常显示?我可以使用email
功能,但要求是脚本需要打开默认的邮件客户端并插入所有信息。
下面是我使用的代码和文本文件。我简化了内容,以便专注于这个问题。
email-template.txt
Hello. Today is {{date}}
email-template-jp.txt
こんにちは。今日は {{date}} です。
Python脚本
#
# -*- coding: utf-8 -*-
#
import sys
import re
import os
import glob
import webbrowser
import codecs,sys
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
# vars
date_range = sys.argv[1:][0]
email_template_en = "email-template.txt"
email_template_jp = "email-template-jp.txt"
email_to_send = "email-to-send.txt" # finished email is saved here
# Default values for the composed email that will be opened
mail_list = "test@test.com"
cc_list = "test1@test.com, test2@test.com"
subject = "Email Subject"
# Open email templates and insert the date from the parameters sent in
try:
f_en = open(email_template_en, "r")
f_jp = codecs.open(email_template_jp, "r", "UTF-8")
try:
email_content_en = f_en.read()
email_content_jp = f_jp.read()
email_en = re.sub(r'{{date}}', date_range, email_content_en)
email_jp = re.sub(r'{{date}}', date_range, email_content_jp).encode("UTF-8")
# this throws an error
# UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 26: ordinal not in range(128)
# email_en_jp = (email_en + email_jp).encode("UTF-8")
email_en_jp = (email_en + email_jp)
finally:
f_en.close()
f_jp.close()
pass
except Exception, e:
raise e
# Open the default mail client and fill in all the information
try:
f = open(email_to_send, "w")
try:
f.write(email_en_jp)
# Does not send Japanese text to the mail client. But will write to the .txt file fine. Unsure why.
webbrowser.open("mailto:%s?subject=%s&cc=%s&body=%s" %(mail_list, subject, cc_list, email_en_jp), new=1) # open mail client with prefilled info
finally:
f.close()
pass
except Exception, e:
raise e
编辑:忘了说我使用的是Python 2.7.1
1 个回答
编辑 2: 最终找到一个可行的解决方案。
把你的 webbrowser 调用替换成这个。
import subprocess
[... other code ...]
arg = "mailto:%s?subject=%s&cc=%s&body=%s" % (mail_list, subject, cc_list, email_en_jp)
subprocess.call(["open", arg])
这会在 MacOS 上打开你默认的邮件客户端。对于其他操作系统,请在 subprocess 这一行把 "open" 替换成相应的可执行文件。
编辑: 我进一步研究了一下,Mark 上面的评论让我去阅读了 RFC (2368),这是关于 mailto URL 方案的。
特殊的 hname "body" 表示相关的 hvalue 是消息的
正文。 "body" hname 应该包含消息的
第一个 text/plain 正文部分的内容。mailto URL 主要是为了生成短文本消息,这些消息实际上是自动处理的内容(比如订阅邮件列表的消息),而不是一般的 MIME 正文。
再往下看:
在 mailto URLs 中,禁止使用 8 位字符。MIME 编码的单词(如 [RFC2047] 中定义的)在头部值中是允许的,但不适用于 "body" hname 的任何部分。
所以根据 RFC 的规定,这似乎是不可能的,尽管这让我怀疑 naota 提供的 JSFiddle 中的 JavaScript 解决方案为什么能工作。
我把之前的回答保留在下面,尽管它并不有效。
我在使用 Python 2.7.x 时遇到过同样的问题好几次,每次都有不同的解决方案能成功。
所以这里有几个建议,可能有效也可能无效,因为我没有测试过。
a) 强制使用 Unicode 字符串:
webbrowser.open(u"mailto:%s?subject=%s&cc=%s&body=%s" % (mail_list, subject, cc_list, email_en_jp), new=1)
注意在开头的 ( 后面和 " 前面有个小 u。
b) 强制正则表达式使用 Unicode:
email_jp = re.sub(ur'{{date}}', date_range, email_content_jp).encode("UTF-8")
# or maybe
email_jp = re.sub(ur'{{date}}', date_range, email_content_jp)
c) 关于正则表达式的另一个想法,尝试先用 re.UNICODE 标志编译它,然后再应用。
pattern = re.compile(ur'{{date}}', re.UNICODE)
d) 虽然不直接相关,但我注意到你是通过普通的 open 方法写入组合文本。这里也尝试使用 codecs.open。
f = codecs.open(email_to_send, "w", "UTF-8")
希望这能帮到你。