2017-03-10 26 views
0

我試圖從Gmail收件箱中使用mailbee閱讀電子郵件。 這個想法是採取任何winmail.dat並提取其附件,並將它們添加到附件池,因此我們不必手動執行它。 MailBee將無法識別我用我的testmail作爲Tnef文件發送的winmail.dat(該文件的類型爲Tnef附件類型)。 IsTnef作爲錯誤出現。C#:MailBee:使用mailbee的tnef實用程序卸載winmail.dat中的附件

我找不到有關mailbee tnef附件的信息,有什麼想法嗎?

這是我得到:

var attachments = message.Attachments.Cast<MailBeeAttachment>().ToList(); 
var encapsulated = attachments.Where(a => a.IsTnef).SelectMany(a => a.GetAttachmentsFromTnef().Cast<MailBeeAttachment>()); 
// Add encapsulated attachments 
attachments.AddRange(encapsulated); 

回答

1

你可能想繼續使用的MailBee ......但如果你是開放的選擇,讓我,如果你用我的開源MimeKit回答這個問題/ MailKit庫代替:

當MimeKit的MIME解析器遇到了Content-Type頭匹配application/vnd.ms-tnefapplication/ms-tnef,它會自動使用專用TnefPart類來表示連接附件換貨。

要從中提取封裝的附件,您可以簡單地使用 ExtractAttachments()方法,該方法可能與MailBee的GetAttachmentsFromTnef()方法非常相似。

你的代碼的MailBee到MimeKit的翻譯應該是這樣的:

var attachments = message.Attachments.ToList(); 
var encapsulated = attachments.OfType<TnefPart>().SelectMany(a => a.ExtractAttachments()); 
// Add encapsulated attachments 
attachments.AddRange(encapsulated); 

最有可能的MailBee的IsTnef屬性返回給你假的原因,然而,可能是因爲Content-Type頭不匹配我前面提到的tnef mime-types。如果確實如此,那麼我在上面發佈的翻譯代碼也會在MimeKit下失敗。

但是......

MimeKit還規定,如果你決定使用另一種方法來確定一個MIME部分包含TNEF內容,您可以使用較低級別的TNEF支持類。

static void ExtractAttachments (MimePart attachment, IList<MimeEntity> attachments) 
{ 
    using (var reader = new TnefReader (attachment.ContentObject.Open(), 0, TnefComplianceMode.Loose)) { 
     // skip past the non-attachment tnef content... 
     while (reader.ReadNextAttribute()) { 
      if (reader.AttributeLevel == TnefAttributeLevel.Attachment) 
       break; 
     } 

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

static void ExtractAttachments (TnefReader reader, IList<MimeEntity> attachments) 
{ 
    var attachMethod = TnefAttachMethod.ByValue; 
    var filter = new BestEncodingFilter(); 
    var prop = reader.TnefPropertyReader; 
    MimePart attachment = null; 
    int outIndex, outLength; 
    TnefAttachFlags flags; 
    string[] mimeType; 
    byte[] attachData; 
    string text; 

    do { 
     if (reader.AttributeLevel != TnefAttributeLevel.Attachment) 
      break; 

     switch (reader.AttributeTag) { 
     case TnefAttributeTag.AttachRenderData: 
      attachMethod = TnefAttachMethod.ByValue; 
      attachment = new MimePart(); 
      break; 
     case TnefAttributeTag.Attachment: 
      if (attachment == null) 
       break; 

      while (prop.ReadNextProperty()) { 
       switch (prop.PropertyTag.Id) { 
       case TnefPropertyId.AttachLongFilename: 
        attachment.FileName = prop.ReadValueAsString(); 
        break; 
       case TnefPropertyId.AttachFilename: 
        if (attachment.FileName == null) 
         attachment.FileName = prop.ReadValueAsString(); 
        break; 
       case TnefPropertyId.AttachContentLocation: 
        text = prop.ReadValueAsString(); 
        if (Uri.IsWellFormedUriString (text, UriKind.Absolute)) 
         attachment.ContentLocation = new Uri (text, UriKind.Absolute); 
        else if (Uri.IsWellFormedUriString (text, UriKind.Relative)) 
         attachment.ContentLocation = new Uri (text, UriKind.Relative); 
        break; 
       case TnefPropertyId.AttachContentBase: 
        text = prop.ReadValueAsString(); 
        attachment.ContentBase = new Uri (text, UriKind.Absolute); 
        break; 
       case TnefPropertyId.AttachContentId: 
        attachment.ContentId = prop.ReadValueAsString(); 
        break; 
       case TnefPropertyId.AttachDisposition: 
        text = prop.ReadValueAsString(); 
        if (attachment.ContentDisposition == null) 
         attachment.ContentDisposition = new ContentDisposition (text); 
        else 
         attachment.ContentDisposition.Disposition = text; 
        break; 
       case TnefPropertyId.AttachData: 
        var stream = prop.GetRawValueReadStream(); 
        var content = new MemoryStream(); 
        var guid = new byte[16]; 

        if (attachMethod == TnefAttachMethod.EmbeddedMessage) { 
         var tnef = new TnefPart(); 

         foreach (var param in attachment.ContentType.Parameters) 
          tnef.ContentType.Parameters[param.Name] = param.Value; 

         if (attachment.ContentDisposition != null) 
          tnef.ContentDisposition = attachment.ContentDisposition; 

         attachment = tnef; 
        } 

        // read the GUID 
        stream.Read (guid, 0, 16); 

        // the rest is content 
        using (var filtered = new FilteredStream (content)) { 
         filtered.Add (filter); 
         stream.CopyTo (filtered, 4096); 
         filtered.Flush(); 
        } 

        content.Position = 0; 

        attachment.ContentTransferEncoding = filter.GetBestEncoding (EncodingConstraint.SevenBit); 
        attachment.ContentObject = new ContentObject (content); 
        filter.Reset(); 

        attachments.Add (attachment); 
        break; 
       case TnefPropertyId.AttachMethod: 
        attachMethod = (TnefAttachMethod) prop.ReadValueAsInt32(); 
        break; 
       case TnefPropertyId.AttachMimeTag: 
        mimeType = prop.ReadValueAsString().Split ('/'); 
        if (mimeType.Length == 2) { 
         attachment.ContentType.MediaType = mimeType[0].Trim(); 
         attachment.ContentType.MediaSubtype = mimeType[1].Trim(); 
        } 
        break; 
       case TnefPropertyId.AttachFlags: 
        flags = (TnefAttachFlags) prop.ReadValueAsInt32(); 
        if ((flags & TnefAttachFlags.RenderedInBody) != 0) { 
         if (attachment.ContentDisposition == null) 
          attachment.ContentDisposition = new ContentDisposition (ContentDisposition.Inline); 
         else 
          attachment.ContentDisposition.Disposition = ContentDisposition.Inline; 
        } 
        break; 
       case TnefPropertyId.AttachSize: 
        if (attachment.ContentDisposition == null) 
         attachment.ContentDisposition = new ContentDisposition(); 

        attachment.ContentDisposition.Size = prop.ReadValueAsInt64(); 
        break; 
       case TnefPropertyId.DisplayName: 
        attachment.ContentType.Name = prop.ReadValueAsString(); 
        break; 
       } 
      } 
      break; 
     case TnefAttributeTag.AttachCreateDate: 
      if (attachment != null) { 
       if (attachment.ContentDisposition == null) 
        attachment.ContentDisposition = new ContentDisposition(); 

       attachment.ContentDisposition.CreationDate = prop.ReadValueAsDateTime(); 
      } 
      break; 
     case TnefAttributeTag.AttachModifyDate: 
      if (attachment != null) { 
       if (attachment.ContentDisposition == null) 
        attachment.ContentDisposition = new ContentDisposition(); 

       attachment.ContentDisposition.ModificationDate = prop.ReadValueAsDateTime(); 
      } 
      break; 
     case TnefAttributeTag.AttachTitle: 
      if (attachment != null && string.IsNullOrEmpty (attachment.FileName)) 
       attachment.FileName = prop.ReadValueAsString(); 
      break; 
     case TnefAttributeTag.AttachMetaFile: 
      if (attachment == null) 
       break; 

      // TODO: what to do with the meta data? 
      break; 
     case TnefAttributeTag.AttachData: 
      if (attachment == null || attachMethod != TnefAttachMethod.ByValue) 
       break; 

      attachData = prop.ReadValueAsBytes(); 
      filter.Flush (attachData, 0, attachData.Length, out outIndex, out outLength); 
      attachment.ContentTransferEncoding = filter.GetBestEncoding (EncodingConstraint.EightBit); 
      attachment.ContentObject = new ContentObject (new MemoryStream (attachData, false)); 
      filter.Reset(); 

      attachments.Add (attachment); 
      break; 
     } 
    } while (reader.ReadNextAttribute()); 
} 

當然......你也可以只通過這樣騙:

var tnef = new TnefPart { ContentObject = attachment.ContentObject }; 
attachments.AddRange (tnef.ExtractAttachments()); 

所以,最終的結果可能是這樣的(如果你決定來匹配文件名代替):

var attachments = message.Attachments.ToList(); 
var encapsulated = attachments.OfType<MimePart>() 
    .Where(x => (x is TnefPart) || x.FileName == "winmail.dat") 
    .SelectMany(x => { 
     var tnef = (x as TnefPart) ?? new TnefPart { ContentObject = x.ContentObject }; 
     return tnef.ExtractAttachments(); 
    }); 
// Add encapsulated attachments 
attachments.AddRange(encapsulated); 
1

測試時,您不應該手動添加winmail.dat。它總是由MS Exchange或Outlook以特殊方式生成(並附加)。 IsTnef會從真實的(Outlook或Exchange製作的)電子郵件中返回真實的附件。