3

ファイル名に Unicode 文字が含まれるファイルが添付されたメールを送信するにはどうすればよいですか?

これまでのところ、ファイルは到着しますが、ファイル名は"noname"です。

これは、ASCII ファイル名に対して完全にうまく機能する部分です。

import smtplib
from email.mime.text import MIMEText
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.Utils import formatdate
from email import Encoders
from email.Utils import encode_rfc2231

msg = MIMEMultipart()
msg['Subject'] = "New magazine delivery!"
msg['From'] = sender_email
msg['To'] = ', '.join(kindle_emails)
msg['Date'] = formatdate(localtime=True)
message = "see attachment"
msg.attach(MIMEText(message))
part = MIMEApplication(open(f, 'rb').read(), _subtype='application/x-mobipocket-ebook')

part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(filename)
msg.attach(part)

初挑戦

ファイル名だけでなく、エンコーディング、言語、およびエンコードされた文字列のタプルを追加します。

part.add_header('Content-Disposition', 'attachment', filename=('utf-8', 'fr', os.path.basename(f).encode('utf-8')))

2 回目の試行:

次のように文字セットをグローバルに設定します。

from email import Charset
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')

3 回目の試行

使用するutils.encode_rfc2231

from email.Utils import encode_rfc2231
utf8filename = encode_rfc2231(os.path.basename(f).encode('utf-8'), charset='utf-8')
part.add_header('Content-Disposition', 'attachment', filename=('utf-8', 'fr', utf8filename))

4 回目の試行

urllib.quote()ファイル名を urlencode するために使用します。これは、ファイル名に対して 3 番目の方法と同じ効果があります。

utf8filename = urllib.quote(os.path.basename(f).encode('utf-8'))
part.add_header('Content-Disposition', 'attachment', filename=('utf-8', 'fr', utf8filename))

何か案は?

RFC2231 ファイル名の文字エンコーディングに関する重要な点が欠けていますか?

Gmail の SMTP サーバーと python 2.7 を使用しています。

4

2 に答える 2

4

サーバーに UTF-8 であることを伝える代わりに、次のようにします。

filename=('utf-8', 'fr', os.path.basename(f).encode('utf-8'))

...そう言わずにUTF-8を送信するだけで機能します:

filename=os.path.basename(f).encode('utf-8')

ファイル名が正しく表示されます。

これは、次のように記載されているドキュメントと矛盾しているようです。

値に非 ASCII 文字が含まれている場合は、(CHARSET、LANGUAGE、VALUE) の形式で 3 つのタプルとして指定する必要があります。ここで、CHARSET は、値をエンコードするために使用する文字セットを指定する文字列です。LANGUAGE は通常、次のように設定できます。 None または空の文字列 (その他の可能性については RFC 2231 を参照)、VALUE は非 ASCII コード ポイントを含む文字列値です。

これは機能しませんが、python 3 のドキュメントには以下が追加されています。

3 つのタプルが渡されず、値に非 ASCII 文字が含まれている場合、utf-8 の CHARSET と None の LANGUAGE を使用して、RFC 2231 形式で自動的にエンコードされます。

ドキュメントには記載されていませんが、python 2.7でもこれだけが機能します。

于 2016-01-08T11:08:56.023 に答える