C# 在.NET中序列化MailMessage对象的优雅方法
我目前正在考虑在C#中序列化一个MailMessage对象,尽管网络上有几个示例的变体,但它们序列化为二进制,这在某种程度上忽略了要点 我的方法是将邮件消息序列化为RFC2822 eml字符串,下面的代码就是我想到的C# 在.NET中序列化MailMessage对象的优雅方法,c#,serialization,mailmessage,rfc822,rfc2822,C#,Serialization,Mailmessage,Rfc822,Rfc2822,我目前正在考虑在C#中序列化一个MailMessage对象,尽管网络上有几个示例的变体,但它们序列化为二进制,这在某种程度上忽略了要点 我的方法是将邮件消息序列化为RFC2822 eml字符串,下面的代码就是我想到的 public string SerializeEmail(MailMessageArgs e) { string rfc822eml = ""; Guid g = Guid.NewGuid(); lock (g.ToS
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字符串,而不会影响文件系统
由于我似乎无法跟踪到VisualStudio的SMTPClient.Send函数,这种“理想”的处理方式有点棘手
我已经通过对Peter Huber的POP3MimeClient和POP3MailClient类添加一些小更改来整理RFC消息的反序列化,这样我就可以将硬盘上的文件或字符串反序列化回MailMessage
困扰我的是,我真的应该能够使用流序列化MailMessaage,并将流写入我选择的字符串或文件,而不是像上面的代码那样到处创建基于GUID的文件夹,并将文件内容读回字符串
任何关于我如何使这更优雅的建议都将不胜感激
谢谢。这将是一次黑客攻击。别忘了,微软可以在下一个版本的.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();
经过大量工作,我终于成功地反序列化了邮件消息: 为了使它正确,我创建了一个dll,它将在客户端应用程序和Web服务中使用。这需要与反序列化工作相同:) 我在这里选择了dll序列化类: 非常感谢分享 一旦编译并将我的新dll添加到项目中,发送和接收就可以工作了 因此,我将邮件消息转换为:string serializedMessage=SerializeAsBase64(邮件); 在Web服务中,我以这种方式重建它: MailMessage Mm=反序列化FromBase64(serializedMessage)
我希望这有助于 谢谢你。我对它做了一些微调,以处理我们定制的MailMessage对象,它有一些额外的特性,结果令人印象深刻。它工作完美,速度快,优雅,正如我所认为的那样。非常酷:为什么他们不公开API!我的沉默,现在删除评论。这是一个非常好的扩展。是否有人实现了EML back to MailMessage?使用POP客户端并重写一两个函数来获取流并将其加载到MailMessage中。RFC2822格式与通过POP和IMAP客户端提供的格式相同,因此您应该能够非常轻松地对其进行反序列化。您好@PaulV-您介意共享反序列化位吗?非常感谢。嗨,这不容易分享。当时我正在起草一份合同,我再也不能使用该代码了。如果我没记错的话,它基本上是将字符串从DB加载到流中,然后从那里填充消息对象,就像您从流上的POP服务器下载它一样。