Minimum Socket.ReceiveTimeout is half a second

If you’re using Timeout property of Imap, Pop3 or SmtpServer classes and ever tested small timeout values (e.g. 10 milliseconds) to see socket timeout in action, you might be surprised that it never occurs.

This is because Windows internally limits the minimum timeout value for a socket to 500 milliseconds. This has nothing to do with MailBee and even .NET Framework. Setting any 1-499ms value will have the same effect as setting 500ms.

Those who are interested in details can google on minimum Socket.ReceiveTimeout 500ms.

Note that .NET 4.5-style async/await methods of upcoming MailBee.NET v9.5 honor any value of a timeout (because they are not relying on Windows socket timeouts).

Minimum Socket.ReceiveTimeout is half a second

AccessViolationException in Google OAuth2 API library

For years, a critical bug in Google.Apis library has been preventing OAuth2-enabled apps from working correctly.

UserCredential credential = ... // Get credential somehow
Oauth2Service oauthService = new Oauth2Service(new BaseClientService.Initializer() { HttpClientInitializer = credential });
Userinfoplus userInfo = await oauthService.Userinfo.Get().ExecuteAsync(myCancelTokenSource.Token);

.Userinfo.Get() may fail with AccessViolationException (that is so severe that you can’t even catch it).

Fortunately, the bug only occurs when the app is being run under the debugger. You can use Ctrl-F5 to run it without debugging.

Many MailBee.NET OAUTH2 samples (such as those installed in My Documents/MailBee.NET Objects/Samples/WinForms/.NET 4.5 OAuth) depend on this library so be aware of this issue.

More info on the bug: http://stackoverflow.com/questions/24723701/google-plus-api-c-sharp-accessviolationexception

AccessViolationException in Google OAuth2 API library

How to keep rich-text formatting when extracting messages from .PST files

If reading a message from .PST file, you may often encounter a situation when the message does not have HTML body and has RTF body instead. That’s how you can display RTF body in your apps (assuming richTextBox1 is a RichTextBox control):

...
PstReader reader = new PstReader("data.pst");
var folder = reader.GetFolderByID(some_folder_id);
var items = folder.Items;
var item = items[some_item_id];
PstMessage message = item as PstMessage;
message.RtfInEmlMethod = RtfInEmlStorageMethod.AsBodyPart;
var mail = message.GetAsMailMessage();
if (mail.IsBodyAvail("text/rtf", false))
{
	richTextBox1.Rtf = mail.BodyParts["text/rtf"].Text;
}
How to keep rich-text formatting when extracting messages from .PST files

Precedence of Sender, X-Sender and From headers in DKIM

Consider this code:

...
mailer.Message.DomainKeysSign(false, new string[] { "From", "To", "Subject", "Message-ID" }, @"C:\Certs\dkim.pem", true, "mail", DomainKeysTypes.DKIM);
mailer.Send();

Let’s assume it works and sends out a DKIM signed message.

Now you decided to add an X-Sender header. For instance, you want to use From different from real sender but still want to prevent┬áspam filters from thinking that you’re a spammer which forges addresses. For that:

...
mailer.Message.Headers.Add("X-Sender", "real@sender.com", true);
mailer.Message.DomainKeysSign(false, new string[] { "From", "To", "Subject", "Message-ID" }, @"C:\Certs\dkim.pem", true, "mail", DomainKeysTypes.DKIM);
mailer.Send();

This will now crash with MailBeeInvalidArgumentException! Why so? One of the purposes of DKIM is to make sure the address from which the message was sent is not forged. However, if you added X-Sender (which tells the mail server the real address of the sender) but didn’t include it into the list of headers to sign with DKIM, this means this header can then be altered. This would defeat the purpose of DKIM. Thus, if you add X-Sender to your message, make sure to also add it into the list of headers to be signed:

...
mailer.Message.Headers.Add("X-Sender", "addr@domain.com", true);
mailer.Message.DomainKeysSign(false, new string[] { "X-Sender", "From", "To", "Subject", "Message-ID" }, @"C:\Certs\dkim.pem", true, "mail", DomainKeysTypes.DKIM);
mailer.Send();

This also works for Sender header. The order of precedence is as follows:

  • Sender
  • X-Sender
  • From

I.e. if the message has Sender header, it must be signed. Signing of X-Sender and From is optional. If the message does not have Sender but has X-Sender, X-Sender must be signed. If the message has neither Sender nor X-Sender, it’s From header which must be signed.

The above is not relevant is you pass null in headersToSign parameter. In this case MailBee.NET will take care of all the things automatically.

Precedence of Sender, X-Sender and From headers in DKIM

How to keep HTML formatting when converting .EML to Outlook .MSG

.MSG messages can have up to 3 alternate versions of the body: RTF, HTML, and plain-text.

By default, when you convert .EML message with HTML body into Outlook .MSG, MailBee tries to create RTF version of HTML content (Outlook 2003 or older and not always good with HTML). This, however, produces some artifacts as RTF and HTML formats are very different and it’s hardly possible to preserve the exact formatting.

If you don’t need to support old Outlook versions, you can tell MailBee not to add RTF body. The resulting .MSG with HTML body can then be opened in Outlook 2007 or higher.

...
conv.HtmlToRtfMethod = HtmlToRtfConversionMethod.None;
conv.MailMessageToMsg(sourceEmlObj, outputMsgFilename);

conv is MsgConvert instance and sourceEmlObj is MailMessage you’re converting to Outlook .MSG file.

The example above converts an object into a file but it will also work for other cases, such as to directly convert .EML file to .MSG file, convert from/to stream, and so on.

Note that older Outlook versions will still be able to read the body in plain-text format if you supplied it in the source .EML message. If plain-text version was not there, you can add it to the source message with MailMessage.BodyPlainText property (before performing conversion). In case if you don’t have the plain-text version to assign to the property, you can tell MailBee to generate plain-text from HTML body with MailMessage.MakePlainBodyFromHtmlBody method.

How to keep HTML formatting when converting .EML to Outlook .MSG

AES encryption in S/MIME

The standard security provider in Windows does not list AES algorithms support but it can be requested explicitly (secureMime is Smime instance):

Smime secureMime = new Smime();
Algorithm aesAlg = Algorithm.CreateInstanceByOid("2.16.840.1.101.3.4.1.42");
if (aesAlg != null)
{
  secureMime.EncryptionAlgorithm = aesAlg;
}
MailMessage securedMsg = secureMime.SignAndEncrypt(...)
...

“2.16.840.1.101.3.4.1.42” is OID of AES 256 algorithm. That’s it!

Note: the code above focuses on enabling AES algorithm, the rest (setting message properties and certificates) would be exactly the same as with the default algorithm (usually, 3DES).

Alternatively to setting AES OID manually, you can enumerate algorithms in Windows (although this is more code). We get the list of all security providers, find that one which supports AES and then search for AES algorithm in it:

Smime secureMime = new Smime();
string[] sysProviders = CryptoServiceProvider.GetSystemProviders();
string aesProviderName = null;
foreach (string providerName in sysProviders)
{
  if (providerName.IndexOf("AES") > -1)
  {
    aesProviderName = providerName;
    break;
  }
}
if (aesProviderName != null)
{
  secureMime.Provider = new CryptoServiceProvider(aesProviderName);
}
Algorithm[] algs = sm.Provider.GetSupportedAlgorithms();
Algorithm aesAlg = null;
foreach (Algorithm alg in algs)
{
  if (alg.Name.IndexOf("AES 256") > -1)
  {
    aesAlg = alg;
    break;
  }
}
if (aesAlg != null)
{
	sm.EncryptionAlgorithm = aesAlg;
}
MailMessage securedMsg = secureMime.SignAndEncrypt(...)
...

The AES support has been added just recently. To get it, update your MailBee.NET version with NuGet console
Install-Package MailBee.NET

AES encryption in S/MIME

Reading SMTP id assigned by the server to the message being sent

Suppose you’re sending a message with Smtp.Send and want to get the ID or whatever your SMTP server assigns to each message being submitted. That’s how (mailer is Smtp object instance):

void mailer_MessageSubmittedToServer(object sender, SmtpMessageSubmittedToServerEventArgs e)
{
  string response = ((Smtp)sender).GetServerResponse();
  Console.WriteLine(response);
}

...

mailer.MessageSubmittedToServer += new SmtpMessageSubmittedToServerEventHandler(mailer_MessageSubmittedToServer);
mailer.Send();

The response value can be somewhat like that (for most servers):

250 OK id=2YLuMd-5gfKMK-3K

or (for MS Exchange):

250 2.6.0 [InternalId=807779] Queued mail for delivery

It should then be easy to parse the returned string and get the id value (or values, like in case of MS Exchange which returns you two values).

Reading SMTP id assigned by the server to the message being sent