web-dev-qa-db-fra.com

Lecture d'e-mails à partir d'Outlook avec Python via MAPI

J'essaie d'écrire un court programme qui lit le contenu des courriers électroniques dans un dossier de mon profil Exchange/Outlook afin de pouvoir manipuler les données. Cependant, je ne parviens pas à trouver beaucoup d’informations sur l’intégration python et Exchange/Outlook. Beaucoup de choses sont soit très anciennes/n'ont pas de documentation/ne sont pas expliquées. J'ai essayé plusieurs extraits mais semble avoir les mêmes erreurs. J'ai essayé le code de Tim Golden:

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 ()

Cependant je reçois une erreur:

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

Je ne suis pas sûr du nom de mon profil et j'ai donc essayé avec:

session.Logon()

être invité mais cela ne fonctionnait pas non plus (même erreur). Aussi essayé les deux avec Outlook ouvert et fermé et ni rien changé.

36
johnharris85

J'ai eu le même problème que vous - vous n'avez pas trouvé grand chose qui a fonctionné. Le code suivant, cependant, fonctionne comme un charme.

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
56
Bobby

J'ai créé mon propre itérateur pour parcourir des objets Outlook via python. Le problème est que python essaie d’itérer à partir de Index [0], mais Outlook attend le premier élément Index [1] ... Pour simplifier, il existe une classe d’aide Oli avec les méthodes suivantes: : 

.items () - donne un tuple (index, item) ... 

. prop () - aide à l'introspection d'objet Outlook exposant les propriétés disponibles (méthodes et attributs)

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
12
Martin Stancik

Désolé pour mon mauvais anglais. Vérifier les mails en utilisant Python avecMAPIest plus facile, 

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

Ici, nous pouvons obtenir le plus grand nombre de premiers courriers dans la boîte aux lettres ou dans n’importe quel sous-dossier. En fait, nous devons vérifier le numéro et l’orientation de la boîte aux lettres. À l'aide de cette analyse, nous pouvons vérifier chaque boîte aux lettres et ses sous-dossiers de boîte aux lettres. 

De même s'il vous plaît trouver le code ci-dessous, où nous pouvons voir, les derniers/mails précédents. Comment nous devons vérifier. 

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

Avec cela, nous pouvons obtenir le courrier électronique le plus récent dans la boîte aux lettres. Selon le code mentionné ci-dessus, nous pouvons vérifier toutes nos boîtes aux lettres et ses sous-dossiers.

3
Ozzius

J'ai eu le même problème. En combinant diverses approches à partir d'Internet (et au-dessus), vous obtenez l'approche suivante (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 __== "__main__":
    mail = CheckMailer()
    for i in xrange(320):  # this is 10.6 hours approximately
            mail.check()
            time.sleep(120.00)

Par souci de concistance, j'inclus aussi le code de la classe FileWriter (présent dans FileWrapper.py). J'avais besoin de cela parce que Essayer de diriger UTF8 vers un fichier dans Windows ne fonctionnait pas.

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()
1
raptisth