cybertools/agent/crawl/outlook.py
scrat 167e914055 changed outlook.py: now much more data from the outlook mails is available. Now we also can access the date the mail was sent as well when it has been received. Also data about the attachements is now available (if desired).
Minor change to winapi was necessary in order to support the doctests with the changed outlook api.
_prop_map_get now returns a dictionary instead of a tuple.

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2577 fd906abe-77d9-0310-91a1-e0d9ade77398
2008-05-04 21:26:57 +00:00

199 lines
7.6 KiB
Python

#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Outlook Crawler Class.
$Id$
"""
import re
from email import MIMEMultipart
from zope.interface import implements
from twisted.internet import defer
#from pywintypes import com_error
#The watsup import is needed as soon as we start handling the Outlook Pop-Up
#again
#This should also be integrated within the wrapper-api for doctests
#from watsup.winGuiAuto import findTopWindow, findControl, findControls, clickButton, \
# getComboboxItems, selectComboboxItem, setCheckBox
from cybertools.agent.base.agent import Agent, Master
from cybertools.agent.crawl.mail import MailCrawler
from cybertools.agent.crawl.mail import MailResource
from cybertools.agent.components import agents
from cybertools.agent.system.windows import api
from cybertools.agent.util.task import coiterate
# some constants
COMMASPACE = ', '
class OutlookCrawler(MailCrawler):
keys = ""
inbox = ""
subfolders = ""
pattern = ""
def collect(self, filter=None):
self.result = []
self.d = defer.Deferred()
self.oOutlookApp = None
if self.findOutlook():
self.fetchCriteria()
coiterate(self.crawlFolders()).addCallback(self.finished).addErrback(self.error)
else:
pass
#self.d.addErrback([])
return self.d
def error(self, reason):
print '***** error',
print reason
def finished(self, result):
self.d.callback(self.result)
def fetchCriteria(self):
criteria = self.params
self.keys = criteria.get('keys')
self.inbox = criteria.get('inbox') #boolean
self.subfolders = criteria.get('subfolders') #boolean
self.pattern = criteria.get('pattern')
if self.pattern != '' and self.pattern != None:
self.pattern = re.compile(criteria.get('pattern') or '.*')
def crawlFolders(self):
onMAPI = self.oOutlookApp.GetNamespace("MAPI")
ofInbox = \
onMAPI.GetDefaultFolder(api.client.constants.olFolderInbox)
# fetch mails from inbox
if self.inbox:
for m in self.loadMailsFromFolder(ofInbox):
yield None
# fetch mails of inbox subfolders
if self.subfolders and self.pattern is None:
lInboxSubfolders = getattr(ofInbox, 'Folders')
for of in range(lInboxSubfolders.__len__()):
# get a MAPI-subfolder object and load its emails
for m in self.loadMailsFromFolder(lInboxSubfolders.Item(of + 1)):
yield None
elif self.subfolders and self.pattern:
lInboxSubfolders = getattr(ofInbox, 'Folders')
for of in range(lInboxSubfolders.__len__()):
# get specified MAPI-subfolder object and load its emails
if self.pattern.match(getattr(lInboxSubfolders.Item(of + 1), 'Name')):
for m in self.loadMailsFromFolder(lInboxSubfolders.Item(of + 1)):
yield None
def loadMailsFromFolder(self, folder):
# get items of the folder
folderItems = getattr(folder, 'Items')
for item in range(len(folderItems)):
mail = folderItems.Item(item+1)
if mail.Class == api.client.constants.olMail:
if self.keys is None:
self.keys = []
for key in mail._prop_map_get_.items():
try:
if isinstance(key[0], (int, str, unicode, bool)):
self.keys.append(key[0])
except api.com_error:
pass
record = {}
for key in self.keys:
try:
if (hasattr(mail, key)):
value = getattr(mail, key)
if isinstance(value, (int, str, unicode, bool)):
record[key] = value
else:
record[key] = "Invalid data format"
except:
record[key] = "Requested attribute not available"
# Create the mime email object
msg = self.createEmailMime(record)
# Create a resource and append it to the result list
self.createResource(msg, folder, "Microsoft Office Outlook")
yield None
def login(self):
pass
def handleOutlookDialog(self):
"""
This function handles the outlook dialog, which appears if someone
tries to access to MS Outlook.
"""
hwnd = None
while True:
hwnd = api.ctypes.windll.user32.FindWindowExA(None, hwnd, None, None)
if hwnd == None:
break
else:
val = u"\0" * 1024
api.ctypes.windll.user32.GetWindowTextW(hwnd, val, len(val))
val = val.replace(u"\000", u"")
if val and repr(val) == "u'Microsoft Office Outlook'":
print repr(val)
# get the Main Control
form = api.findTopWindow(wantedText='Microsoft Office Outlook')
controls = findControls(form)
# get the check box
checkBox = findControl(form, wantedText='Zugriff')
setCheckBox(checkBox, 1)
# get the combo box
comboBox = findControl(form, wantedClass='ComboBox')
items = getComboboxItems(comboBox)
selectComboboxItem(comboBox, items[3])#'10 Minuten'
# finally get the button and click it
button = findControl(form, wantedText = 'Erteilen')
clickButton(button)
break
def findOutlook(self):
outlookFound = False
try:
self.oOutlookApp = \
api.client.gencache.EnsureDispatch("Outlook.Application")
outlookFound = True
except com_error:
pass
return outlookFound
def createEmailMime(self, emails):
# Create the container (outer) email message.
msg = MIMEMultipart.MIMEMultipart()
for key in emails.keys():
if isinstance(emails[key], (str, unicode)):
msg[key] = emails[key].encode('utf-8')
elif isinstance(emails[key], (list, tuple, dict)):
lst = []
for rec in emails[key]:
lst.append(rec)
msg[key] = COMMASPACE.join(lst)
else:
msg[key] = emails[key]
if emails.has_key('Body'):
msg.preamble = emails['Body'].encode('utf-8')
else:
msg.preamble = "e-Mail body not available"
return msg
agents.register(OutlookCrawler, Master, name='crawl.outlook')