Python 是一种解释型, 交互式, 面向对象的编程语言, 不但简单, 开源, 可移植, 而且拥有丰富的 Python 官方和第三方类库. 这些类库的底层代码不一定都是 Python, 还有很多 C/C++ 的身影. 通过 C/C++ 语言实现的代码可以在 Python 中被调用. 所以 Python 也被称为 "胶水语言". 基于 Python 的强大类库, 我们可以实现诸如 web 开发, 自动化管理, 数据分析, 机器学习等各种功能. 今天我要介绍的是如何借助 Python 的 Exchangelib 库轻松实现 Exchange 邮箱的自动化管理. 重点介绍邮箱中的邮件数据和会议日程 \ 日历的在 Python 中的自动化管理操作.
Exchange 是微软的企业级邮件服务系统, 本地 Exchange 版本目前最新的是 Exchange2019. 随着云服务的不断发展, 用户群体也越来越庞大. 很多用户转而使用 Exchange Online 服务或者将本地 Exchange 与 Exchange Online 进行混合部署. 本文的实现代码和案例对本地的 Exchange 和 Exchange Online 邮箱都是适用的.
Exchangelib 是一个强大的 Exchange 客户端 Python 库. 它实现了 Exchange 邮箱的对象关系映射. Exchangelib 库对邮箱的管理操作是通过 EWS (Exchange Web Service) 来实现的. EWS 是 Exchange 邮箱的接口服务. EWS 集成了原来 WebDAV 和 CODEX 的功能, 基于 SOAP 协议. 这使它可以被发送 HTTPS 请求的任何操作系统远程访问. EWS 是非常高效的 Exchange 资源访问接口.
在开始之前, 我们首先在 CMD 中运行命令 pip 来安装 Exchangelib 库 (pip 是 Python 的包管理工具):pip install exchangelib.
接下来导入 exchangelib 和 datetime 等类库:
- from exchangelib import Message,Credentials,Account,htmlBody,Mailbox
- from exchangelib import EWSTimeZone,EWSDateTime
- import datetime as dt
1.1 邮件发送的实现如下:
# 将邮箱的帐号和密码等信息赋值给 account credentials = Credentials("","") account = Account(',credentials=credentials,autodiscover=True) #HTML 中包含的是 HTML 格式的邮件内容 HTML = 'Hello World!' # 在 message 中配置帐号 邮件标题 内容 收件人等信息 message = Message( account=account, subject="For Test", body=HTMLBody(HTML), to_recipients=('',), ) # 发送邮件 message.send()
1.2 邮件获取的实现如下:
# 获取本地时区 tz = EWSTimeZone.localzone() # 获取某一时间段内的邮件内容; 比如获取日期为 3/27/2021 的所有邮件. 首先指定时区, 然后创建时区相关的时间日期类实例. 如果邮件位于收件箱 Inbox 的子文件夹中, 可以如下所示将替换为子文件夹的名字 items = (account.inbox/'').all().filter(datetime_received__range=( dt.datetime(2021, 3, 27, 0, 0, 0, 0, tz), dt.datetime(2021, 3, 27, 23, 59, 59, 0, tz) ))
如果想取前 100 封邮件, 可以使用如下命令:
items = (account.inbox/'Reports').all().order_by('-datetime_received')[0:100]
1.3 邮件转发的实现如下:
items[0].forward(subject='FWD:%s'%items[0].subject, body=Items[0].body, to_recipients=('',))
1.4 邮件删除的实现如下:
items[0].delete()# 完全删除 items[0].soft_delete()# 软删除 可恢复 to_folder = account.root/'Top of Information Store'/'Deleted Items' items[0].move(to_folder)# 移动到已删除文件夹
通过以上的学习, 我们知道了通过 Python 操作 Exchange 邮箱的基本方法. 下面举一个简单的自动化管理邮箱的例子: 比如实现对特定种类的邮件进行自动回复.
# 获取最近一天的未读邮件 today = dt.datetime.today() day = dt.timedelta(days=1) from_date = today - day tz = EWSTimeZone.localzone() tz_time = from_date.replace(tzinfo=tz) items = account.inbox.filter(is_read=False, datetime_received__gte=tz_time) # 针对包含指定标题内容来自指定用户的邮件进行自动回复. 比如自动批示等等. Filter_items = items.filter(subject__contains='xxx', sender='XXX@XXX.com') for item in Filter_items: Items[0].reply_all( subject='', body='xxx' )
通过 Python 不但可以对邮件数据进行自动化操作, 还可以对日历, 任务, 联系人等进行管理. 接下来我们来看一下通过 Python 如何对邮箱中的会议日程 \ 日历进行自动化管理. 首先我们导入 Exchangelib 中的日历相关模块. CalendarItem 类允许您发送您发起的会议请求或取消之前已经安排的会议. 还可以处理接收到的 MeetingRequest 消息. 您可以使用 AcceptItem,TentativelyAcceptItem 和 DeclineItem 类答复这些消息.
from exchangelib import CalendarItem from exchangelib.items import MeetingRequest, MeetingCancellation,SEND_TO_ALL_AND_SAVE_COPY
2.1 会议日程创建的实现如下:
# EWSTimeZone.localzone() 用来获取本地的时区信息 便于将日期转换成本地时区的日期 tz = EWSTimeZone.localzone() # CalenderItem 用来准备会议日程的信息: 比如开始时间和结束时间, 主题, 会议邀请正文, 参会人等等 item = CalendarItem( account=account, folder=account.calendar, start=dt.datetime(2021, 4, 15, 11, 0, 0, 0, tz), end=dt.datetime(2021, 4, 15, 12, 0, 0, 0, tz), subject="For Test", body="meeting test", required_attendees=['xxx@xxx.com,'xxx@xxx.com'] ) # item.save() 用来发送会议邀请邮件 item.save(send_meeting_invitations=SEND_TO_ALL_AND_SAVE_COPY)
2.1 会议日程获取的实现如下:
# 比如我们要获取某一天内的所有会议日程 calendars = account.calendar.all().filter(datetime_received__range=( dt.datetime(2021, 4, 14, 23, 59, 59, 0, tz), dt.datetime(2021, 4, 15, 23, 59, 59, 0, tz) )) # 将会议日程的标题打印输出并查看 for calendar in calendars: print(calendar.subject)
2.2 会议日程取消的实现如下:
# 取消邮件标题为'For Test'的会议日程. 取消命令为 "calendar.cancel()".calendar.subject.find() 用来进行关键字查找, 用于查找对应的邮件项. for calendar in calendars: if calendar.organizer.email_address == account.primary_smtp_address and calendar.subject.find('For Test') >= 0: calendar.cancel()
2.2 自动接收会议邀请的实现如下:
# 通过对收件箱邮件的过滤, 得到会议邀请邮件. 然后针对该类型邮件可以按照如下操作接受会议邀请, 拒绝会议邀请, 暂时接受会议邀请. Body 中可以我定义回复的邮件正文内容. for item in items: if isinstance(item,MeetingRequest): item.accept(body="Accpeted")# 接受会议邀请 item.decline(body="sorry, I have no time")# 拒绝会议邀请 item.tentatively_accept(body="I'll join if I'm free at that time")# 暂时接受会议邀请
实际上 Exchange 邮箱里的数据, 不管是日历还是邮件都是基于文件夹结构的. 我们可以通过命令 "print(account.root.tree())" 来查看邮箱的目录结构.
通过对以上的介绍, 相信大家已经能够掌握基于 Python 的邮箱和日历的基本操作方法. 在实际的自动化应用中, 我们可以基于不同需求来进行定向开发. 基于不同的条件自动化处理相应的数据.
在 IT 运维中, 可以基于我们以上的知识点来获取指定类型邮件, 提取邮件关键信息进行自动处理或者汇总起来以邮件报告的形式自动发送出来以供查看. 这些都是非常好的自动化应该场景. 在日常办公中, 也可以基于我们针对会议日程的知识点来实现自动化处理会议邀请邮件, 定期删除或者存档日历信息等操作.
来源: http://developer.51cto.com/art/202104/658116.htm