Tech

Python读取Outlook的日历

公司的会议预订系统使用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)。

Folders

所以其实就是要读取Outlook中名为Calendar的Folder,要获得会议预订记录,取出Folder的Items进行迭代就可以了:

#!/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是层级结构,也可以用其它方式获取到,例如:

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返回多个:

#!/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中的权限要先打开,否则会提示找不到对象。

#!/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):
Folders

如果是灰色,可以直接在注册表中修改:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\15.0\Outlook\Security]
@=""
"ObjectModelGuard"=dword:00000002
avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒