Outlook以外のメールクライアントを使用しているのであれば、一度は目にしたことがある方も多いであろう「winmail.dat」。
今日久々にこのファイルを取り扱う機会があったので、折角なのでwinmail.datから添付ファイルを取り出すスクリプトを書いてみました。
winmail.datとは?
winmail.datとは、Microsoftのサポートページに詳しい説明が記載されています。
一般的に、TNEF の使用は Microsoft Outlook リッチ テキスト形式 (RTF) と呼ばれる Outlook の設定の影響を受けます。 リッチ テキスト形式と TNEF は全く同じではありませんが、密接に関連しています。
TNEF でエンコードされたメッセージには、メッセージのプレーン テキスト版と、オリジナル メッセージのその他のさまざまな部分を「パッケージ化する」バイナリ アタッチメントが含まれています。 ほとんどの場合において、バイナリ アタッチメントは Winmail.dat の名前が付けられており、次の情報が含まれていることがあります。
TNEF は、トランスポート ニュートラル カプセル化形式、Outlook リッチ テキスト形式、または Exchange リッチ テキスト形式とも呼ばれ、MAPI メッセージ プロパティをカプセル化する Microsoft 固有の形式です。 Outlook のすべてのバージョンが TNEF を完全にサポートします。 Web 上の Outlook (旧称 Outlook Web App) は TNEF を MAPI に変換し、書式設定されたメッセージを表示します。 TNEF をサポートしていないその他の電子メールクライアントでは、通常、TNEF 形式のメッセージが Winmail.dat または Win.ini 添付ファイル付きのプレーンテキストメッセージとして表示されます。
https://docs.microsoft.com/ja-jp/exchange/mail-flow/content-conversion/tnef-conversion より
要するに、Outlookからリッチテキスト形式のメールを送信したときに、TNEFをサポートしていないメールクライアントで受信すると、「winmail.dat」という名前の添付ファイルとして、メールの中身がまとめられてしまうわけですね。
TNEF対応のMimeKit
この「winmail.dat」を処理するにあたり、メール送信でお馴染みのMimeKitのドキュメントを見てみると、ちゃんとTNEFに対応していることが分かります。
今回はこのMimeKitを使って、winmail.datから添付ファイルを取り出してみたいと思います。
winmail.datから添付ファイルを取り出すC#コード
PowerShellでスクリプトを書く前に、まずは簡単にC#でコードを書いてみます。
MimeKitは事前にNuGetでインストールしておいてください。
/* * [winmail.dat]から添付ファイルを取り出すC#コード * ※MimeKit使用 */ using System; using System.IO; using MimeKit; using MimeKit.Tnef; namespace AttachmentsFromTnef { class Program { public static void Main(string[] args) { var tnef = new TnefPart(); tnef.Content = new MimeContent(File.OpenRead(@"C:\Test\winmail.dat"), ContentEncoding.Binary); foreach (var atth in tnef.ExtractAttachments()) { if (atth.IsAttachment == true) { var part = (MimePart)atth; using (var stm = File.Create(Path.Combine(@"C:\Test", part.FileName))) { part.Content.DecodeTo(stm); } } } Console.Write("Press any key to continue."); Console.ReadKey(true); } } }
参考資料が乏しく、インテリセンスを活用しながら適当に書きましたが、大体上記のような感じでコードが書けました。
あとはこれをPowerShellに書き換えていくだけです。
winmail.datから添付ファイルを取り出すPowerShellコード
$winmail_path = "C:\Test\winmail2.dat" #[winmail.dat]のパス [void][System.Reflection.Assembly]::LoadFile("C:\System\MimeKit\MimeKit.dll") #DLL読み込み $tnef = New-Object MimeKit.Tnef.TnefPart $tnef.Content = New-Object MimeKit.MimeContent([System.IO.File]::OpenRead($winmail_path), [MimeKit.ContentEncoding]::Binary) #[winmail.dat]と同じ場所に添付ファイル出力 foreach($atth in $tnef.ExtractAttachments()){ if($atth.IsAttachment -eq $true){ try{ $part = [MimeKit.MimePart]$atth $output_path = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($winmail_path), $part.FileName) $stm = New-Object -TypeName System.IO.FileStream -ArgumentList $output_path, Create $part.Content.DecodeTo($stm) }finally{ $stm.Dispose() } } }
C#と大体同じですね!
MimeKitのおかげで簡単に処理が書けました。
というわけで、winmail.datを処理するスクリプトを書いてみたわけですが、最近このファイルを見かける回数も減りましたし、需要はあまりないのではないかと思います
ましてや、「Winmail Opener」を使えば簡単にファイルを取り出せるので、大量にwinmail.datを処理する必要があるときくらいしか出番が無いスクリプトでしょう。
ただ、“MimeKitを使えばwinmail.datも処理できる”ことだけでも頭の片隅に置いておけば、いつか役立つときがくるかもしれません。
この記事へのコメントはありません。