openpop - 在电子邮件中查找内嵌图像和签名图像的区别

时间:2016-06-01 09:35:48

标签: c# openpop

我首先提到这个没有答案的问题,这与我的问题非常相似:

Distinguish inline image and signature image in email using openpop.pop3

我没有足够的代表对这个问题发表评论,所以我做了一个新的代表。

我需要一种方法来检查openpop中的附件,看它是来自签名(通常是小徽标等)还是来自嵌入在电子邮件正文中的大图像。当您在许多邮件应用程序中将图片添加为附件时,SmartPhones通常会执行此操作。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您无法使用OpenPOP.NET轻松完成此操作,但使用MailKit这一点非常简单。

您可以做的是从FAQHtmlPreviewVisitor示例开始,然后每隔一段时间对其进行修改,以便将附件拆分为2个列表:

  1. 实际附件列表
  2. HTML使用的图像列表(又名"签名图像")
  3. 代码:

    /// <summary>
    /// Visits a MimeMessage and splits attachments into those that are
    /// referenced by the HTML body vs regular attachments.
    /// </summary>
    class AttachmentVisitor : MimeVisitor
    {
        List<MultipartRelated> stack = new List<MultipartRelated> ();
        List<MimeEntity> attachments = new List<MimeEntity> ();
        List<MimePart> embedded = new List<MimePart> ();
        bool foundBody;
    
        /// <summary>
        /// Creates a new AttachmentVisitor.
        /// </summary>
        public AttachmentVisitor ()
        {
        }
    
        /// <summary>
        /// The list of attachments that were in the MimeMessage.
        /// </summary>
        public IList<MimeEntity> Attachments {
            get { return attachments; }
        }
    
        /// <summary>
        /// The list of embedded images that were in the MimeMessage.
        /// </summary>
        public IList<MimePart> EmbeddedImages {
            get { return embedded; }
        }
    
        protected override void VisitMultipartAlternative (MultipartAlternative alternative)
        {
            // walk the multipart/alternative children backwards from greatest level of faithfulness to the least faithful
            for (int i = alternative.Count - 1; i >= 0 && !foundBody; i--)
                alternative[i].Accept (this);
        }
    
        protected override void VisitMultipartRelated (MultipartRelated related)
        {
            var root = related.Root;
    
            // push this multipart/related onto our stack
            stack.Add (related);
    
            // visit the root document
            root.Accept (this);
    
            // pop this multipart/related off our stack
            stack.RemoveAt (stack.Count - 1);
        }
    
        // look up the image based on the img src url within our multipart/related stack
        bool TryGetImage (string url, out MimePart image)
        {
            UriKind kind;
            int index;
            Uri uri;
    
            if (Uri.IsWellFormedUriString (url, UriKind.Absolute))
                kind = UriKind.Absolute;
            else if (Uri.IsWellFormedUriString (url, UriKind.Relative))
                kind = UriKind.Relative;
            else
                kind = UriKind.RelativeOrAbsolute;
    
            try {
                uri = new Uri (url, kind);
            } catch {
                image = null;
                return false;
            }
    
            for (int i = stack.Count - 1; i >= 0; i--) {
                if ((index = stack[i].IndexOf (uri)) == -1)
                    continue;
    
                image = stack[i][index] as MimePart;
                return image != null;
            }
    
            image = null;
    
            return false;
        }
    
        // called when an HTML tag is encountered
        void HtmlTagCallback (HtmlTagContext ctx, HtmlWriter htmlWriter)
        {
            if (ctx.TagId == HtmlTagId.Image && !ctx.IsEndTag && stack.Count > 0) {
                // search for the src= attribute
                foreach (var attribute in ctx.Attributes) {
                    if (attribute.Id == HtmlAttributeId.Src) {
                        MimePart image;
    
                        if (!TryGetImage (attribute.Value, out image))
                            continue;
    
                        if (!embedded.Contains (image))
                            embedded.Add (image);
                    }
                }
            }
        }
    
        protected override void VisitTextPart (TextPart entity)
        {
            TextConverter converter;
    
            if (foundBody) {
                // since we've already found the body, treat this as an
                // attachment
                attachments.Add (entity);
                return;
            }
    
            if (entity.IsHtml) {
                converter = new HtmlToHtml {
                    HtmlTagCallback = HtmlTagCallback
                };
    
                converter.Convert (entity.Text);
            }
    
            foundBody = true;
        }
    
        protected override void VisitTnefPart (TnefPart entity)
        {
            // extract any attachments in the MS-TNEF part
            attachments.AddRange (entity.ExtractAttachments ());
        }
    
        protected override void VisitMessagePart (MessagePart entity)
        {
            // treat message/rfc822 parts as attachments
            attachments.Add (entity);
        }
    
        protected override void VisitMimePart (MimePart entity)
        {
            // realistically, if we've gotten this far, then we can treat
            // this as an attachment even if the IsAttachment property is
            // false.
            attachments.Add (entity);
        }
    }
    

    使用它:

    var visitor = new AttachmentVisitor ();
    
    message.Accept (visitor);
    
    // Now you can use visitor.Attachments and visitor.EmbeddedImages
    

    更简单但更不容错误的方法是这样做:

    var signatureImages = message.BodyParts.OfType<MimePart> ().
        Where (x => x.ContentType.IsMimeType ("image", "*") &&
               x.ContentDisposition != null &&
               x.ContentDisposition.Disposition.Equals ("inline" StringComparison.OrdinalIgnoreCase));