re.compile未匹配指定正则模式时如何自动发信至指定邮箱?
实现思路
- 提前把正则表达式编译逻辑移到邮件遍历循环外,避免每处理一封邮件就重复编译正则,减少不必要的性能消耗。
- 为每封待处理邮件新增匹配状态标记,初始值设为未匹配。遍历邮件正文提取到正则匹配项时,除了将匹配结果写入csv文件,同时将标记更新为已匹配。
- 单封邮件的内容解析、正则匹配流程全部跑完后,检查匹配状态标记:如果仍为未匹配状态,就通过SMTP协议将原始邮件原封不动转发到指定邮箱。
- 转发时直接复用原始邮件的完整RFC822内容,避免手动拼接主题、正文导致附件、邮件头信息丢失。
调整后可直接运行的代码
import imaplib import email from email.header import decode_header import csv import re import smtplib from email.message import Message # -------------------------- 配置项 请自行修改 -------------------------- IMAP_SERVER = "你的imap服务器地址,比如imap.qq.com" EMAIL_ACCOUNT = "你的邮箱账号" EMAIL_PASSWORD = "你的邮箱第三方授权码/登录密码" TARGET_FORWARD_EMAIL = "未匹配邮件要转发到的目标邮箱地址" SEARCH_MAIL_COUNT = N # 替换为原代码中的N值,即要遍历的最近N封邮件 # ---------------------------------------------------------------------- # 提前编译正则,无需在循环内重复编译 pattern = re.compile( r"([a-zA-Z]+[0-9]+) Line ([0-9]+) Seq ([0-9]) ([0-9]+/[0-9]+/[0-9]+)") # 初始化IMAP连接 imap = imaplib.IMAP4_SSL(IMAP_SERVER) imap.login(EMAIL_ACCOUNT, EMAIL_PASSWORD) imap.select("INBOX") # 获取收件箱邮件总数,兼容原代码逻辑 res, messages_data = imap.search(None, "ALL") messages = int(messages_data[0].split()[-1]) with open("data.csv", "w", newline="", encoding="utf-8") as f_out: writer = csv.writer(f_out) # 可根据自身需求决定是否保留csv表头 writer.writerow(["标识字段", "行号", "序列值", "日期"]) for i in range(messages, messages - SEARCH_MAIL_COUNT, -1): res, msg_data = imap.fetch(str(i), "(RFC822)") for response in msg_data: if not isinstance(response, tuple): continue # 保留邮件原始字节内容,用于后续转发 raw_email = response[1] msg = email.message_from_bytes(raw_email) # 解码邮件头,兼容多编码场景 subject, encoding = decode_header(msg["Subject"])[0] if isinstance(subject, bytes): subject = subject.decode(encoding if encoding else "utf-8", errors="replace") from_addr, encoding = decode_header(msg.get("From"))[0] if isinstance(from_addr, bytes): from_addr = from_addr.decode(encoding if encoding else "utf-8", errors="replace") print("Subject:", subject) print("From:", from_addr) # 初始化当前邮件的匹配状态为未匹配 has_match = False # 遍历邮件内容块 for part in msg.walk(): payload = part.get_payload(decode=True) if payload is None: continue # 自动识别邮件编码解码,避免乱码报错 charset = part.get_content_charset() body = payload.decode(charset if charset else "utf-8", errors="replace") matches = list(pattern.finditer(body)) if matches: has_match = True writer.writerows(map(lambda m: m.groups(), matches)) # 保留原有逻辑:匹配到第一个文本块就跳出循环 break # 新增转发逻辑:当前邮件无任何匹配项时执行转发 if not has_match: forward_msg = Message() forward_msg["From"] = EMAIL_ACCOUNT forward_msg["To"] = TARGET_FORWARD_EMAIL forward_msg["Subject"] = f"[转发未匹配规则邮件] 原主题:{subject}" forward_msg.set_payload(raw_email) # 连接SMTP服务发送邮件 with smtplib.SMTP_SSL(IMAP_SERVER, 465) as smtp: smtp.login(EMAIL_ACCOUNT, EMAIL_PASSWORD) smtp.send_message(forward_msg, from_addr=EMAIL_ACCOUNT, to_addrs=TARGET_FORWARD_EMAIL) print(f"邮件《{subject}》未匹配规则,已转发到指定邮箱") imap.close() imap.logout()
注意事项
- 代码已补全编码兼容处理,解决原代码直接调用
decode()遇到非UTF-8编码邮件时的报错问题。 - 如果需要匹配邮件所有文本块(比如多段正文、嵌套转发邮件内容),可以删除内容遍历循环里的
break,等所有part遍历完成后再判断匹配状态即可。 - 不同邮箱服务商的SMTP端口可能存在差异,如果465端口连接失败,可以尝试替换为25、587端口,对应调整SMTP连接方式。
- 邮箱登录建议使用专门的第三方服务授权码,不要直接使用账号登录密码,避免账号安全风险。
内容的提问来源于stack exchange,提问作者LaunchCoder33
相关产品推荐
相关产品推荐

