MimeKit: Multiple bugs in TnefPart.cs

I’ve been working a lot lately with winmail.dat files and discovered multiple bugs in some of the methods in TnefPart.cs:

First function with bugs is ExtractRecipientTable (please see my comments inline):

   static void ExtractRecipientTable (TnefReader reader, MimeMessage message)
	    {
		var prop = reader.TnefPropertyReader;

		// Note: The RecipientTable uses rows of properties...
		while (prop.ReadNextRow ()) {
			InternetAddressList list = null; // There is a logic bug here where list is initialized to null every time reading a new row. 
However, the assumption is that there is a RecipientType property for each new row and the list is 
initialized accordingly. However, this is not the case in the Tnef files I'm processing. 
Hence, list is null most of the time and a new MailboxAddress is not created and added to the 
MimeMessage. The solution I made was to move the initialization of the list outside the while 
loop. 
			string name = null, addr = null;

			while (prop.ReadNextProperty ()) {
				switch (prop.PropertyTag.Id) {
				case TnefPropertyId.RecipientType:
					int recipientType = prop.ReadValueAsInt32 ();
					switch (recipientType) {
					case 1: list = message.To; break;
					case 2: list = message.Cc; break;
					case 3: list = message.Bcc; break;
					}
					break;
				case TnefPropertyId.TransmitableDisplayName:
					if (string.IsNullOrEmpty (name))
						name = prop.ReadValueAsString ();
					break;
				case TnefPropertyId.DisplayName:
					name = prop.ReadValueAsString ();
					break;
				case TnefPropertyId.EmailAddress:
					if (string.IsNullOrEmpty (addr))
						addr = prop.ReadValueAsString ();
					break;
				case TnefPropertyId.SmtpAddress:
					// The SmtpAddress, if it exists, should take precedence over the EmailAddress
					// (since the SmtpAddress is meant to be used in the RCPT TO command).
					addr = prop.ReadValueAsString ();
					break;
				}
			}
			if (list != null && !string.IsNullOrEmpty (addr))
				list.Add (new MailboxAddress (name, addr));
		}
	}`

Another bug in the implementation of ExtractRecipientTable which I have not been able to identify the cause yet is that it is unable to read correctly the RecipientType for both Cc and Bcc. I’ve also noticed that there are Null property values, this might have something to do with it… I’m still investigating.

Related to this bug is also another bug where prop.ReadNextRow () is unable to retrieve the actual following row in the recipient table. One fix which I discovered to work is to break out of the while loop immediately after the MailboxAddress is created:

  if (list != null && !string.IsNullOrEmpty (addr))
  {
	  list.Add (new MailboxAddress (name, addr));
              break;
  }

It seems like there is an issue of calling prop.ReadNextProperty() to process the rest of the remaining properties in the row…

Another issue which I noticed was after this function is called, the AttributeTag get’s corrupted. In the case of the function ExtractTnefMessage. Please see my commends in-line.

            static MimeMessage ExtractTnefMessage (TnefReader reader)
	{
		var builder = new BodyBuilder ();
		var message = new MimeMessage ();

		message.Headers.Remove (HeaderId.Date);

		while (reader.ReadNextAttribute ()) {
			if (reader.AttributeLevel == TnefAttributeLevel.Attachment)
				break;

			var prop = reader.TnefPropertyReader;

			switch (reader.AttributeTag) {
			case TnefAttributeTag.RecipientTable:
				ExtractRecipientTable (reader, message);
    // After call to ExtractRecipientTable, reader.AttributeTag is corrupted. And hence 
 ReadNextAttribute doesn't contain the MapiProperties Attribute any more. 
				break;
			case TnefAttributeTag.MapiProperties:
				ExtractMapiProperties (reader, message, builder); // This function does not get executed at all. 
				break;
			case TnefAttributeTag.DateSent:
				message.Date = prop.ReadValueAsDateTime ();
				break;
			case TnefAttributeTag.Body:
				builder.TextBody = prop.ReadValueAsString ();
				break;
			}
		}

		if (reader.AttributeLevel == TnefAttributeLevel.Attachment)
			ExtractAttachments (reader, builder);

		message.Body = builder.ToMessageBody ();

		return message;
	}`

Platform (please complete the following information):

  • OS: Windows
  • .NET Framework: .NET 4.5
  • MimeKit Version: 2.5.1

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 46 (26 by maintainers)

Commits related to this issue

Most upvoted comments

@jstedfast I just ran into this old ticket while googling around for some .CFG form inanity in Outlook and I figured it might interest you that Microsoft has explained what these two props do over here:

https://social.microsoft.com/Forums/mvpforum/en-SG/8e15ac6d-0404-41c0-9af7-26a06ca797bf/meaning-of-mapi-identifiers-0x5d0a-and-0x5d0b?forum=os_exchangeprotocols

HEX 0x5D0A (DEC 23818) = Creator SMTP Address HEX 0x5D0B (DEC 23819) = Last Modifier SMTP Address