1

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

使用 openpop.pop3 区分电子邮件中的内联图像和签名图像

我没有足够的代表来评论这个问题,所以我制作了一个新的来引用它。

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

4

1 回答 1

1

您不能使用 OpenPOP.NET 轻松做到这一点,但使用 MailKit 做到这一点相当简单

您可以从常见问题解答HtmlPreviewVisitor中的示例开始,稍微修改一下,将附件分成 2 个列表:

  1. 实际附件列表
  2. HTML 使用的图像列表(又名“签名图像”)

代码:

/// <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));
于 2016-06-03T23:42:46.687 回答