c# - 在 .NET 中序列化 MailMessage 对象的优雅方式

标签 c# serialization mailmessage rfc822 rfc2822

我目前正在考虑在 C# 中序列化一个 MailMessage 对象,尽管网上有几个示例的变体,但它们序列化为二进制文件,这在我看来没有捕获要点。

我的方法是将 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 并添加一个 Serialize 函数,该函数将自动返回 rfc822 字符串,而无需它访问文件系统。

因为我似乎无法使用 Visual Studio 追踪到 SMTPClient.Send 函数,所以这种“理想”的处理方式有点棘手。

我已经通过对 Peter Huber 的 POP3MimeClient 和 POP3MailClient 类添加一些小的更改来解决 RFC 消息的反序列化问题,这样我就可以将 HDD 上的文件或字符串反序列化回 MailMessage。

让我苦恼的是,我真的应该能够使用流序列化 MailMessaage 并将流写入我选择的字符串或文件,而不是四处走动创建基于 GUID 的文件夹作为上面的代码执行并将文件的内容读回字符串...

任何关于如何使它更优雅的指示将不胜感激。

谢谢。

最佳答案

这将是一个 hack。别忘了,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();

关于c# - 在 .NET 中序列化 MailMessage 对象的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18745392/

相关文章:

C# MVC 调试哪个 Controller 返回 View

c# - 在 c# windows 窗体应用程序上从许多不同的电子邮件平台读取邮件

c# - 使用 Mongo C# 驱动程序序列化不可变值类型

php - codeigniter php - 序列化数组

使用远程服务的 Java 序列化和实例共享

powershell - 发送-替换HTML电子邮件

c# - 如何将 MailMessage 对象作为 *.eml 或 *.msg 文件保存到磁盘

c# - 为什么.NET Framework 指定标准委托(delegate)(Action)?

c# - 在哪里可以找到 SocketException 抛出的 SocketErrorCode 和 NativeErrorCode 列表?

c# - WinSCP Session.EnumerateRemoteFiles 的多个文件掩码