Search code examples
c#emailhtml-emailemail-attachmentsnetoffice

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


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?


Solution

  • 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}");
    }