9

私は現在、C# で MailMessage オブジェクトをシリアル化することを検討しています。ネット上にはいくつかの例のバリエーションがありますが、それらはバイナリにシリアル化され、IMO のポイントを逃しています。

私のアプローチは、MailMessage を RFC2822 eml 文字列にシリアル化したいというもので、以下のコードは私が思いついたものです。

    public string SerializeEmail(MailMessageArgs e)
    {
        string rfc822eml = "";
        Guid g = Guid.NewGuid();
        lock (g.ToString())
        {
            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(@"C:\tmpspool");
            di.CreateSubdirectory(g.ToString());
            string spoolDir = @"C:\tmpspool\" + g.ToString();
            SmtpClient Client = new SmtpClient("localhost");
            Client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
            Client.PickupDirectoryLocation = spoolDir;
            Client.Send(e.mailObj);
            var files = from file in Directory.EnumerateFiles(spoolDir)
                       select file;
            string serializedEml = files.First();
            rfc822eml = File.ReadAllText(serializedEml);
            File.Delete(serializedEml);
            Directory.Delete(spoolDir);
        }

        return rfc822eml;
    }

それはかなり厄介ですが、うまくいきます。ただし、理想的には、新しい SMTPClient を作成し、ファイル システムにヒットすることなく rfc822 文字列を自動的に返す Serialize 関数を追加します。

Visual Studio で SMTPClient.Send 関数を追跡できないように見えるので、この「理想的な」方法は少しトリッキーです。

Peter Huber の POP3MimeClient および POP3MailClient クラスにいくつかの小さな変更を加えて、RFC メッセージの逆シリアル化を既に整理して、HDD 上のファイルまたは文字列を逆シリアル化し、MailMessage に戻すことができるようにしました。

私を悩ませているのは、上記のコードのように GUID ベースのフォルダーを作成するために家を回る代わりに、ストリームを使用して MailMessaage をシリアル化し、そのストリームを自分の選択した文字列またはファイルに書き込むことができるはずだということです。ファイルの内容を文字列に読み込んでいます...

これをよりエレガントにする方法についての指針は大歓迎です。

ありがとう。

4

2 に答える 2

21

これはハックになります。MS は次のバージョンの .Net で変更できることを忘れないでください。

(ILSpyの助けを借りて)以下のような拡張メソッドを書くことができます

public static class MailExtensions
{
    public static string ToEml(this MailMessage mail)
    {
        var stream = new MemoryStream();
        var mailWriterType = mail.GetType().Assembly.GetType("System.Net.Mail.MailWriter");
        var mailWriter = Activator.CreateInstance(
                            type: mailWriterType,
                            bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic,
                            binder: null,
                            args: new object[] { stream },
                            culture: null,
                            activationAttributes: null);

        mail.GetType().InvokeMember(
                            name: "Send",
                            invokeAttr: BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
                            binder: null,
                            target: mail,
                            args: new object[] { mailWriter, true, true });


        return Encoding.UTF8.GetString(stream.ToArray());
    }
}

として使用します

string eml = mailMessage.ToEml();
于 2013-09-11T16:09:56.497 に答える