0
votes

My goal is to add an image (from local .png file) to an Outlook MailItem using Python.

I have read answers to similar questions on SO (mostly using VBA), but the issue I have is that the mail looks fine (I can see the image) before I send it (and when I look in my Sent Items folder), but when it is received at the other end, the image is broken.

If I manually insert the image in a message (using Insert / Picture / From this Device from the Outlook menu) the email arrives fine, with the image displayed.

Here is the basic code I am using (based mostly on VBA examples):

import win32com.client as wc

def main():
    outlook = wc.Dispatch("Outlook.Application")

    #Create a new mail item
    msg = outlook.CreateItem(0)

    #Set some properties
    msg.BodyFormat = 2
    msg.Subject = 'Here is my chart'
    msg.Recipients.Add('[email protected]')
    
    #Add an attachment, with position 0
    imageFile = 'C:\\Temp\\myplot.png'
    ats = msg.Attachments
    att = ats.Add(imageFile,1,0)
    
    #Set the HTMLBody
    msg.HTMLBody = '<img src="cid:{0:}" width=200 height=200>'.format(att.FileName)

    #Send
    msg.Send()

main()

This is what I see in my Sent Items folder:

enter image description here

The HTML in my sent item (using View Source) is this:

<img src="cid:myplot.png" width=200 height=200>

But this is what arrives:

enter image description here

The HTML in the body at the destination is this:

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body>
<img src="cid:[email protected]" width="200" height="200">
</body>
</html>

When I manually insert the image, the received HTML is much longer (so I won't include it all here), but the 'img' tag is here (and this matches what is in the Sent Items folder):

<img width="614" height="461" style="width:6.3958in;height:4.802in" id="Picture_x0020_1" src="cid:[email protected]" alt="Chart, line chart Description automatically generated">

I would appreciate any insights on this! (Sadly Outlook won't let me record a macro to see what the manual process is doing). I have seen one example (from C#) where the SetProperty() method is used on the MailItem to add other items that are not in the Outlook object model (schema, context id), together with a newly created Guid, but is this really necessary?

Using Microsoft 365, Outlook version 2105, Beta Channel

1

1 Answers

1
votes

Create an attachment and set the PR_ATTACH_CONTENT_ID property (DASL name "http://schemas.microsoft.com/mapi/proptag/0x3712001F") using Attachment.PropertyAccessor.SetProperty.

Your HTML body (MailItem.HTMLBody property) would then need to reference that image attachment through the cid:

img src="cid:xyz"

where xyz is the value of the PR_ATTACH_CONTENT_ID property.

Look at an existing message with OutlookSpy (click IMessage button).

attachment = mailitem.Attachments.Add("c:\temp\MyPicture.jpg");
attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "MyId1");
mailitem.HTMLBody = "<html><body>Test image <img src=""cid:MyId1""></body></html>";