Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting System.Net.Mail.MailMessage as a MemoryStream in .NET 4.5 beta

Tags:

So, the below code used to work in .NET 4 to get a System.Net.Mail.MailMessage object as a MemoryStream, however with the release of .NET 4.5 beta a runtime exception occurs.

Assembly assembly = typeof(SmtpClient).Assembly; Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); using (MemoryStream stream = new MemoryStream()) {     ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);     object mailWriter = mailWriterContructor.Invoke(new object[] { stream });     MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);     sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);      ..... } 

Runtime exception occurs on sendMethod.Invoke().

like image 417
dimoss Avatar asked Mar 07 '12 03:03

dimoss


2 Answers

Managed to figure out how to get this working again in .NET 4.5 beta. The private API Send() method in MailMessage has changed to: internal void Send(BaseWriter writer, bool sendEnvelope, bool allowUnicode)

Please find updated code below.

Assembly assembly = typeof(SmtpClient).Assembly; Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); using (MemoryStream stream = new MemoryStream()) {     ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);     object mailWriter = mailWriterContructor.Invoke(new object[] { stream });     MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);     sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);      ..... } 
like image 168
dimoss Avatar answered Oct 24 '22 03:10

dimoss


This might be usable if you don't want to go with unsupported hacks and don't mind extra performance hit.

public static class MailMessageExtensions     {     public static string  RawMessage(this MailMessage m)         {         var smtpClient = new SmtpClient { DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory };          using (var tempDir = new TemporaryDirectory())             {             smtpClient.PickupDirectoryLocation = tempDir.DirectoryPath;             smtpClient.Send( m );             var emlFile = Directory.GetFiles( smtpClient.PickupDirectoryLocation ).FirstOrDefault();             if ( emlFile != null )                 {                 return File.ReadAllText( emlFile );                 }             else                 return null;             }         return null;         }      }  class TemporaryDirectory : IDisposable     {     public TemporaryDirectory()         {         DirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());         Directory.CreateDirectory( DirectoryPath );         }      public string DirectoryPath { get; private set; }      public void Dispose()         {         if ( Directory.Exists( DirectoryPath ) )             Directory.Delete( DirectoryPath, true );         }     } 
like image 23
mbergal Avatar answered Oct 24 '22 02:10

mbergal