An elegant way to serialize a MailMessage object in .NET.

I'm currently looking at serializing a MailMessage object in C #, and although there are several example variations on the network, they are serialized in binary format, which skips the IMO point.

My approach is that I would like to serialize MailMessage to the RFC2822 eml line, and the code below is what I came up with.

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; } 

This is pretty unpleasant, but it really works. Ideally, I would create a new SMTPClient and add a Serialize function that would automatically return the rfc822 line without pressing the file system.

It seems to me that I can’t track the SMTPClient.Send function in Visual Studio, this β€œideal” way to make things a little more complicated.

I already figured out how to deserialize the RFC message by adding some minor changes to the Peter Huber POP3MimeClient and POP3MailClient classes so that I can deserialize the file on my hard drive or the string back to MailMessage.

What is imposing on me is that I really should be able to serialize MailMessaage using a stream and write the stream to a line-or file of my choice, instead of going around the house to create GUID-based folders, as the code above does and reads the contents of the file back to the line ...

Any pointers on how I could make this more elegant would be greatly appreciated.

Thanks.

+7
c # serialization rfc822 mailmessage rfc2822
source share
2 answers

It will be a hack. Do not forget that MS may change it in future versions of .Net.

(With ILSpy) you can write an extension method like below

 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()); } } 

and use as

 string eml = mailMessage.ToEml(); 
+19
source share

I finally managed to deserialize MailMessage after a lot of work:

To make everything right, I created a dll that will be used both in the client application and in the webservice. For deserialization, this should be the same :)

I chose the dll serialization classes here: https://bitbucket.org/burningice/compositec1contrib.email/src/0bba07df532c8134717cfb40757f4cb22f002b1d/Email/Serialization/?at=default

Thanks so much for sharing!

After compiling and adding my new dll to projects, send and receive worked.

So, I convert MailMessage this way: string serializedMessage = SerializeAsBase64 (mail); and in Webservice I reconstruct it like this: MailMessage Mm = DeserializeFromBase64 (serializedMessage);

Hope this helps ...

0
source share

All Articles