原始地址: https://docs.microsoft.com/en-us/previous-versions/bb446002(v=msdn.10)?redirectedfrom=MSDN

如果遇到了ImportError,参考下面的链接 https://stackoverflow.com/questions/58267574/sending-emails-from-outlook-with-python-not-working

代码:

import pythoncom
import win32com.client

class Contact():
    """Class serves as little more than an enhanced node tree."""
    def __init__(self, exchange_user):
        """
        Establish a core COM object to work off of for subsequent properties.
        Manager and workers are cached, in that they are only gotten once.
        This reduces external calls if we need to access the name or job title multiple times.
        """
        self._exchange_user = exchange_user
        self._manager = None
        self._workers = None
    @property
    def alias(self):
        return self._exchange_user.Alias
    @property
    def department(self):
        return self._exchange_user.Department
    @property
    def office(self):
        return self._exchange_user.OfficeLocation
    @property
    def name(self):
        """
        It is the responsability of the organization controlling the exchange server communicated to by Outlook
        to fill in details such as Name and Job Title.
        """
        return self._exchange_user.Name
    @property
    def cname(self):
        schema = 'http://schemas.microsoft.com/mapi/proptag//0x3A0A001F'
        return self._exchange_user.PropertyAccessor.GetProperty(schema)
    @property
    def title(self):
        """
        It is the responsability of the organization controlling the exchange server communicated to by Outlook
        to fill in details such as Name and Job Title.
        """
        return self._exchange_user.JobTitle
    @property
    def mobilephone(self):
        return self._exchange_user.MobileTelephoneNumber
    @property
    def manager(self):
        """Getting an exchange user's manager is fairly easy, and wrapping each in our class is relatively inexpensive."""
        if self._manager is None:
            self._manager = Contact(self._exchange_user.GetExchangeUserManager())
        return self._manager
    @property
    def workers(self):
        """
        Exchange Users can acquire workers by lists of address entries,
        fortunately each address entry can effortlessly get its exchange user object counterpart.
        A given address entry isn't guaranteed to be an Exchange User, normally, but in this case we're working
        exclusively within Exchange, so the call to acquire an exchange user should not fail.
        Still, though, stranger things have happened.
        """
        if self._workers is None:
            self._workers = []
            for address_entry in self._exchange_user.GetDirectReports():
                self._workers.append(Contact(address_entry.GetExchangeUser()))
        return self._workers
    def __repr__(self):
        """
        Generic repr I've used elsewhere.
        This probably should be changed to better reflect what we want our output to end up looking like.
        """
        return f"{self.__class__.__name__}({self.name}, {self.title})"

def recurse_print_contacts(root_contact, depth=0):
    """
    Depth first chosen because I already had the boilerplate code on hand.
    Also, since this isn't a search then navigating the tree will take just as long if it were breadth first.
    I believe Depth first implementations are easier to understand for any novices, so that helps too.
    """
    # I like seeing the list of users flow through to give me an idea of the speed the program is going.
    # Also since external service calls are the speed bottleneck and not console output this isn't significant.
    print(root_contact,depth)
    this_repr = "{0}{1} ({2})\n".format('\t'*depth, root_contact.name, root_contact.title)
    for worker in root_contact.workers:
        this_repr += recurse_print_contacts(worker, depth+1)
    return this_repr

if __name__ == '__main__':
    # Allow win32com to generate python code files for Outlook. They're imperfect but serve their purpose fairly well.
    generate_cache = win32com.client.gencache.EnsureDispatch("Outlook.Application")
    outlook_namespace = win32com.client.DispatchEx("Outlook.Application").Session
    # The first account, I assume, is the primary account of the exchange mailbox owner using Outlook.
    # After that navigating properties is trivial. Finding the current user's Address Entry probably could've been done better/quicker,
    #   but this is the first series of properties I found that lead me to what I wanted.
    my_address_entry = outlook_namespace.Accounts.Item(1).CurrentUser.AddressEntry
    u = my_address_entry.GetExchangeUser()

    properties = set(['0x39FF001E','0x3A00001F','0x3A00001F','0x3A00001E','0x3A010102','0x3A02001F','0x3A02001F','0x3A02001E',
                      '0x3A03000B','0x3A04000B','0x3A05001F','0x3A05001F','0x3A05001E','0x3A06001F','0x3A06001F','0x3A06001E',
                      '0x3A07001F','0x3A07001F','0x3A07001E','0x3A08001F','0x3A08001F','0x3A08001E','0x3A08001F','0x3A07001F',
                      '0x3A08001E','0x3A09001F','0x3A09001F','0x3A09001E','0x3A0A001F','0x3A0A001F','0x3A0A001E','0x3A0B001F',
                      '0x3A0B001F','0x3A0B001E','0x3A0C001F','0x3A0C001F','0x3A0C001E','0x3A0D001F','0x3A0D001F','0x3A0D001E',
                      '0x3A0E000B','0x3A0F001F','0x3A0F001F','0x3A0F001E','0x3A10001F','0x3A10001F','0x3A10001E','0x3A11001F',
                      '0x3A11001F','0x3A11001E','0x3A120102','0x3A13001F','0x3A13001F','0x3A13001E','0x3A140102','0x3A15001F',
                      '0x3A15001F','0x3A15001E','0x3A16001F','0x3A16001F','0x3A16001E','0x3A17001F','0x3A17001F','0x3A17001E',
                      '0x3A18001F','0x3A18001F','0x3A18001E','0x3A19001F','0x3A19001F','0x3A19001E','0x3A1A001F','0x3A1A001F',
                      '0x3A1A001E','0x3A1B001F','0x3A1B001F','0x3A1B001E','0x3A1B001F','0x3A1B001F','0x3A1B001E','0x3A1C001F',
                      '0x3A1C001F','0x3A1C001E','0x3A1C001F','0x3A1C001F','0x3A1C001E','0x3A1D001F','0x3A1D001F','0x3A1D001E',
                      '0x3A1E001F','0x3A1E001F','0x3A1E001E','0x3A1F001F','0x3A1F001F','0x3A1F001E','0x3A20001F','0x3A20001F',
                      '0x3A20001E','0x3A21001F','0x3A21001F','0x3A21001E','0x3A21001F','0x3A21001F','0x3A21001E','0x3A220102',
                      '0x3A23001F','0x3A23001F','0x3A23001E','0x3A24001F','0x3A24001F','0x3A24001E','0x3A25001F','0x3A25001F',
                      '0x3A25001E','0x3A26001F','0x3A26001F','0x3A26001E','0x3A26001F','0x3A26001F','0x3A26001E','0x3A27001F',
                      '0x3A27001F','0x3A27001E','0x3A27001F','0x3A27001F','0x3A27001E','0x3A28001F','0x3A28001F','0x3A28001E',
                      '0x3A28001F','0x3A28001F','0x3A28001E','0x3A29001F','0x3A29001F','0x3A29001E','0x3A29001F','0x3A29001F',
                      '0x3A29001E','0x3A2A001F','0x3A2A001F','0x3A2A001E','0x3A2A001F','0x3A2A001F','0x3A2A001E','0x3A2B001F',
                      '0x3A2B001F','0x3A2B001E','0x3A2B001F','0x3A2B001F','0x3A2B001E','0x3A2C001F','0x3A2C001F','0x3A2C001E',
                      '0x3A2D001F','0x3A2D001F','0x3A2D001E','0x3A2E001F','0x3A2E001F','0x3A2E001E','0x3A2F001F','0x3A2F001F',
                      '0x3A2F001E','0x3A30001F','0x3A30001F','0x3A30001E','0x3A40000B','0x3A410040','0x3A420040','0x3A43001F',
                      '0x3A43001F','0x3A43001E','0x3A44001F','0x3A44001F','0x3A44001E','0x3A45001F','0x3A45001F','0x3A45001E',
                      '0x3A46001F','0x3A46001F','0x3A46001E','0x3A47001F','0x3A47001F','0x3A47001E','0x3A48001F','0x3A48001F',
                      '0x3A48001E','0x3A49001F','0x3A49001F','0x3A49001E','0x3A4A001F','0x3A4A001F','0x3A4A001E','0x3A4B001F',
                      '0x3A4B001F','0x3A4B001E','0x3A4C001F','0x3A4C001F','0x3A4C001E','0x3A4D0002','0x3A4E001F','0x3A4E001F',
                      '0x3A4E001E','0x3A4F001F','0x3A4F001F','0x3A4F001E','0x3A50001F','0x3A50001F','0x3A50001E','0x3A51001F',
                      '0x3A51001F','0x3A51001E','0x3A520048','0x3A531102','0x3A54101e','0x3A54101F','0x3A54101E','0x3A550003',
                      '0x3A56101E','0x3A56101F','0x3A56101E','0x3A57001F','0x3A57001F','0x3A57001E','0x3A58101E','0x3A58101F',
                      '0x3A58101E','0x3A59001F','0x3A59001F','0x3A59001E','0x3A5A001F','0x3A5A001F','0x3A5A001E','0x3A5B001F',
                      '0x3A5B001F','0x3A5B001E','0x3A5C001F','0x3A5C001F','0x3A5C001E','0x3A5D001F','0x3A5D001F','0x3A5D001E',
                      '0x3A5E001F','0x3A5E001F','0x3A5E001E','0x3A5F001F','0x3A5F001F','0x3A5F001E','0x3A60001F','0x3A60001F',
                      '0x3A60001E','0x3A61001F','0x3A61001F','0x3A61001E','0x3A62001F','0x3A62001F','0x3A62001E','0x3A63001F',
                      '0x3A63001F','0x3A63001E','0x3A64001F','0x3A64001F','0x3A64001E'])

    for property in properties:
        try:
            p = u.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/{}".format(property))
            print('{}:{} found!!!'.format(property, p))
        except:
            print('{} not found'.format(property))

    this_contact = Contact(my_address_entry.GetExchangeUser())
    CEO_name = "Jone, Black" # whatever the root user's name of the tree is in Exchange
    # Here we hope that someone above us in the organization has the name we specified, or this while loop isn't going to end.
    while this_contact.name != CEO_name:
        this_contact = this_contact.manager
    #this_contact is now the contact for the CEO (or root of the hierarchy we're going to print out)
    whole_repr = recurse_print_contacts(this_contact)
    print(whole_repr)

Published

Category

Windows

Tags