Python – Extracting Embedded Images From Outlook Email


I am using Microsoft's CDO (Collaboration Data Objects) to programmatically read mail from an Outlook mailbox and save embedded image attachments. I'm trying to do this from Python using the Win32 extensions, but samples in any language that uses CDO would be helpful.

So far, I am here…

The following Python code will read the last email in my mailbox, print the names of the attachments, and print the message body:

from win32com.client import Dispatch

session = Dispatch('MAPI.session')
inbox = session.Inbox
message = inbox.Messages.Item(inbox.Messages.Count)

for attachment in message.Attachments:
    print attachment

print message.Text


However, the attachment names are things like: "zesjvqeqcb_chart_0". Inside the email source, I see image source links like this:
<IMG src="cid:zesjvqeqcb_chart_0">

So, is it possible to use this CID URL (or anything else) to extract the actual image and save it locally?

Best Solution

Difference in versions of OS/Outlook/CDO is what might be the source of confusion, so here are the steps to get it working on WinXP/Outlook 2007/CDO 1.21:

  • install CDO 1.21
  • install win32com.client
  • goto C:\Python25\Lib\site-packages\win32com\client\ directory run the following:
  • from the list select "Microsoft CDO 1.21 Library (1.21)", click ok
Generating to C:\Python25\lib\site-packages\win32com\gen_py\
Building definitions from type library...
Importing module
  • Examining file that's just been generated, will give you an idea of what classes, methods, properties and constants are available.

Now that we are done with the boring steps, here is the fun part:

import win32com.client
from win32com.client import Dispatch

session = Dispatch('MAPI.session')
session.Logon ('Outlook') # this is profile name
inbox = session.Inbox
messages = session.Inbox.Messages 
message = inbox.Messages.GetFirst()

    attachments = message.Attachments
    for i in range(attachments.Count):
        attachment = attachments.Item(i + 1) # yep, indexes are 1 based

        filename = "c:\\tmpfile" + str(i)

Same general approach will also work if you have older version of CDO (CDO for win2k)