NetOffice.Outlook distinguish between the images in the body of the email and the attached ones?

77 Views Asked by At

How can I distinguish between an image in the body of an email and an image attached to an email using the NetOffice.Outlook C# library?

UPD:

Here's my semi-working example:

var saveInlineImages = false;
foreach (var attachment in mailItem.Attachments)
{
    if (attachment == null) continue;
    using (attachment)
    {
        var attName = attachment.FileName;
        var savePath = GetSavePath();
        try
        {
            if (!saveInlineImages && IsImage(attName) && IsInlineImage(attachment))
                continue;
            attachment.SaveAsFile(savePath);
        }
        catch
        {
            throw new Exception($"Failed to write the file: {savePath}");
        }
    }

}

private bool IsImage(string attName)
{
    var lowerName = attName.ToLower();
    return lowerName.EndsWith(".jpg") || lowerName.EndsWith(".jpeg") ||
           lowerName.EndsWith(".png") || lowerName.EndsWith(".gif") ||
           lowerName.EndsWith(".tiff") || lowerName.EndsWith(".svg") ||
           lowerName.EndsWith(".raw") || lowerName.EndsWith(".ico") ||
           lowerName.EndsWith(".heic");
}

private bool IsInlineImage(Attachment attachment)
{
    try
    {
        var propertyAccessor = attachment.PropertyAccessor;
        var cid = propertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F");
        return !string.IsNullOrEmpty(cid?.ToString());
    }
    catch
    {
        return false;
    }
}

The problem is that "IsInlineImage" works fine on all accounts except Exchange. In Exchange accounts, this method defines all messages as "Inline". Is there any other universal working method to detect a picture inside the message body?

2

There are 2 best solutions below

0
Alldman On BEST ANSWER

I was able to deal with this problem this way (you need to make sure the attachment is an image before doing this):

private bool IsInlineImage(Attachment attachment)
{
    var mailItem = attachment.Parent as MailItem;
    if (mailItem == null) return false;

    const string PR_ATTACH_CONTENT_ID = "http://schemas.microsoft.com/mapi/proptag/0x3712001F";
    using var propertyAccessor = attachment.PropertyAccessor;
    var cid = propertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID);

    if (string.IsNullOrEmpty(cid?.ToString()))
        return false;

    return mailItem.HTMLBody.Contains($"cid:{cid}");
}
3
Eugene Astafiev On

It doesn't matter whether you use NetOffice or not, you can distinguish images used in the message body by checking the src attribute. In case embedded images you could see the following construction:

<img src="cid:image.png"/>

Where the cid: indicates that the image mentioned represents an attached file and used in the message body as an image.

You may try getting the PR_ATTACH_CONTENT_ID property value on the attached file (the DASL name is "http://schemas.microsoft.com/mapi/proptag/0x3712001F") using the PropertyAccessor object. The value is used for the cid attribute in the HTML markup. The PropertyAccessor.GetProperty method can help with such tasks.