Nagri
Nagri

Reputation: 3136

Retrieving outlook Contacts via python win32com

I am Trying to get Contacts out of Outlook using Python. The code is :

import win32com.client
import pywintypes

o = win32com.client.Dispatch("Outlook.Application")
ns = o.GetNamespace("MAPI")
profile = ns.Folders.Item("Outlook")
contacts = profile.Folders.Item("Contacts")

but its giving error like this:

Traceback (most recent call last):
  File "my_pro.py", line 7, in <module>
    profile = ns.Folders.Item("Outlook")
  File "C:\DOCUME~1\Manoj\LOCALS~1\Temp\gen_py\2.7\00062FFF-0000-0000-C000-00000
0000046x0x9x3\_Folders.py", line 70, in Item
    ret = self._oleobj_.InvokeTypes(81, LCID, 1, (9, 0), ((12, 1),),Index
pywintypes.com_error: (-2147352567, 'Exception occurred.', (4096, u'Microsoft Of
fice Outlook', u'The operation failed. An object could not be found.', None, 0,
-2147221233), None)

I don't understand why it's throwing the error, as I do have a profile named Outlook

Upvotes: 4

Views: 14005

Answers (4)

Cesc
Cesc

Reputation: 1190

If you use python 3.9 and above and you are only interested in email addresses the following is enough.

import win32com.client

outlook = win32com.client.gencache.EnsureDispatch("Outlook.Application")
addresses = outlook.Session.GetGlobalAddressList().AddressEntries

mails = [
    user.PrimarySmtpAddress for x in addresses
    if (user := x.GetExchangeUser()) is not None
]

print(mails)

Upvotes: 1

Trenton McKinney
Trenton McKinney

Reputation: 62403

  • This option works for extracting contacts from the Outlook.pst file, not an Exchange server.
    • See this answer for extracting contacts from the Global Address List on an Exchange server.
  • This requires Outlook installed on Windows, but not running.
    • Tested with python 3.8, Windows 10, Outlook Office 365
  • Once the contacts_items object is created, use the appropriate Property to extract the desired information.
  • I have noticed that outlook.Application.Quit() isn't closing Outlook, so it may need to be closed in Task Manager.
import win32com.client

# create outlook object
outlook = win32com.client.Dispatch("Outlook.Application")
ns = outlook.GetNamespace("MAPI")

# create an object for the contacts in the default folder
contacts_items = ns.GetDefaultFolder(10).Items

# print name and email address
for c in contacts_items:
    print(f'{c.FullName}: {c.Email1Address}')

# create a dict of contacts
contacts = {c.FullName: c.Email1Address for c in contacts_items}

# close the application
outlook.Application.Quit()

MSOutlook Class

import win32com.client


DEBUG = 0

class MSOutlook:
    def __init__(self):
        self.outlookFound = 0
        try:
            self.oOutlookApp = \
                win32com.client.gencache.EnsureDispatch("Outlook.Application")
            self.outlookFound = 1
        except:
            print("MSOutlook: unable to load Outlook")
        
        self.records = []


    def loadContacts(self, keys=None):
        if not self.outlookFound:
            return

        # this should use more try/except blocks or nested blocks
        onMAPI = self.oOutlookApp.GetNamespace("MAPI")
        ofContacts = \
            onMAPI.GetDefaultFolder(win32com.client.constants.olFolderContacts)

        if DEBUG:
            print(f"number of contacts: {len(ofContacts.Items)}")

        for oc in range(len(ofContacts.Items)):
            contact = ofContacts.Items.Item(oc + 1)
            if contact.Class == win32com.client.constants.olContact:
                if keys is None:
                    # if we were't give a set of keys to use
                    # then build up a list of keys that we will be
                    # able to process
                    # I didn't include fields of type time, though
                    # those could probably be interpreted
                    keys = []
                    for key in contact._prop_map_get_:
                        if isinstance(getattr(contact, key), (int, str, unicode)):
                            keys.append(key)
                    if DEBUG:
                        keys.sort()
                        print("Fields\n======================================")
                        for key in keys:
                            print(key)
                record = {}
                for key in keys:
                    record[key] = getattr(contact, key)
                if DEBUG:
                    print(oc, record['FullName'])
                self.records.append(record)

Class Usage

if DEBUG:
    print("attempting to load Outlook")
oOutlook = MSOutlook()
# delayed check for Outlook on win32 box
if not oOutlook.outlookFound:
    print("Outlook not found")
    sys.exit(1)

fields = ['FullName',
            'CompanyName', 
            'MailingAddressStreet',
            'MailingAddressCity', 
            'MailingAddressState', 
            'MailingAddressPostalCode',
            'HomeTelephoneNumber', 
            'BusinessTelephoneNumber', 
            'MobileTelephoneNumber',
            'Email1Address',
            'Body'
            ]

if DEBUG:
#     import time
    print("loading records...")
    startTime = time.time()
# you can either get all of the data fields
# or just a specific set of fields which is much faster
#oOutlook.loadContacts()
oOutlook.loadContacts(fields)
if DEBUG:
    print(f"loading took {time.time() - startTime} seconds")

print(f"Number of contacts: {len(oOutlook.records)}")
    
for i in range(len(oOutlook.records)):
    print(f"Contact: {oOutlook.records[i]['FullName']}")
    print(f"Body:\n{oOutlook.records[i]['Body']}")

Upvotes: 1

FlappyMagikarp
FlappyMagikarp

Reputation: 21

  • This option works for extracting contacts when Outlook is connected to an Exchange server.
  • I managed to find/modify a working solution. It saves the email addresses and the full names of all your contacts in Outlook as a list:
import win32com.client

# Outlook stuff
outApp = win32com.client.gencache.EnsureDispatch("Outlook.Application")
outGAL = outApp.Session.GetGlobalAddressList()
entries = outGAL.AddressEntries

# Empty list to store contact info
data_set = list()

# Iterates through your contact book and extracts/appends them to a list
for entry in entries:
    if entry.Type == "EX":
        user = entry.GetExchangeUser()
        if user is not None:
            if len(user.FirstName) > 0 and len(user.LastName) > 0:
                row = list()
                row.append(user.FirstName)
                row.append(user.LastName)
                row.append(user.PrimarySmtpAddress)
                """print("First Name: " + user.FirstName)
                print("Last Name: " + user.LastName)
                print("Email: " + user.PrimarySmtpAddress)"""
                data_set.append(row)

# Prints list
print(data_set)

Original code: https://www.excelcise.org/getting-information-from-outlook-global-address-list-gal-with-python/

Upvotes: 2

unRheal
unRheal

Reputation: 21

You probably don't have a profile named "Outlook" (Unless you created one)

Usually the "Profile Name" is the name given to the top level folder, that your "Inbox" is in. As in "Personal Folders"

Upvotes: 2

Related Questions