Friday, January 4, 2013

How to save MailMessage into eml file by Reflection on .net framework 4.5?

/// 
        /// HACK - SmtpClient does not give access to filenames when outputting e-mails to disk.  The following extension method
        /// uses reflection to call the internal MailWriter type so that mails can be created with a specified filename.
        /// 
        /// Code taken from: http://www.codeproject.com/KB/IP/smtpclientext.aspx
        /// 
        /// Mail message to be serialized./// Filename of mail message.public static void Save(this MailMessage Message, string FileName)
        {
            // TODO: See if the Mono framework has serialization code we can use.

            Assembly assembly = typeof(SmtpClient).Assembly;
            Type _mailWriterType =
              assembly.GetType("System.Net.Mail.MailWriter");

            using (FileStream _fileStream =
                   new FileStream(FileName, FileMode.Create))
            {
                // Get reflection info for MailWriter contructor
                ConstructorInfo _mailWriterContructor =
                    _mailWriterType.GetConstructor(
                        BindingFlags.Instance | BindingFlags.NonPublic,
                        null,
                        new Type[] { typeof(Stream) },
                        null);

                // Construct MailWriter object with our FileStream
                object _mailWriter =
                  _mailWriterContructor.Invoke(new object[] { _fileStream });

                // Get reflection info for Send() method on MailMessage
                MethodInfo _sendMethod =
                    typeof(MailMessage).GetMethod(
                        "Send",
                        BindingFlags.Instance | BindingFlags.NonPublic);

                // Call method passing in MailWriter
                _sendMethod.Invoke(
                    Message,
                    BindingFlags.Instance | BindingFlags.NonPublic,
                    null,
                    new object[] { _mailWriter, true, true },
                    null);

                // Finally get reflection info for Close() method on our MailWriter
                MethodInfo _closeMethod =
                    _mailWriter.GetType().GetMethod(
                        "Close",
                        BindingFlags.Instance | BindingFlags.NonPublic);

                // Call close method
                _closeMethod.Invoke(
                    _mailWriter,
                    BindingFlags.Instance | BindingFlags.NonPublic,
                    null,
                    new object[] { },
                    null);
            }
        }

How to know if .Net Framework 4.5 installed?

.NET 4.5 is not running side by side with .Net 4.0. It is a upgrade.
.NET 4.5 overwrites .NET 4. So all of files are in the same folder.

Following are the different version for .Net 4.0
4.0.30319.1 = .NET 4.0 RTM
4.0.30319.269 = most common .NET 4.0 version we're seeing in the data collected from our users
4.0.30319.544 = another .NET 4.0 version that a small portion of our users have installed
4.0.30319.17626 = .NET 4.5 RC
4.0.30319.17929 = .NET 4.5 RTM
4.0.30319.18010 = current version on my Windows 8 machine

So there are many ways to know if .Net 4.5 installed
1. By System.dll version number: 4.0.30319.17626 or greater
2. By Registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client
3. By code
  public static bool IsNet45OrNewer()
  {
      // Class "ReflectionContext" exists from .NET 4.5 onwards.
      return Type.GetType("System.Reflection.ReflectionContext", false) != null;
  }

SignalR: Building real time web applications

http://blogs.msdn.com/b/webdev/archive/2012/12/17/signalr-building-real-time-web-applications.aspx