はじめに
メールの文字化け対策について調査を行っていました。それで副次的に気がついたのですが、メールサーバやメールリーダーが「ヘッダ」だけでなくメールの「本文」の修正を行う事があるようです。
マジか!
修正内容について調査してみました。
初めにメールサーバによる書き換えを調査します.
(結論を先に述べると、Office365(クラウド)はHTMLのタグの改行空白の修正が入ります。)
続いてOffice2019(Win)による書き換えを調査します.
(結論を先に述べると、Plain/HTMLのAlternativeメールは、Office2019(Win+IMAP)でメールのコピー作業を行うと,IMAPサーバ上の元メールとコピーしたメールの内容が書き換わってます.HTMLの内容に合わせてPlainの内容が書き換わります。)
※注意: 無料版のOutlookのメールアカウントは単純な内容のメール(例えば本文が「テスト」一行のメールなど)を多数送受信するとアカウントロックされる事があるようです。ご注意ください。以下の調査は職場で契約しているOffice365を用いてます。(Office365は職場の管理者が色々設定している可能性があるため,無料版Outlookで試したかったのですが,断念しました.)
事前準備
職場のメールアドレス(CentOS7/Postfix)を用意しました.続いてOffice365のメールアドレスとgmail(クラウド)のメールアドレスを準備しました。
- 職場のメール: 職場のアドレス@example.com (CentOS7/Postfix)
- Gmailメール: テストアドレス@gmail.com
- Office365メール: テストアドレス@outlook.com
Mewで上記の3つのアドレスを読み書きできるようにしてください.
Gmailは「安全性の低いアプリの許可」をオンにしないと読めないと思います.Office365は特になにもしないでもimapで読めましたが(職場で契約したものなので)無料版のOutlookでも同様かはわかりません.
サンプルメール1(PLAIN+HTML)
以下のようなファイルを用意しました.JISコードで作成したPLAINテキストおよび,ほぼ同じ内容のHTMLファイルです.
転送時にファイルが書き換えられるかのテスト(20210629)
*送信元(Mew6.8/JIS)*
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
</head>
<body>
転送時にファイルが書き換えられるかのテスト(20210629)<BR>
<b>送信元(Mew6.8/JIS)</b>
</body>
</html>
サンプルメール2(内容差分)
以下のようなファイルを用意しました.JISコードで作成したPLAINテキストおよび,内容が異なるHTMLファイルです.Plainテキストの「差分txt」がHTMLでは「差分html」に修正しています.
転送時にファイルが書き換えられるかのテスト(20210629)
*送信元(Mew6.8/JIS)/差分txt*
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
</head>
<body>
転送時にファイルが書き換えられるかのテスト(20210629)<BR>
<b>送信元(Mew6.8/JIS)/差分html</b>
</body>
</html>
Mewのマルチパートで送信
テストメールをMewで作成します.テストメールをOutlookやThunderbirdで作成すると,メールリーダーがどのようなメールを作成するか確認し辛いので,Mewで無理やり同等のマルチパートメールを作成します.
そのため,少々めんどくさい操作しています.
次の組み合わせでMewのマルチパートで送信してみます.
-サンプルメール1(PLAIN+HTML): 書換テストjis.txt / 書換テストjis.html
-サンプルメール2(内容差分): 書換テストdiff.txt / 書換テストdiff.html
ここでMewで送信時の注意点ですが、
- Mewの本文にはなにも書かない.
- Multipart/MixedからAlternativeしてください(Tで修正).
- ファイル名を無しにしてください(Pで修正). ファイル名を消すと
「xxxx.txt」から「*xxxx.txt」に修正されます.
こんな感じです.
To: テストアドレス@gmail.com, テストアドレス@outlook.com
Subject: 添付ファイルが書き換えられるかのテスト(20210629)/JIS
From: 職場のアドレス@example.com
Dcc: 職場のアドレス@example.com
X-Mailer: Mew version 6.8 on Emacs 24.3
----
(本文にはなにも書かない.)
------------------------------ attachments ------------------------------
Multipart/Alternative (←MixedからAlternativeに修正) 3/
1 Text/Plain(guess) *Cover.txt
2 Text/Plain(guess) *書換テストji.
3 Text/Html(guess) *書換テストji..
4 .
--------0-1-2-3-4-5-6-7-8-9----------------------------------------------
Mew6.8(CentOS7.9)から職場のメールサーバ経由でOffice365/gmailのメールサーバに送信します。
Mew6.8 → SMTP → 職場のメールサーバ(CentOS7) → SMTP → (クラウド)Office365/Gmail
サンプルメール1(PLAIN+HTML)を送信して,続いてサンプルメール2(内容差分)を送信してください.
To: テストアドレス@gmail.com, テストアドレス@outlook.com
Subject: 添付ファイルが書き換えられるかのテスト(20210629)/diff
From: 職場のアドレス@example.com
Dcc: 職場のアドレス@example.com
X-Mailer: Mew version 6.8 on Emacs 24.3
----
(本文にはなにも書かない.)
------------------------------ attachments ------------------------------
Multipart/Alternative 3/
1 Text/Plain(guess) *Cover.txt
2 Text/Plain(guess) *書換テストdi..
3 Text/Html(guess) *書換テストdi..
4 .
--------0-1-2-3-4-5-6-7-8-9----------------------------------------------
メールサーバによる修正
サンプルメール1(PLAIN+HTML)
GmailとOffice365に送ったメールをMewで取り込んでください.
オリジナルのメールとdiffを取ってみます.
-
Gmailは本文修正なしです.
-
Office365は本文のHTMLパートに以下の修正が入ります.HTMLの細かな修正がはいります.
$ diff -uwi jis_org.eml jis_office365.eml
(diffの出力は一部割愛)
----Next_Part(Tue_Jun_29_10_03_27_2021_939)--
Content-Type: Text/Plain; charset=iso-2022-jp
@@ -31,8 +131,7 @@
Content-Type: Text/Html; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
-<html>
- <head>
+<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
</head>
<body>
サンプルメール2(内容差分)の差分
Gmailは修正なし.Office365はサンプルメール1(JIS)とほぼ同じです.
メールリーダーによる修正
先ほど確認した書換はメールサーバによるものですが、次にメールリーダでの修正について確認します。
職場のメールサーバにOffice2019(Win10+IMAP)で接続します。Office2019での操作でサンプルメール1と2を別のフォルダにコピー作業を行ってみます.(移動では確認してません.)
こんな形になります.
Office2019(Win) → IMAP → 職場のメールサーバ(CentOS7)
IMAPのため,Office2019上でコピー作業すると,IMAPサーバ上のファイルのコピーが発生します.
コピー後,コピーしたメールを再びMewで取り込みます.
サンプルメール1(PLAIN+HTML)の差分
コピーしただけでは何も起きないと思いますよね.そんな事はなかったりします.
ヘッダ部分は読みにくいので文章で説明しますが,
- Subjectの改行位置の修正
-Subject: =?iso-2022-jp?B?GyRCRTpJVSVVJSElJCVrJCw9cRsoQg==?=
- =?iso-2022-jp?B?GyRCJC00OSQoJGkkbCRrJCskThsoQg==?=
- =?iso-2022-jp?B?GyRCJUYlOSVIGyhCKDIwMjEwNjI5KS9KSVM=?=
+Subject: =?iso-2022-jp?B?GyRCRTpJVSVVJSElJCVrJCw9cSQtNDkkKCRpJGwkayQrJE4lRiU5GyhC?=
+ =?iso-2022-jp?B?GyRCJUgbKEIoMjAyMTA2MjkpL0pJUw==?=
- From/Toなどのアドレス表記の修正。アドレスは多数あるので抜粋です。
修正前:
- 職場のメール <職場のアドレス@example.com>
- テストアドレス@outlook.com
修正後:
- "職場のメール" <職場のアドレス@example.com>
- <テストアドレス@outlook.com>
- MIMEのboundaryの変更
Content-Type: Multipart/Alternative;
- boundary="--Next_Part(Tue_Jun_29_10_03_27_2021_939)--"
+ boundary="----=_NextPart_000_002D_01D76CD0.721A1BB0"
- ヘッダ部からの追加削除
削除:
Content-Transfer-Encoding: 7bit
追加:
(省略)
続いて本文への修正ですが、
-
(前述しましたが)boundary修正
-
「This is a multipart message in MIME format.」追加
-
Plainテキストの修正
「*」除去.← ちょっとこれなに -
Encodeが7bit からquoted-printable修正.
$ diff -uwi jis_org.eml jis_office2019.eml
(diffの出力は一部割愛)
+This is a multipart message in MIME format.
-----Next_Part(Tue_Jun_29_10_03_27_2021_939)--
-Content-Type: Text/Plain; charset=iso-2022-jp
+------=_NextPart_000_002D_01D76CD0.721A1BB0
+Content-Type: text/plain;
+ charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
転送時にファイルが書き換えられるかのテスト(20210629)
-*送信元(Mew6.8/JIS)*
+送信元(Mew6.8/JIS)
-----Next_Part(Tue_Jun_29_10_03_27_2021_939)--
-Content-Type: Text/Html; charset=iso-2022-jp
-Content-Transfer-Encoding: 7bit
+------=_NextPart_000_002D_01D76CD0.721A1BB0
+Content-Type: text/html;
+ boundary="--Next_Part(Tue_Jun_29_10_03_27_2021_939)--";
+ charset="iso-2022-jp"
+Content-Transfer-Encoding: quoted-printable
<html>
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
+ <meta http-equiv=3D"Content-Type" content=3D"text/html; =
+charset=3Diso-2022-jp">
</head>
<body>
- 転送時にファイルが書き換えられるかのテスト(20210629)<BR>
- <b>送信元(Mew6.8/JIS)</b>
+ =1B$BE>Aw;~$K%U%!%$%k$,=3Dq$-49$($i$l$k$+$N%F%9%H=1B(B(20210629)<BR>
+ <b>=1B$BAw?.85=1B(B(Mew6.8/JIS)</b>
</body>
</html>
-----Next_Part(Tue_Jun_29_10_03_27_2021_939)----
+------=_NextPart_000_002D_01D76CD0.721A1BB0--
サンプルメール2(内容差分)の差分
このサンプルはPlainテキストとHTMLで文章の内容が異なります.Plainテキストの「差分txt」がHTMLでは「差分html」に修正しています.
サンプルメール1と同じのは割愛しますが,
- Plainテキストの修正。
「差分txt」が「差分html」に差し替え.← ちょっとこれなに
$ diff -uwi jis_org.eml jis_office2019.eml
(diffの出力は一部割愛)
+This is a multipart message in MIME format.
-----Next_Part(Tue_Jun_29_10_08_49_2021_742)--
-Content-Type: Text/Plain; charset=iso-2022-jp
+------=_NextPart_000_0026_01D76CD0.71D76D60
+Content-Type: text/plain;
+ charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
転送時にファイルが書き換えられるかのテスト(20210629)
-*送信元(Mew6.8/JIS)/差分txt*
+送信元(Mew6.8/JIS)/差分html
-----Next_Part(Tue_Jun_29_10_08_49_2021_742)--
-Content-Type: Text/Html; charset=iso-2022-jp
-Content-Transfer-Encoding: 7bit
+------=_NextPart_000_0026_01D76CD0.71D76D60
+Content-Type: text/html;
+ boundary="--Next_Part(Tue_Jun_29_10_08_49_2021_742)--";
+ charset="iso-2022-jp"
+Content-Transfer-Encoding: quoted-printable
<html>
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
+ <meta http-equiv=3D"Content-Type" content=3D"text/html; =
+charset=3Diso-2022-jp">
</head>
<body>
- 転送時にファイルが書き換えられるかのテスト(20210629)<BR>
- <b>送信元(Mew6.8/JIS)/差分html</b>
+ =1B$BE>Aw;~$K%U%!%$%k$,=3Dq$-49$($i$l$k$+$N%F%9%H=1B(B(20210629)<BR>
+ <b>=1B$BAw?.85=1B(B(Mew6.8/JIS)/=1B$B:9J,=1B(Bhtml</b>
</body>
</html>
-----Next_Part(Tue_Jun_29_10_08_49_2021_742)----
+------=_NextPart_000_0026_01D76CD0.71D76D60--
というようにPLAINテキストとHTMLのAlternative属性のメールはHTMLに準じてPlainテキスト部が修正されます.
その他の修正
上記以外にOutlook2019(Win+IMAP)でファイルのコピー作業をすると,以下の修正が入るようです.詳細は省略します.
-
(常に発生)添付ファイルのファイル名(Content-Disposition: filename)が
RFC2231の場合は,Base64形式(=?charset?B?.....?=)に修正.Mewで添付ファイル「一二三四五六七八.txt」を添付し,職場メールサーバに送信後Outlook2019(Win+IMAP)でファイルのコピー操作を実施した例です.
追記:よく見たら添付ファイルの「charset=iso-2022-jp」指令が無くなってるので確認したらBASE64をdecodeしたらこれShift-JISじゃないか。。
$ diff -uwi jp-filename-mew.eml jp-filename-office2019.eml
(diffの出力は一部割愛)
-----Next_Part(Tue_Jun_29_14_58_42_2021_099)--
-Content-Type: Text/Plain; charset=iso-2022-jp
+This is a multipart message in MIME format.
+
+------=_NextPart_000_000C_01D76CF7.585CFD10
+Content-Type: text/plain;
+ boundary="--Next_Part(Tue_Jun_29_14_58_42_2021_099)--";
+ charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
ファイル名命名規則の修正
-----Next_Part(Tue_Jun_29_14_58_42_2021_099)--
-Content-Type: Text/Plain; charset=iso-2022-jp;
- name="=?iso-2022-jp?B?GyRCMGxGczswO004Xk87PDdILBsoQi50eHQ=?="
-Content-Transfer-Encoding: 7bit
-Content-Disposition: inline;
- filename*=iso-2022-jp''%1B%24B0lFs%3B0%3BM8%5EO%3B%3C7H%2C%1B%28B%2Etxt
+------=_NextPart_000_000C_01D76CF7.585CFD10
+Content-Type: Text/Plain;
+ name="=?iso-2022-jp?B?GyRCMGxGczswO004Xk87PDdILBsoQi50eHQ=?="
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="=?iso-2022-jp?B?GyRCMGxGczswO004Xk87PDdILBsoQi50eHQ=?="
-ファイル名: 一二三四五六七八.txt
+g3SDQINDg4uWvDogiOqT8Y5PjmyM3JhajrWUqi50eHQNCg==
-----Next_Part(Tue_Jun_29_14_58_42_2021_099)----
+------=_NextPart_000_000C_01D76CF7.585CFD10--
-
(まれに発生)添付ファイルのファイル名やSubjectがBase64(=?charset?B?.....?=)
からQuoted Printable形式 (=?charset?Q?=16進数...?=)に修正. -
base64の幅が72文字の場合は76文字に修正.(これがあるのでdiff取る時は注意)
補足:diffとる時は次のスクリプトが役にたつかも.BASE64の添付ファイル部分を削ります。ファイルを書換えるのでバックアップ後実施ください.
# !/usr/bin/perl
#
# 頭が悪い実装.
# 72文字-76文字の行が5行続いたらBASE64と判断
for my $i (@ARGV){
next unless(-f $i);
my $bakfile = $i . ".bak";
rename ($i , $bakfile) or die;
open(FILE, "< ", $bakfile) or die;
my $tmp=join("",<FILE>);
close(FILE);
open(FILE, ">", $i) or die;
#print $tmp;
$tmp =~ s/\n[\da-zA-Z\+\/]{72,76}\n[\da-zA-Z\+\/]{72,76}\n[\da-zA-Z\+\/]{72,76}\n[\da-zA-Z\+\/]{72,76}\n[\da-zA-Z\+\/]{72,76}\n[\da-zA-Z\+\/\=\n]+/\nStripBASE64\n/g;
print FILE $tmp;
close(FILE);
}
以上です。