|
.NET Framework 4のメール送信で、長い日本語ファイル名の添付をする方法
.NET Framework 4のSystem.Net.Mail.SmtpClientでメールを送信する際
長い日本語ファイル名の添付でエラーが発生して送信ができない事象が発生しました。
以下がその時のエラー内容となります。
System.IO.IOException: 転送接続にデータを書き込めません: 既存の接続はリモート ホストに強制的に切断されました。。 ---> System.Net.Sockets.SocketException: 既存の接続はリモート ホストに強制的に切断されました。
場所 System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
パケットキャプチャをしたところ、原因はメール内容にLF改行が含まれていたせいとなります。(bare LF問題)
なぜ、LF改行が存在していたかというと、長い日本語ファイル名の添付ファイルが原因でした。
こちらのサイトに詳しく記載されておりますのでご参照ください。
.NET Framework 4 のメール送信で、長い日本語ファイル名の添付に失敗する原因を追ってみた
Attachment.PrepareForSendingがSystem.Net.Mail.Attachmentの
プライベートなメンバ変数nameの値を利用して再変換をかけているので
リフレクションを利用してエンコード済みの文字列に値を書き換えることで解決しました。
MailMessage msg = new MailMessage();
string filePath = @"C:\あかさたなはまやらわあかさたなはまやらわ.txt";
System.Net.Mail.Attachment at = new System.Net.Mail.Attachment(filePath);
// ファイル名をRFC2047形式にエンコード
string fileName = new System.IO.FileInfo(filePath).Name;
fileName = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(fileName));
fileName = string.Format("=?{0}?B?{1}?=", System.Text.Encoding.UTF8.BodyName, fileName);
// エンコード後文字列をSystem.Net.Mail.Attachmentのプライベートなメンバ変数nameに代入
System.Type t = typeof(System.Net.Mail.Attachment);
t.InvokeMember("name", System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.SetField,
null,
at,
new object[] { fileName });
msg.Attachments.Add(at);
実行結果
Content-Type: application/octet-stream; name="=?utf-8?B?44GC44GL44GV44Gf44Gq44Gv44G+44KE44KJ44KP44GC44GL44GV44Gf44Gq44Gv44G+44KE44KJ44KPLnR4dA==?="
関連するページ
メモ > PHP > 変数関連
メモ > JavaScript > 文字列関連
メモ > Android > Galaxy S2 LTE(SC-03D)の電池アイコンを変更する
メモ > Java > 文字列関連
メモ > Java > java.text.MessageFormat