2017-03-10 2 views
0

J'essaie de lire des courriels en utilisant mailbee à partir d'une boîte de réception gmail. L'idée est de prendre n'importe quel winmail.dat et d'extraire ses pièces jointes et de les ajouter au pool de pièces jointes afin de ne pas avoir à le faire manuellement. MailBee ne reconnaîtra pas le winmail.dat que j'envoie avec mon testmail en tant que fichier Tnef (le type du fichier est le type de pièce jointe Tnef). l'IsTnef sort faux.C#: MailBee: Décharger les pièces jointes à l'intérieur d'un winmail.dat en utilisant les utilitaires tnef de mailbee

Je n'ai pas trouvé beaucoup d'informations sur les pièces jointes mailbee tnef, des idées?

C'est ce que je suis:

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); 

Répondre

1

Vous voulez probablement continuer à utiliser MailBee ... mais si vous êtes ouvert à des solutions de rechange, permettez-moi de répondre à cette question comme si vous utilisiez mon open source MimeKit/MailKit bibliothèques au lieu:

Lorsque l'analyseur MIME MimeKit rencontre des pièces jointes avec un en-tête Content-Type qui correspond application/vnd.ms-tnef ou application/ms-tnef, il utilisera automatiquement le but spécial TnefPart classe pour représenter cette attach ment.

Pour extraire les pièces jointes encapsulées à partir de cela, vous pouvez simplement utiliser la méthode ExtractAttachments() qui fonctionne probablement un peu comme la méthode GetAttachmentsFromTnef() de MailBee.

La traduction de votre code de MailBee à MimeKit ressemblerait à ceci:

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

Très probablement la raison pour laquelle IsTnef propriété de MailBee retourne faux pour vous, cependant, est probablement parce que l'en-tête Content-Type ne correspond aux tnef mime-types que j'ai mentionnés plus tôt. Si c'est effectivement le cas, le code traduit que j'ai posté ci-dessus échouera également sous MimeKit.

Mais ...

MimeKit propose également des cours de soutien TNEF niveau inférieur que vous pouvez utiliser si vous décidez d'utiliser une autre méthode pour déterminer d'une partie MIME contient le contenu 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()); 
} 

Bien sûr ... vous pouvez aussi tout simplement tricher en faisant ceci:

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

Ainsi, le résultat final pourrait ressembler à ceci (si vous décidez de faire correspondre FileName à la place):

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

Vous ne devez pas ajouter winmail.dat manuellement lors des tests. Il est toujours produit (et joint) par MS Exchange ou Outlook d'une manière spéciale. IsTnef renverra les vraies pièces jointes à partir de courriels réels (Outlook ou Exchange).