目录
0. 前言
1. 安装win32com模块
2. 打开Outlook并运行代码
3. 谁最关心你
4. 结束语
0. 前言
由于公司的数据库由多人使用同一密码,有人重新申请新密码就会重置原密码,并且通过邮件的形式将新密码发送给使用该数据库的群成员。这就导致部署的服务访问数据库频繁出错,所以想到使用python读取邮件内容里的密码,然后修改服务密码。
1. 安装win32com模块
通过pip安装:
python -m pip install pypiwin32
2. 打开Outlook并运行代码
2.1 这里只读取两级目录,类似下面这样:
2.2 说明
根级目录:Outlook绑定的邮箱账户名称,也可以是Outlook连接的邮件存档名称;
一级目录:是与收件箱(Inbox)同级的目录;
二级目录:是一级目录的子目录,就是自建的二级文件夹;
代码如下:
from win32com.client.gencache import EnsureDispatch as Dispatch
# 固定写法
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
# 根级目录(邮箱名称,包括Outlook读取的存档名称)
Accounts = outlook.Folders
for Account_Name in Accounts:
print('>> 正在查询的帐户名称:{}'.format(Account_Name.Name))
# 一级目录集合(与inbox同级)['收件箱', '发件箱', '已发送', 'xxx', 'xxx']
Level_1_Names = Account_Name.Folders
for Level_1_Name in Level_1_Names:
print('- 正在查询一级目录:{}'.format(Level_1_Name.Name))
# 一级文件夹的mail合集[所有邮件对象]
Mail_1_Messages = Level_1_Name.Items
# 将邮件按接收时间排序
Mail_1_Messages.Sort("[ReceivedTime]", True)
# 开始查看单个邮件的信息
for xx in Mail_1_Messages:
Root_Directory_Name_1 = Account_Name.Name # 记录根目录名称
Level_1_FolderName_1 = Level_1_Name.Name # 记录一级目录名称
Level_2_FolderName_1 = '' # 一级目录肯定没有二级目录,顾留为空
# 接收时间
if (hasattr(xx, 'ReceivedTime')):
ReceivedTime_1 = str(xx.ReceivedTime)[:-6]
else:
ReceivedTime_1 = ''
# 发件人
if (hasattr(xx, 'SenderName')):
SenderName_1 = xx.SenderName
else:
SenderName_1 = ''
# 收件人
if (hasattr(xx, 'To')):
to_to_1 = xx.To
else:
to_to_1 = ''
# 抄送人
if (hasattr(xx, 'CC')):
cc_cc_1 = xx.CC
else:
cc_cc_1 = ''
# 主题
if (hasattr(xx, 'Subject')):
Subject_1 = xx.Subject
else:
Subject_1 = ''
# 邮件MessageID
if (hasattr(xx, 'EntryID')):
MessageID_1 = xx.EntryID
else:
MessageID_1 = ''
# 会话主题
if (hasattr(xx, 'ConversationTopic')):
ConversationTopic_1 = xx.ConversationTopic
else:
ConversationTopic_1 = ''
# 会话ID
if (hasattr(xx, 'ConversationID')):
ConversationID_1 = xx.ConversationID
else:
ConversationID_1 = ''
# 会话记录相对位置
if (hasattr(xx, 'ConversationIndex')):
ConversationIndex_1 = xx.ConversationIndex
else:
ConversationIndex_1 = ''
# 邮件内容
if (hasattr(xx, 'Body')):
EmailBody_1 = xx.Body
else:
EmailBody_1 = ''
# 判断当前查询的一级邮件目录是否有二级目录(若有多级目录,可以参考此段代码)
if Level_1_Name.Folders:
# 二级目录的集合
Level_2_Names = Level_1_Name.Folders
for Level_2_Name in Level_2_Names:
print(' - - 正在查询二级目录:' , Level_1_Name.Name , '//' , Level_2_Name.Name)
# 二级目录的邮件集合
Mail_2_Messages = Level_2_Name.Items
# 开始查看单个邮件的信息
for yy in Mail_2_Messages:
# 记录根目录名称
Root_Directory_Name_2 = Account_Name.Name
# 记录一级目录名称
Level_1_FolderName_2 = Level_1_Name.Name
# 记录二级目录名称
Level_2_FolderName_2 = Level_2_Name.Name
# 接收时间
if (hasattr(yy, 'ReceivedTime')):
ReceivedTime_2 = str(yy.ReceivedTime)[:-6]
else:
ReceivedTime_2 = ''
# 发件人
if (hasattr(yy, 'SenderName')):
SenderName_2 = yy.SenderName
else:
SenderName_2 = ''
# 收件人
if (hasattr(yy, 'To')):
to_to_2 = yy.To
else:
to_to_2 = ''
# 抄送人
if (hasattr(yy, 'CC')):
cc_cc_2 = yy.CC
else:
cc_cc_2 = ''
# 主题
if (hasattr(yy, 'Subject')):
Subject_2 = yy.Subject
else:
Subject_2 = ''
# 邮件MessageID
if (hasattr(yy, 'EntryID')):
MessageID_2 = yy.EntryID
else:
MessageID_2 = ''
# 会话主题
if (hasattr(yy, 'ConversationTopic')):
ConversationTopic_2 = yy.ConversationTopic
else:
ConversationTopic_2 = ''
# 会话ID
if (hasattr(yy, 'ConversationID')):
ConversationID_2 = yy.ConversationID
else:
ConversationID_2 = ''
# 会话记录相对位置
if (hasattr(yy, 'ConversationIndex')):
ConversationIndex_2 = yy.ConversationIndex
else:
ConversationIndex_2 = ''
# 邮件正文内容
if (hasattr(yy, 'Body')):
EmailBody_2 = yy.Body
else:
EmailBody_2 = ''
else:
pass
结果如下:
如果需要保存邮件中的附件,可以这么做:
from win32com.client.gencache import EnsureDispatch as Dispatch
# 获取收件箱目录(数字6代表收件箱)
outlook_accounts = Dispatch('Outlook.Application').GetNamespace('MAPI').GetDefaultFolder(6)
# 收件箱下所有邮件
mails = outlook_accounts.Items
# 邮件按时间排序
mail.Sort('[ReceivedTime]', True)
# 获取第6封邮件的所有附件(下标从1开始)
atts = mails.Item(6)Attachments
# 第6封邮件附件数量
atts_num = atts.Count
# 遍历附件对象
for att in atts:
print('att_name: {}'.format(att.FileName))
# 将附件存入D盘
att.SaveAsFile('D:\{}'.format(att.FileName))
3. 谁最关心你
由第二部分衍生出这一步,统计收件箱中给我发邮件最多的十个人,代码如下:import numpy as np
from collections import Counter
import matplotlib.pyplot as plt
from win32com.client.gencache import EnsureDispatch as Dispatch
class CareMe(object):
def __init__(self):
self.Mail_list_name = []
def mail_list(self):
# 默认第6个为收件箱
outlook_accounts = Dispatch('Outlook.Application').GetNamespace('MAPI').GetDefaultFolder(6)
# 获取收件箱下所有邮件
total_recv = outlook_accounts.Items
# 收件箱下邮件总数
total_num = total_recv.Count
for i in range(1, total_num + 1):
# 收集每封邮件的发件人
self.Mail_list_name.append(total_recv.Item(i).SenderName)
# 获取发件人和邮件数量的对应关系,并按照邮件数量降序排序取前10位
Mail_Sender = sorted(dict(Counter(self.Mail_list_name)).items(), key=lambda x: x[1], reverse=True)[:10]
return Mail_Sender
def drawing_display(self, mail_list):
email_per, email_num = [], []
for data_tuple in mail_list:
email_per.append(data_tuple[0])
email_num.append(data_tuple[1])
# 设置画布大小
fig, ax = plt.subplots(1, 1, figsize=(9, 6))
# 柱体宽度
bar_width = 0.35
# 透明度
opacity = 0.5
# 显示中文和-1
plt.rcParams['font.sans-serif'] = 'Microsoft YaHei'
plt.rsParams['axes.unicode_minus'] = False
# 绘图
plt.bar(x=np.arange(len(email_per)), height=email_num, width=bar_width, alpha=opacity, color='b', label='Person')
# 横轴标签
plt.xlabel('Person')
# 纵轴标签
plt.ylabel('total_number')
# 标题
plt.title('Who cares about you the most?')
# 横轴数据以及间隔
plt.xticks(np.arange(len(email_per)), email_per, rotation=30)
# 纵轴数据起点和最高点设置
plt.ylim(0, max(email_num) + 10)
# 在柱体顶部显示数量
for x, y in enumerate(email_num):
plt.text(x, y + 0.05, '%.0f' % y, ha='center', va='battom', fontsize=10)
# 显示样例
plt.legent()
# 让图像的显示分布正常
plt.tight_layout()
# 保存图片
plt.savefig('care_me_most.jpg', dpi=1080)
plt.show()
plt.close()
if __name__ == '__main__':
care_me = CareMe()
mail_list = care_me.mail_list()
care_me.drawing_display(maillist)
4. 结束语
在测试中发现邮件中的图片和附件不知道如何取出,后续涉及到了再来补充吧,暂时先记录到这里。参考:Python3读取Outlook邮件并写入MySQL - 知乎
完整代码下载: who_care_me.py