公司的会议预订系统使用Outlook,要读取这些预订记录传到部署在阿里云的数据库。Exchange服务器没办法从外网访问,就在内网某台机器上写了一个脚本,定时执行,来从Outlook中读取日历上的预订记录。
模块:pywin32 (http://sourceforge.net/projects/pywin32/)
环境:Windows 2008 + Outlook 2013 + Python 2.7.8
Filder & Items
因为从来没做过Windows开发,所以先看了一遍文档,主要的概念是Folder(https://msdn.microsoft.com/EN-US/library/ff866772.aspx)。
所以其实就是要读取Outlook中名为Calendar的Folder,要获得会议预订记录,取出Folder的Items进行迭代就可以了:
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/env python # -*- coding:utf-8 -*- import datetime import win32com.client namespace = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI') if __name__ == '__main__': calendar = namespace.GetDefaultFolder(9) for item in calendar.Items: print(item.Subject) |
获取一个Namespace对象 (https://msdn.microsoft.com/EN-US/library/office/ff869368.aspx),Calendar是默认的Folder,所以使用了GetDefaultFolder这个方法。Folder是层级结构,也可以用其它方式获取到,例如:
1 2 3 4 5 6 7 8 |
if __name__ == '__main__': calendar = None for folder in namespace.Folders[0].Folders: if folder.Name.lower() == 'calendar': calendar = folder break for item in calendar.Items: print(item.Subject) |
Find&Restrict
之前的代码是获取所有的Items,如果要对Items进行过滤,可以使用Find或Restrict,它们是属于Items的方法(https://msdn.microsoft.com/EN-US/library/office/ff868813.aspx)。区别是Find返回单个Item,Restrict返回多个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#!/usr/bin/env python # -*- coding:utf-8 -*- import datetime import win32com.client namespace = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI') def _get_filter(): begin = datetime.date.today() end = begin + datetime.timedelta(days=7) #日历中7天内的记录 filter_string = "[Start] >= '" + begin.strftime("%m/%d/%Y") + "' AND [End] <= '" + end.strftime("%m/%d/%Y") + "'" return filter_string if __name__ == '__main__': calendar = namespace.GetDefaultFolder(9) filter_string = _get_filter() item = calendar.Items.Find(filter_string)#返回一条记录 print(item.Subject) items = calendar.Items.Restrict(filter_string)#返回collection for item in items: print(item.Start.Format('%Y-%m-%d')) print(item.Subject) |
Recipient
会议室预订记录是在共享日历(Shared Calendar)上,通过『打开日历(Open Calendar)-打开共享日历(Open Shared Calendar)』的操作,我已经把这个日历添加到『我的日历(My Calendar)』了,但我没办法直接读取它上面的记录。按直观的理解,添加这个日历,它应该是已经加入这个Folder了,结果试验了文档中我能找到的所有相关方法都无法读取。只能用Recipient来读取,但它需要连接Exchange服务器,帐号在AU中的权限要先打开,否则会提示找不到对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/usr/bin/env python # -*- coding:utf-8 -*- import datetime import win32com.client namespace = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI') def _get_filter(): begin = datetime.date.today() end = begin + datetime.timedelta(days=7) filter_string = "[Start] >= '" + begin.strftime("%m/%d/%Y") + "' AND [End] <= '" + end.strftime("%m/%d/%Y") + "'" return filter_string if __name__ == '__main__': recipient = namespace.createRecipient('Shared Calendar Name') resolved = recipient.Resolve() shared_calendar = namespace.GetSharedDefaultFolder(recipient, 9) items = shared_calendar.Items for item in items: print(item.Subject) |
CreateRecipient方法(https://msdn.microsoft.com/EN-US/library/office/ff866418.aspx)接受邮箱地址、日历名字、别名等识别方式,执行之后会新建一个名为Shared Calendars的Group。
Others
执行脚本需要现在Outlook的『文件(FILE) – 选项(Options) – 信任中心(Trust Center) – 信任中心设置(Trust Center Settings)』中关闭警告(从不向我发出可疑活动警告Never ware me about suspicious activity):
如果是灰色,可以直接在注册表中修改:
1 2 3 |
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\15.0\Outlook\Security] @="" "ObjectModelGuard"=dword:00000002 |