网站备案免费的吗,网站开发与维护宣传册,广州番禺,商品推广软文范例200字系列文章目录
python办公自动化–数据可视化#xff08;pandasmatplotlib#xff09;–生成条形图和饼状图 python办公自动化–数据可视化#xff08;pandasmatplotlib#xff09;–生成折线图 python办公自动化–数据可视化#xff08;pandas读取excel文件#xff0c;m…系列文章目录
python办公自动化–数据可视化pandasmatplotlib–生成条形图和饼状图 python办公自动化–数据可视化pandasmatplotlib–生成折线图 python办公自动化–数据可视化pandas读取excel文件matplotlib生成可视化图表 python办公自动化-openpyxl学习-工资表生成工资条 python办公自动化–使用将csv大文件分割为xlsx小文件 python办公自动化----使用pandas和os合并多个订单表 三种方法批量填充订单表中的空白单元格–python,excel vba,excel python办自动化–批量发送带附件的变量邮件示例给员工发送工资条 文章目录系列文章目录前言一、登录邮箱二、记录日志三、搜索解析邮件四、设置搜索条件1.前五十封2.发件人白名单3.邮件主题白名单4.发件日期为今天五、下载.xlsx附件六、关闭邮箱安全退出七.代码整合可直接使用总结前言
今天我们来学习使用python读取邮箱中的邮件并且将里面的附件表格下载到我们本地的文件夹中。
我们这个系列叫做python自动化办公要实现真正意义上的办公自动化就是要解放我们的双手实现全过程的自动化。基本上数据分析的工作分为以下流程收集数据----清晰整理数据-----分析数据-----发送结果 我们前面学习了使用pandas清洗整理数据结合我的另一个专栏–python数据分析学习了python发送带附件的变量邮件发送结果至于最精彩最关键的分析数据这个阶段我们也略微接触了一些今天我们就好好学习一下python读取邮件。
情景设置你是公司的数据分析师每天各个部门的负责人每天八点会将昨天的数据作为附件表格以“order”和“kucun”作为主题发送到你的邮箱你需要使用将每天的邮件里面的附件下载到本地的E盘的“附件下载”这个文件夹中。
一、登录邮箱
# 导入imaplib库用于IMAP协议邮箱操作
import imaplib
# 邮箱登录用户名
email_user youremail
# 邮箱授权码(非登录密码)用于IMAP协议认证
email_password yourpassword
# IMAP服务器地址Foxmail使用QQ邮箱的IMAP服务器
imap_server imap.qq.com
mail imaplib.IMAP4_SSL(imap_server)
# 使用用户名和授权码登录邮箱
mail.login(email_user, email_password)
print(邮箱登录成功)
首先我们要在邮箱的设置界面打开我们的smtp/imap/pop3等服务在这个过程中我们会获得一个授权码通过这个授权码我们就可以将连接到我们的邮箱。我这里登录的是QQ邮箱所以服务器地址就是“imap.qq.com”那么大家在尝试登录的时候就要先把上面的用户名授权码以及邮箱地址改为自己的地址和授权码。 登录成功以后我们才可以进行下面的操作。 二、记录日志
因为我们读取邮件下载附件这个动作并不是只做一次所以我们需要设置日志来记录脚本的运行信息。
# 导入logging库用于记录日志
import logging
# 导入os库用于文件和目录操作
import os
# 附件下载目录使用双反斜杠转义
download_folder E:\\附件下载# 日志系统配置
#
logging.basicConfig(levellogging.DEBUG, # 设置日志级别为DEBUG记录所有级别日志format%(asctime)s - %(levelname)s - %(message)s, # 日志格式: 时间-级别-消息handlers[# 文件处理器将日志写入到下载目录中的email_downloader.log文件logging.FileHandler(os.path.join(download_folder, email_downloader.log)),# 控制台处理器将日志输出到标准输出logging.StreamHandler()]
)
# 获取当前模块的日志记录器实例
logger logging.getLogger(__name__)这里我们在E盘新建一个文件夹叫做“附件下载”在这里面我们会新建一个log文件来保存日志
三、搜索解析邮件
# 导入email.utils用于邮件日期解析
import email.utils
# 导入email.header用于解码邮件头
import email.header# 选择收件箱文件夹
mail.select(inbox)# 执行IMAP搜索命令
status, messages mail.search(None, search_criteria)
if status ! OK: # 检查搜索是否成功raise Exception(邮件搜索失败)# 解析邮件内容为Message对象
email_message email.message_from_bytes(msg_data[0][1])四、设置搜索条件
# 1. FROM 白名单中的任一发件人(使用OR连接)
# 2. SINCE 今天日期
# 3. HAS attachment 必须包含附件
from_clause OR .join([fFROM {sender} for sender in sender_whitelist])
search_criteria f({from_clause} SINCE {today} HAS attachment)
logger.info(f严格模式: 只处理今天({today})收到的邮件)
logger.info(f发件人白名单: {sender_whitelist})
logger.info(f主题白名单: {subject_whitelist})
logger.info(f搜索条件: {search_criteria})1.前五十封 代码如下示例 # 获取邮件ID列表并只取最后50个最新的50封
mail_ids messages[0].split()[-50:]
logger.info(f找到 {len(mail_ids)} 封匹配邮件只处理最近50封)# 从最新到最旧处理邮件
for mail_id in reversed(mail_ids):# 获取邮件完整内容(RFC822格式)status, msg_data mail.fetch(mail_id, (RFC822))if status ! OK: # 如果获取失败则跳过continue通常我们的邮箱每天不会收到太多邮件50封这个量对于一天来说应该绰绰有余了
2.发件人白名单
# 发件人邮箱白名单列表
sender_whitelist [fajianren1163.com, # 示例邮箱1fajianren2gmail.com, # 示例邮箱2
]
if from_header not in sender_whitelist: # 严格检查白名单logger.debug(f跳过非白名单发件人: {from_header})continue通常每天给我们发送邮件的人是固定的我们只需要下载他们发送的邮件里面的附件因此添加发件人白名单这一个限制条件。
3.邮件主题白名单
# 主题白名单列表精确匹配
subject_whitelist [order, # 示例主题1kucun
]
subject email_message[Subject]
if subject not in subject_whitelist: # 严格检查主题白名单logger.debug(f跳过非白名单主题: {subject})continue有时候这部门负责人给我们发的邮件并不是昨天的销售数据所以我们要用邮件主题进行区分 这里和上面的发件人白名单是一样的处理逻辑这里注意两点1.使用英文作为邮件主题比如上面的order和kucun2.注意大小写这里是严格匹配所以大小写需要保持一致
4.发件日期为今天
# 从datetime导入datetime用于日期时间处理
from datetime import datetime# 邮件日期验证
#
try:# 解析邮件日期头mail_date email.utils.parsedate_to_datetime(email_message[Date]) if email_message[Date] else Noneif mail_date and mail_date.date() ! datetime.now().date(): # 如果不是今天则跳过logger.debug(f跳过非今天({mail_date.date()})收到的邮件)continue这里我们需要设置时间为条件确保我们每天下载的都是最新的数据要不然会重复下载前面几天的数据。
五、下载.xlsx附件
# 遍历邮件各部分
#
for part in email_message.walk(): # 递归遍历邮件所有部分if part.get_content_maintype() multipart: # 跳过multipart容器部分continue# 检查是否为.xlsx附件# filename part.get_filename() # 获取附件文件名content_type part.get_content_type() # 获取内容类型# 判断条件# 1. 文件名以.xlsx结尾或# 2. 内容类型是Excel文件if (filename and filename.lower().endswith(.xlsx)) or \(content_type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet):# 处理无文件名的情况# if not filename: # 如果附件没有文件名# 使用邮件ID生成唯一文件名filename fattachment_{mail_id.decode()}.xlsx# 文件名处理# # 解码邮件头中的文件名decoded_name email.header.decode_header(filename)[0][0]if isinstance(decoded_name, bytes):decoded_name decoded_name.decode(utf-8)today_str datetime.now().strftime(%Y%m%d) # 获取当前日期字符串base_name, ext os.path.splitext(decoded_name) # 拆分文件名和扩展名# 生成新文件名格式YYYYMMDD-原文件名.xlsxnew_filename f{today_str}-{base_name}{ext}# 拼接完整的文件保存路径filepath os.path.join(download_folder, new_filename)# 附件保存处理# if not os.path.exists(filepath): # 检查文件是否已存在# 以二进制模式保存附件with open(filepath, wb) as f:f.write(part.get_payload(decodeTrue)) # 解码并写入附件内容logger.info(f下载附件: {filename} - {new_filename})else: # 文件已存在则跳过logger.info(f附件已存在跳过: {new_filename})首先我们根据文件类型筛选出.xlsx格式的附件然后我们将当天的日期和附件的名字结合在一起作为新名字最后我们将附件以新名字命名保存到E盘的‘附件下载”这个文件夹中 六、关闭邮箱安全退出 # 关闭邮箱连接# mail.close() # 关闭当前邮箱文件夹mail.logout() # 退出IMAP会话logger.info(处理完成) # 记录处理完成信息except Exception as e: # 异常处理部分# 记录错误信息包含堆栈跟踪logger.error(f发生错误: {str(e)}, exc_infoTrue) # 确保邮箱连接被正确关闭if mail in locals() and mail.state ! LOGOUT: # 检查mail对象是否存在且未退出try:mail.logout() # 尝试安全退出except:pass # 忽略退出时的任何错误if __name__ __main__:# 当脚本直接运行时执行主函数download_specific_attachments() 七.代码整合可直接使用
# 导入imaplib库用于IMAP协议邮箱操作
import imaplib
# 导入email库用于解析邮件内容
import email
# 导入os库用于文件和目录操作
import os
# 导入logging库用于记录日志
import logging
# 从datetime导入datetime用于日期时间处理
from datetime import datetime
# 导入email.utils用于邮件日期解析
import email.utils
# 导入email.header用于解码邮件头
import email.headerdef download_specific_attachments():下载指定发件人今天发送的邮件中的.xlsx附件主要功能1. 连接IMAP邮箱服务器2. 搜索指定发件人今天发送的邮件3. 只处理最近20封邮件4. 解析邮件内容并识别.xlsx附件5. 下载附件并按指定格式重命名6. 记录完整操作日志# 邮箱服务器配置部分# # 邮箱登录用户名email_user youremail# 邮箱授权码(非登录密码)用于IMAP协议认证email_password yourpassword# IMAP服务器地址Foxmail使用QQ邮箱的IMAP服务器imap_server imap.qq.com# 发件人邮箱白名单列表sender_whitelist [fajianren1163.com, # 示例邮箱1fajianren2gmail.com, # 示例邮箱2]# 主题白名单列表精确匹配subject_whitelist [order , # 示例主题1kucun ]# 附件下载目录使用双反斜杠转义download_folder E:\\附件下载# 日志系统配置# logging.basicConfig(levellogging.DEBUG, # 设置日志级别为DEBUG记录所有级别日志format%(asctime)s - %(levelname)s - %(message)s, # 日志格式: 时间-级别-消息handlers[# 文件处理器将日志写入到下载目录中的email_downloader.log文件logging.FileHandler(os.path.join(download_folder, email_downloader.log)),# 控制台处理器将日志输出到标准输出logging.StreamHandler()])# 获取当前模块的日志记录器实例logger logging.getLogger(__name__)# 创建附件下载目录# exist_okTrue表示如果目录已存在不会报错os.makedirs(download_folder, exist_okTrue)try:# 邮箱连接和登录部分# logger.info(正在连接到IMAP服务器...)# 创建IMAP4_SSL安全连接对象mail imaplib.IMAP4_SSL(imap_server)# 使用用户名和授权码登录邮箱mail.login(email_user, email_password)# 记录登录成功状态logger.info(登录成功)# 选择收件箱文件夹mail.select(inbox)# 构造IMAP搜索条件# # 获取今天的日期格式化为IMAP要求的格式(如21-Jul-2025)today datetime.now().strftime(%d-%b-%Y)# 构造IMAP搜索条件# 1. FROM 白名单中的任一发件人(使用OR连接)# 2. SINCE 今天日期# 3. HAS attachment 必须包含附件from_clause OR .join([fFROM {sender} for sender in sender_whitelist])search_criteria f({from_clause} SINCE {today} HAS attachment)logger.info(f严格模式: 只处理今天({today})收到的邮件)logger.info(f发件人白名单: {sender_whitelist})logger.info(f主题白名单: {subject_whitelist})logger.info(f搜索条件: {search_criteria})# 执行IMAP搜索命令status, messages mail.search(None, search_criteria)if status ! OK: # 检查搜索是否成功raise Exception(邮件搜索失败)# 处理搜索结果# # 获取邮件ID列表并只取最后20个最新的20封mail_ids messages[0].split()[-20:]logger.info(f找到 {len(mail_ids)} 封匹配邮件只处理最近20封)# 从最新到最旧处理邮件for mail_id in reversed(mail_ids):# 获取邮件完整内容(RFC822格式)status, msg_data mail.fetch(mail_id, (RFC822))if status ! OK: # 如果获取失败则跳过continue# 解析邮件内容为Message对象email_message email.message_from_bytes(msg_data[0][1])# 验证发件人是否在白名单中# # 验证邮件主题是否在白名单中并处理中文汉字主题# from_header email.utils.parseaddr(email_message[From])[1] # 解析发件人邮箱if from_header not in sender_whitelist: # 严格检查白名单logger.debug(f跳过非白名单发件人: {from_header})continuetry:# 尝试将邮件主题解码为utf-8处理可能的中文字符问题subject email_message[Subject].encode(latin1).decode(utf-8)except UnicodeDecodeError:# 如果解码失败则记录日志并跳过该邮件logger.warning(邮件主题编码问题跳过该邮件)continueif subject not in subject_whitelist: # 严格检查主题白名单logger.debug(f跳过非白名单主题: {subject})continue# 邮件日期验证# try:# 解析邮件日期头mail_date email.utils.parsedate_to_datetime(email_message[Date]) if email_message[Date] else Noneif mail_date and mail_date.date() ! datetime.now().date(): # 如果不是今天则跳过logger.debug(f跳过非今天({mail_date.date()})收到的邮件)continueelif not mail_date: # 如果邮件没有日期信息则默认处理logger.debug(邮件无日期信息默认处理)except Exception as e: # 日期解析错误处理logger.warning(f日期解析错误: {str(e)}默认处理)# 遍历邮件各部分# for part in email_message.walk(): # 递归遍历邮件所有部分if part.get_content_maintype() multipart: # 跳过multipart容器部分continue# 检查是否为.xlsx附件# filename part.get_filename() # 获取附件文件名content_type part.get_content_type() # 获取内容类型# 判断条件# 1. 文件名以.xlsx结尾或# 2. 内容类型是Excel文件if (filename and filename.lower().endswith(.xlsx)) or \(content_type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet):# 处理无文件名的情况# if not filename: # 如果附件没有文件名# 使用邮件ID生成唯一文件名filename fattachment_{mail_id.decode()}.xlsx# 文件名处理# # 解码邮件头中的文件名decoded_name email.header.decode_header(filename)[0][0]if isinstance(decoded_name, bytes):decoded_name decoded_name.decode(utf-8)today_str datetime.now().strftime(%Y%m%d) # 获取当前日期字符串base_name, ext os.path.splitext(decoded_name) # 拆分文件名和扩展名# 生成新文件名格式YYYYMMDD-原文件名.xlsxnew_filename f{today_str}-{base_name}{ext}# 拼接完整的文件保存路径filepath os.path.join(download_folder, new_filename) # 附件保存处理# if not os.path.exists(filepath): # 检查文件是否已存在# 以二进制模式保存附件with open(filepath, wb) as f: f.write(part.get_payload(decodeTrue)) # 解码并写入附件内容logger.info(f下载附件: {filename} - {new_filename}) else: # 文件已存在则跳过logger.info(f附件已存在跳过: {new_filename}) # 关闭邮箱连接# mail.close() # 关闭当前邮箱文件夹mail.logout() # 退出IMAP会话logger.info(处理完成) # 记录处理完成信息except Exception as e: # 异常处理部分# 记录错误信息包含堆栈跟踪logger.error(f发生错误: {str(e)}, exc_infoTrue) # 确保邮箱连接被正确关闭if mail in locals() and mail.state ! LOGOUT: # 检查mail对象是否存在且未退出try:mail.logout() # 尝试安全退出except:pass # 忽略退出时的任何错误if __name__ __main__:# 当脚本直接运行时执行主函数download_specific_attachments() 点击运行后在我本地的E盘里面的“附件下载”这个文件夹内容如下 可以看到成功下载了附件以及生成了log日志 那么大家在使用上面的代码的时候需要修改的就是邮箱授权码以及发件人白名单和邮件主题白名单了。
总结
今天我们学习了用python读取邮箱里面的邮件并且下载附件到本地我们还设置了时间、发件人以及邮件主题等多个限制条件。其实这里面可以玩的东西远不止这么多我大家可以自行去探索。
OK那么到今天为止我们就讲完了python发邮件以及收邮件我们得到了数据源那么下阶段将正式开始学习python处理数据当然主要是excel表格的数据包括一些匹配、聚合等等当然如果有空也会更新python处理word或者pptx等。
至于下阶段的更新我会放在python数据分析这个专栏。如果大家对上面的文章有不懂的地方也可以随时私信我。同样的如果大家发现哪里不对也欢迎批评指正哈。 大家有兴趣的可以点个关注以及免费的赞赞哟爱你们