Connect to Exchange mailbox with Python

Tony Meyer picture Tony Meyer · Nov 13, 2008 · Viewed 90.7k times · Source

I need to connect to an Exchange mailbox in a Python script, without using any profile setup on the local machine (including using Outlook). If I use win32com to create a MAPI.Session I could logon (with the Logon() method) with an existing profile, but I want to just provide a username & password.

Is this possible? If so, could someone provide example code? I would prefer if it only used the standard library and the pywin32 package. Unfortunately, enabling IMAP access for the Exchange server (and then using imaplib) is not possible.

In case it is necessary: all the script will be doing is connecting to the mailbox, and running through the messages in the Inbox, retrieving the contents. I can handle writing the code for that, if I can get a connection in the first place!

To clarify regarding Outlook: Outlook will be installed on the local machine, but it does not have any accounts setup (i.e. all the appropriate libraries will be available, but I need to operate independently from anything setup inside of Outlook).

Answer

Erik Cederstrand picture Erik Cederstrand · Jun 18, 2010

I know this is an old thread, but...

If you're using Exchange 2007 or newer, or Office365, take a look at Exchange Web Services. It's a pretty comprehensive SOAP-based interface for Exchange, and you can do pretty much anything Outlook is able to do, including delegate or impersonation access to other user accounts.

http://msdn.microsoft.com/en-us/library/bb204119.aspx

UPDATE: I have released a Python EWS client on PyPI that supports autodiscover, calendars, inbox, tasks, contacts, and more:

from exchangelib import DELEGATE, Account, Credentials

credentials = Credentials(
    username='MYWINDOMAIN\\myusername',  # Or [email protected] for O365
    password='topsecret'
)
account = Account(
    primary_smtp_address='[email protected]', 
    credentials=credentials, 
    autodiscover=True, 
    access_type=DELEGATE
)
# Print first 100 inbox messages in reverse order
for item in account.inbox.all().order_by('-datetime_received')[:100]:
    print(item.subject, item.body, item.attachments)