1

I've read this post How can I search the Outlook (2010) Global Address List for a name? and found a working solution for getting a name from Outlook GAL.

I have 3 questions:

  1. I can get the contact if the search_string is an email address. When it's a name, the search doesn't work. It would return False for resolved, but True for sendable. Then I get error when using ae object. What am I doing wrong?

  2. I don't understand the code enough to modify it for searching multiple names. I simply created a for loop but maybe there is a more efficient way? For example, can I reuse the outlook.Session object between different searches?

  3. Is the line recipient.Resolve() necessary?

Thanks in advance!

My attempt is below.

from __future__ import print_function
import win32com.client

search_strings = ['Doe John', 'Doe Jane']

outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')

for search_string in search_strings:
    recipient = outlook.Session.CreateRecipient(search_string)
    recipient.Resolve()
    print('Resolved OK: ', recipient.Resolved)
    print('Is it a sendable? (address): ', recipient.Sendable)
    print('Name: ', recipient.Name)

    ae = recipient.AddressEntry
    email_address = None

    if 'EX' == ae.Type:
        eu = ae.GetExchangeUser()
        email_address = eu.PrimarySmtpAddress

    if 'SMTP' == ae.Type:
        email_address = ae.Address

    print('Email address: ', email_address)
Tim
  • 3,178
  • 1
  • 13
  • 26

1 Answers1

1

Can't believe I found the solution so quickly after posting the question. Since it's hard to find the answer. I'm sharing my findings here.

It's inspired by How to fetch exact match of addressEntry object from GAL (Global Address List), though it's in c# rather than python.

This method uses exact match of displayname rather than relying on outlook to resolve the name. Though, it's possible to loop through the global address list and do partial match yourself.

import win32com.client

search_string = 'Doe John'

outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')
gal = outlook.Session.GetGlobalAddressList()
entries = gal.AddressEntries
ae = entries[search_string]
email_address = None

if 'EX' == ae.Type:
    eu = ae.GetExchangeUser()
    email_address = eu.PrimarySmtpAddress

if 'SMTP' == ae.Type:
    email_address = ae.Address

print('Email address: ', email_address)
Tim
  • 3,178
  • 1
  • 13
  • 26
  • Do not ever loop through all items in GAL - some GAL containers contain 100,000 or more entries. – Dmitry Streblechenko Feb 20 '19 at 23:22
  • You are right! I just learned the lesson the hard way. But I guess I can do a binary search with the index maybe. – Tim Feb 20 '19 at 23:28
  • You can't - anything that iterates over all items is bad. Let the server do the work - either ResolveName in OOM or, if Redemption is an option, RDOSession.AddressBook.GAL.ResolveNameEx – Dmitry Streblechenko Feb 21 '19 at 00:33
  • Resolve doesn’t work for me as it doesn’t even work in outlook. I’ll give the second option a try. Is there a way to search by displayname? – Tim Feb 21 '19 at 00:41
  • Sure, both Extended MAPi (PR_AND) and RDOSession.AddressBook.GAL.ResolveNameEx in Redemption search by display name. You can then iterate over the returned list of matches. – Dmitry Streblechenko Feb 21 '19 at 00:45
  • Perfect! I’ll give those a try. Thanks! – Tim Feb 21 '19 at 00:56
  • @DmitryStreblechenko how do I get the RDOSession object? I tried `outlook.CreateObject('Redemption.RDOSession')` but that doesn't work. – Tim Feb 21 '19 at 15:18
  • @DmitryStreblechenko sorry stupid question, is Redemption something I have to install for the RDOSession to work? – Tim Feb 21 '19 at 15:26