Reading e-mails from Outlook with Python through MAPI

I’m trying to write a short program that will read in the contents of e-mails within a folder on my exchange/Outlook profile so I can manipulate the data. However I’m having a problem finding much information about python and exchange/Outlook integration. A lot of stuff is either very old/has no docs/not explained. I’ve tried several snippets but seem to be getting the same errors. I’ve tried Tim Golden’s code:

import win32com.client

session = win32com.client.gencache.EnsureDispatch ("MAPI.Session")

#
# Leave blank to be prompted for a session, or use
# your own profile name if not "Outlook". It is also
# possible to pull the default profile from the registry.
#
session.Logon ("Outlook")
messages = session.Inbox.Messages

#
# Although the inbox_messages collection can be accessed
# via getitem-style calls (inbox_messages[1] etc.) this
# is the recommended approach from Microsoft since the
# Inbox can mutate while you're iterating.
#
message = messages.GetFirst ()
while message:
    print message.Subject
    message = messages.GetNext ()

However I get an error:

pywintypes.com_error: (-2147221005, 'Invalid class string', None, None)

Not sure what my profile name is so I tried with:

session.Logon()

to be prompted but that didn’t work either (same error). Also tried both with Outlook open and closed and neither changed anything.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I had the same problem you did – didn’t find much that worked. The following code, however, works like a charm.

import win32com.client

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

inbox = outlook.GetDefaultFolder(6) # "6" refers to the index of a folder - in this case,
                                    # the inbox. You can change that number to reference
                                    # any other folder
messages = inbox.Items
message = messages.GetLast()
body_content = message.body
print body_content

Method 2

I have created my own iterator to iterate over Outlook objects via python. The issue is that python tries to iterates starting with Index[0], but outlook expects for first item Index[1]… To make it more Ruby simple, there is below a helper class Oli with following
methods:

.items() – yields a tuple(index, Item)…

.prop() – helping to introspect outlook object exposing available properties (methods and attributes)

from win32com.client import constants
from win32com.client.gencache import EnsureDispatch as Dispatch

outlook = Dispatch("Outlook.Application")
mapi = outlook.GetNamespace("MAPI")

class Oli():
    def __init__(self, outlook_object):
        self._obj = outlook_object

    def items(self):
        array_size = self._obj.Count
        for item_index in xrange(1,array_size+1):
            yield (item_index, self._obj[item_index])

    def prop(self):
        return sorted( self._obj._prop_map_get_.keys() )

for inx, folder in Oli(mapi.Folders).items():
    # iterate all Outlook folders (top level)
    print "-"*70
    print folder.Name

    for inx,subfolder in Oli(folder.Folders).items():
        print "(%i)" % inx, subfolder.Name,"=> ", subfolder

Method 3

Sorry for my bad English.
Checking Mails using Python with MAPI is easier,

outlook =win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders[5]
Subfldr = folder.Folders[5]
messages_REACH = Subfldr.Items
message = messages_REACH.GetFirst()

Here we can get the most first mail into the Mail box, or into any sub folder. Actually, we need to check the Mailbox number & orientation. With the help of this analysis we can check each mailbox & its sub mailbox folders.

Similarly please find the below code, where we can see, the last/ earlier mails. How we need to check.

`outlook =win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders[5]
Subfldr = folder.Folders[5]
messages_REACH = Subfldr.Items
message = messages_REACH.GetLast()`

With this we can get most recent email into the mailbox.
According to the above mentioned code, we can check our all mail boxes, & its sub folders.

Method 4

I had the same issue. Combining various approaches from the internet (and above) come up with the following approach (checkEmails.py)

class CheckMailer:

        def __init__(self, filename="LOG1.txt", mailbox="Mailbox - Another User Mailbox", folderindex=3):
            self.f = FileWriter(filename)
            self.outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI").Folders(mailbox)
            self.inbox = self.outlook.Folders(folderindex)


        def check(self):                
        #===============================================================================
        # for i in xrange(1,100):                           #Uncomment this section if index 3 does not work for you
        #     try:
        #         self.inbox = self.outlook.Folders(i)     # "6" refers to the index of inbox for Default User Mailbox
        #         print "%i %s" % (i,self.inbox)            # "3" refers to the index of inbox for Another user's mailbox
        #     except:
        #         print "%i does not work"%i
        #===============================================================================

                self.f.pl(time.strftime("%H:%M:%S"))
                tot = 0                
                messages = self.inbox.Items
                message = messages.GetFirst()
                while message:
                    self.f.pl (message.Subject)
                    message = messages.GetNext()
                    tot += 1
                self.f.pl("Total Messages found: %i" % tot)
                self.f.pl("-" * 80)
                self.f.flush()

if __name__ == "__main__":
    mail = CheckMailer()
    for i in xrange(320):  # this is 10.6 hours approximately
            mail.check()
            time.sleep(120.00)

For concistency I include also the code for the FileWriter class (found in FileWrapper.py). I needed this because
trying to pipe UTF8 to a file in windows did not work.

class FileWriter(object):
    '''
    convenient file wrapper for writing to files
    '''


    def __init__(self, filename):
        '''
        Constructor
        '''
        self.file = open(filename, "w")

    def pl(self, a_string):
        str_uni = a_string.encode('utf-8')
        self.file.write(str_uni)
        self.file.write("n")

    def flush(self):
        self.file.flush()


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x