The requirement: Given an Outlook message, detach any attachments to the filesystem and replace them in the message by a shortcut.
Although ostensibly two different things, Outlook and Exchange are pretty tightly coupled in reality. This code uses the CDO technique, an IDispatch-based mechanism under the application name MAPI.Session. For any work with CDO I highly recommend the CDOLive website.
The approach is to iterate over the messages in a folder, interrogating each one as to its attachments. If any of the attachments is a file (ie is not itself a link), save the file to the file system using a simple incrementing counter approach and add a new attachment of the same name which is a link to the newly-created file on the file system. Finally, delete the now unneeded original attachment. Please note the warning below: the code as presented has few safeguards and should be considered illustrative only.
The code below is pared to the bone for readability. Naturally you'll need checks galore. The only safeguards I've retained are that the code doesn't in fact delete the existing attachments: the line's commented out; and that it only tries to detach file attachments, ie you can run it again on the same folder and it won't try to create links to links!
import os, sys import win32com.client win32com.client.gencache.EnsureDispatch ("MAPI.Session") ATTACHMENTS_FOLDER = "c:/temp" COUNTER = 1 def process_attachment (attachment): global COUNTER basename = attachment.Name.encode ("utf-8", "ignore").lower () root, ext = os.path.splitext (basename) while True: try: filepath = os.path.join (ATTACHMENTS_FOLDER, "%d%s" % (COUNTER, ext)) print "Trying", filepath open (filepath, "r") except IOError: break else: COUNTER += 1 try: attachment.WriteToFile (filepath) except: return 0 else: attachments = attachment.Parent new_attachment = attachments.Add () new_attachment.Position = 0 new_attachment.Type = win32com.client.constants.CdoFileLink new_attachment.Source = filepath new_attachment.Name = attachment.Name ## attachment.Delete () return 1 def process_message (message): print "Message:", message.Subject attachments = message.Attachments for n_attachment in range (1, attachments.Count + 1): attachment = attachments.Item (n_attachment) if attachment.Type == win32com.client.constants.CdoFileData: if process_attachment (attachment): message.Update () if __name__ == '__main__': session = win32com.client.gencache.EnsureDispatch ("MAPI.Session") session.Logon () messages = session.Inbox.Messages message = messages.GetFirst () while message: process_message (message) message = messages.GetNext ()