2015年10月6日火曜日

【C#】Outlook addin で RTF形式メールへのファイル添付処理(その後)

RTF形式メールに添付するとOutlookが落ちる問題の続き。

問題は、添付されたファイルをZIP書庫に圧縮する処理を入れようとして見つけたものです。
いろいろやって回避できそうな方法を見つけたので解説しておきます。


メールへの添付ファイルをZIP書庫に変更するには、次のイベントを処理します。

・ファイルが添付される直前に呼び出されるイベント
Outlook.ItemEvents_10_BeforeAttachmentAddEventHandler
void beforeAttachmentAdd(Outlook.Attachment attachment, ref bool Cancel)
パラメータは、添付されるファイルの情報と、問い合わせなどでの中断可能なフラグ参照。

添付されたファイルをZIP書庫に圧縮して添付する処理を考える場合、次のような手順で実現します。
void beforeAttachmentAdd(Outlook.Attachment attachment, ref bool Cancel)
{
    //一時ファイルに添付ファイルを保存
    string work_file = 一時ファイル名;
    attachment.SaveAsFile(work_file);

    //一時ファイルをZIP圧縮
    string zip_file = ZIP書庫名;
    ZIP書庫を作成する処理();

    //添付ファイルを入れ替える
    Outlook.Attachments attachments = attachment.Parent.Attachments;
    attachments.Remove(attachment.Index); //※添付ファイルを削除
    attachments.Add(zip_file);

    //後処理
    File.Delete(zip_file);
    File.Delete(work_file);
}

先の報告で Outlookが落ちるケースでは、「※添付ファイルを削除」の部分 (Attachments.Remove)で内部エラーが発生してうまくいきませんでした。

RTF形式メールの場合は、次のように処理するとうまくいきます。(うまくいくように見えます)
void beforeAttachmentAdd(Outlook.Attachment attachment, ref bool Cancel)
{
    //ZIP書庫の作成手順は上記と同じ

    bool isRtf = (attachment.Parent.BodyFormat ==  Outlook.OlBodyFormat.olFormatRichText);
    if(!isRtf)
    {
        //テキストメール、HTMLメールの場合は上記と同じ処理
    }
    else
    {
        Cancel = true;  //添付されたファイルをキャンセルして添付させないようにする
        Outlook.Attachments attachments = attachment.Parent.Attachments;
        attachments.Add(zip_file);
    }
    //後処理は上記と同じ
}

ファイルが添付される前処理段階でZIP書庫を添付し、イベントで伝えられた添付を Cancel することで、Outlook が落ちるという致命傷を回避して添付することができました・・・

ところがですねぇ。
環境によって、うまくいく場合とうまくいかない場合が出てしまうんですね。

■添付された(はずの)ファイルがメールに表示されない。
これは困りものです。実際には表示されないケースとしては2つのパターンがあります。

1.メールにはちゃんと添付されているんだけど表示がされていない場合
 この場合は、メールの形式をいったんテキスト形式にした後、RTF形式にすると表示されます。
2.Cancel = true; フラグで一緒に添付されたファイルもキャンセルされてしまう場合
  添付ファイル削除イベントハンドラに情報が渡されることで確認できます。

■複数のファイルを添付しようとすると、イベントが呼び出されない。
ZIP書庫の作成時にモーダル画面を表示させて問い合わせなどを行うと、複数ファイルの添付イベントで2回目以降のイベントが発生しない場合があります。

これらの問題を回避するには・・・

次回(いつだよw)に書くことにします。

※この記事での注意事項
(1) attachment.Parent.BodyFormat, attachment.Parent.Attachments の取得は attachment.Parent を Outlook.MailItem などにキャストしたあとで取得します。

(2) attachments.Remove(attachment.Index); の部分を attachment.Delete(); で処理するように記載されているサンプルをよく見かけますが、例外が出る場合がありました
(詳しくわかりませんでした・・・)

(3)最後の問題点(イベントが呼び出されない場合がある)については、その後も解決してません。

0 件のコメント:

コメントを投稿