質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.95%

Python:日本語を含む添付ファイル(CSV)をメール送信すると、アウトルックで テキストファイルとして表示されてしまう

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,415

score 166

日本語を含まない半角英数字だけの添付ファイル名であれば 受信側アウトルックで ちゃんとCSVファイルとして表示されます。

こちらの記事を参考に対処に努めたのですが、テキストファイルを送付されている事例がゆえ、自分の適用方法に問題があるのか うまくいきません(テキストファイルとして、かつ無名の添付ファイルと OUTLOOK上で表されてしまいます)

どなたか対策を ご教示頂けませんでしょうか
よろしくお願い致します。

def send_Mail(self, toaddress, ccaddress, bccaddress, subject, body, filepath, parent):
        try:

            cset = 'utf-8'
            msg = MIMEMultipart()
            msg["Subject"] = subject
            msg["From"] = self.mlsrv_fraddress
            msg["To"] = toaddress
            msg["Cc"] = ccaddress
            msg["Bcc"] = bccaddress
            msg["Date"] = formatdate()
            body = MIMEText(body.encode(cset), 'plain', cset)
            msg.attach(body)


            if not (filepath == ""):

                filename = os.path.basename(filepath)
                with open(filepath, 'rt', encoding='Shift-JIS') as f:
                        content = f.read()
                        attachment = MIMEText(content, 'plain', 'Shift-JIS')
                        attachment.set_param('name', filename)                          #アウトルックのための対応
                        attachment.add_header('Content-Disposition', 'attachment', filename=('iso2022-jp', '', filename))
                msg.attach(attachment)


            to_cc_bcc =  [toaddress, ccaddress, bccaddress]
            while True:
                if ("" in to_cc_bcc):
                    delindex = to_cc_bcc.index("")
                    del to_cc_bcc[delindex]
                else:
                    break



            smtp = smtplib.SMTP(self.mlsrv, self.mlsrv_port)
            smtp.login(self.mlsrv_id, self.mlsrv_pw)

            result = smtp.sendmail(self.mlsrv_fraddress, to_cc_bcc, msg.as_string())

        except Exception as e:
            tkmb.showerror("Abort", e, parent=parent)
            result = 500
        finally:
            return result

20200628 画像差替え

決定的な違い発見

20200702 03:37AM コメントに記載した画像追加

確認

20200702 16:12PM 現況の添付ファイルに関わるコード

filename = os.path.basename(filepath)
with open(filepath, 'rt', encoding='Shift-JIS') as f:
    content = f.read()
    attachment = MIMEText(content, 'plain', 'Shift-JIS', policy=policy.SMTP)
    contentType = Header('text/comma-separated-values;', header_name='Content-Type')
    contentType.append('name="')
    contentType.append(filename, charset='iso-2022-jp')
    contentType.append('"')
    attachment['Content-Type'] = contentType
    contentDisp = Header('attachment;', header_name='Content-Disposition')
    contentDisp.append('filename="')
    contentDisp.append(filename, charset='iso-2022-jp')
    contentDisp.append('"')
    attachment['Content-Disposition'] = contentDisp

20200702 16:56 del文 追加

filename = os.path.basename(filepath)
with open(filepath, 'rt', encoding='Shift-JIS') as f:
    content = f.read()
    attachment = MIMEText(content, 'plain', 'Shift-JIS', policy=policy.SMTP)
    contentType = Header('text/comma-separated-values;', header_name='Content-Type')
    contentType.append('name="')
    contentType.append(filename, charset='iso-2022-jp')
    contentType.append('"')
    del attachment['Content-Type']
    attachment['Content-Type'] = contentType
    contentDisp = Header('attachment;', header_name='Content-Disposition')
    contentDisp.append('filename="')
    contentDisp.append(filename, charset='iso-2022-jp')
    contentDisp.append('"')
    attachment['Content-Disposition'] = contentDisp
    prtin(attachment)

20200702 20:41 最新PGとその実行結果

filename = os.path.basename(filepath)
with open(filepath, 'rt', encoding='Shift-JIS') as f:
    content = f.read()
    attachment = MIMEText(content, 'plain', 'Shift-JIS')
    contentDisp = Header('attachment;', header_name='Content-Disposition')
    contentDisp.append('filename="')
    contentDisp.append(filename, charset='iso-2022-jp')
    contentDisp.append('"')
    attachment['Content-Disposition'] = contentDisp
    print(attachment)


print文の結果とemlをエディタで確認

20200703 0829 結果添付

MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Type: text/comma-separated-values; charset="shift-jis"; name="=?iso-2022-jp?b?MjAyMDA3MDMwODI3NTcuY3N2?="
Content-Disposition: attachment; filename="=?iso-2022-jp?b?MjAyMDA3MDMwODI3NTcuY3N2?="
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

問題はset_paramadd_headerにであります。Python公式ドキュメントより email.message.Message.add_header

it is automatically encoded in RFC 2231 format

set_paramadd_headerは RFC 2231 を従って、このフォーマットにエンコードしています:

title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A

しかし、Outlookはより古いの RFC 2047 だけを従っています、つまりこのフォーマットしか認識してないのです:

=?iso-8859-1?q?this=20is=20some=20text?=

このフォーマットを使いたいなら、add_headerではなく、Headerクラスを使うべきです。

from email.header import Header
contentType = Header('text/comma-separated-values;', header_name='Content-Type', linesep='\r\n')
contentType.append('name="')
contentType.append(filename, charset='iso-2022-jp')
contentType.append('"')
attachment['Content-Type'] = contentType
contentDisp = Header('attachment;', header_name='Content-Disposition', linesep='\r\n')
contentDisp.append('filename="')
contentDisp.append(filename, charset='iso-2022-jp')
contentDisp.append('"')
attachment['Content-Disposition'] = contentDisp

参考と問題を分析しただけの結果ですので、100%の把握がないけど、お役に立てたら幸いです。

参考:
c# - japanese email subject encoding - Stack Overflow
The mess that is attachment filenames – Nodemailer. Blog

追記

問題文と合わせたら、with openのブロックはこうなります:

from email import policy

with open(filepath, 'rt', encoding='Shift-JIS') as f:
    content = f.read()
    attachment = MIMEText(content, 'plain', 'Shift-JIS', policy=policy.SMTP)
    contentType = Header('text/comma-separated-values;', header_name='Content-Type', linesep='\r\n')
    contentType.append('name="')
    contentType.append(filename, charset='iso-2022-jp')
    contentType.append('"')
    attachment['Content-Type'] = contentType
    contentDisp = Header('attachment;', header_name='Content-Disposition', linesep='\r\n')
    contentDisp.append('filename="')
    contentDisp.append(filename, charset='iso-2022-jp')
    contentDisp.append('"')
    attachment['Content-Disposition'] = contentDisp

追記 1

Headerクラスはデフォルトで\nを使って行を区切りますが、それはRFCにあっていません。linesep='\r\n'をしてみましょう。上記のコードも訂正します。

MIMETextを構築するときも、policyという引数のデフォルトはcompat32であり、行終端を\r\nで指定しています。policyemail.policy.SMTPにしてみましょう。

SMTP.sendmail\n\r\nに変換しますので、上記の必要がありません。

追記 2

少なくともOutlookが RFC 2047 を従ってるはずと思った僕は甘すぎたかもしれません。もっとOutlookのバーションに接近しなきゃいけなさそうです。

数えたら、Outlookのencoded wordの一区切りの長さは54、RFC 2047の75と違っています。そして二重引用符の中に行終端がありません。この二つを訂正していきましょう。

こうしたら残した一致してないところは;後の行終端だけなはずですが、どうなりますかね。とりあえず試してみてください。

with open(filepath, 'rt', encoding='Shift-JIS') as f:
    content = f.read()
    attachment = MIMEText(content, 'comma-separated-values', 'Shift-JIS')
    filename_rfc2047 = Header(filename, 'iso-2022-jp', maxlinelen=55).encode().replace('\n', '')
    attachment.set_param('name', filename_rfc2047)
    attachment.add_header('Content-Disposition', 'attachment', filename=filename_rfc2047)
    print(attachment)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/03 11:08

    ごめんなさい、mag.attach(attachment) という行がありませんでした。
    本当にコピペで ご提示のコードだけにしてしまっていて。

    今から入れて実行します。

    キャンセル

  • 2020/07/03 11:14

    XD 今までちゃんと attach してなかったですね。まさかと思いましたけど、失礼だと思ったので提示しませんでした。ごめんなさい。:P
    解決できたら何よりです。XD

    キャンセル

  • 2020/07/03 11:32

    YufanLouさん、yymmtさん
    ***************長い間 お付き合いを頂き ありがとうございました**************
    和名のCSVファイル とうとう アウトルックに 添付ファイルとして現れました。
    ********************************************************************

    YufanLouさんから 20200703 07:43AM  にご提示頂きましたコードは 完全なもので
    mag.attach(attachment) を つけ忘れていた だけでお騒がせ致しました。

    だいぶ添付ファイルがついていない、との報告を繰り返し時間を費やしてしまいましたが
    これは まさに 私の不貞際です、何卒ご容赦ください。

    諦めずにゴールまで導いて頂き 本当に感謝しております、一人では 到底ここまで いきつくことはできませんでした。

    ありがとうございました。

    キャンセル

0

attachment = MIMEText(content, 'plain', 'Shift-JIS')


とありますが、'plain' の部分は 'csv' とすべきではないでしょうか。

https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types `によれば、CSV の mime type は text/csv なようです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/21 07:30

    cugelさん、ご見解ありがとうございました。
    csvに変更しましたが、状況は変わらず OUTLOOK側では 無題のテキストファイルとして表示されてしまいました。WebのメーラだとちゃんとCSVファイルの添付ファイルとして表示されているのですが

    キャンセル

0

気になる箇所としては文字コードの指定でしょうか。isoと2022の間にハイフンを入れたらどうなりますか?

filename=('iso-2022-jp', '', filename)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/02 03:37

    長期に渡るお付き合い 誠にありがとうございます。
    私の適用方法が悪いのか、半角英数字の名前にしたCSVファイルをも、現在はメールに添付ファイルとして現れなくなりました。またそれはOUTLOOKのみならずWebメールでも、です。
    本文にプリント文の結果画像、及びWebメール(.eml)をエディタで確認した画像を貼り付け致します。

    ご確認を頂けましたら幸いです。(今から貼り付けます)

    キャンセル

  • 2020/07/02 10:32

    こちらこそ、ヘッダをみないと形式の問題を気付けないのです。
    公式ドキュメントにHeaderインスタンスを['Content-Type']で直接にsetできるようにみましたが、検証しなかったので、そうできなければsaya24さんはyymmtさんの上記のコードに参考してください。

    キャンセル

  • 2020/07/02 10:52

    色入とありがとうございます。決算業務落ち着いたら 適用対応します。少々お待ちくださいませ

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.95%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Pythonに関する質問
  • Python:日本語を含む添付ファイル(CSV)をメール送信すると、アウトルックで テキストファイルとして表示されてしまう