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
- Make sure to read all TNEF property values in the loop. Partial fix for issue #538 — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Fixed TnefPropertyReader to properly skip remaining values/properties When advancing to the next row or property, make sure to properly skip over the remaining properties or values. Partial fix for ... — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Added TnefPropertyId.LastModifierName Partial fix for issue #538 — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Prefer PidTagRecipientDisplayName > TransmitableDisplayName > DisplayName Another partial fix for issue #538 — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Added more TNEF property tags Partial fix for issue #538 — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Fixed TnefPart's ExtractAttachments() logic for embedded messages Sometimes AttachData can become before AttachMethod, so properly handle this case as well. Another partial fix for issue #538 — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Fixed extraction of TNEF EmbeddedMessage attachment data to skip the leading GUID Final fix for issue #538 — committed to jstedfast/MimeKit by jstedfast 4 years ago
- Add a few more (undocumented) TnefPropertyIds See https://github.com/jstedfast/MimeKit/issues/538#issuecomment-1649640118 — committed to jstedfast/MimeKit by jstedfast a year ago
@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