Python使用IMAP获取邮件后如何按标准转发格式发送而非普通发信
按标准规则转发IMAP收取邮件的实现方案
你需要在现有收信逻辑的基础上,解析原始邮件的关键信息,拼接标准转发前缀后构造新邮件再发送,即可实现符合规范的转发效果,而非直接发送原始邮件。
前置注意事项
你现有代码中存在逻辑错误:
messages_id_list = data[0].decode("utf-8").split(' ') messages_id_list = messages_id_list[0] # 本行需要删除
split操作返回的是所有邮件ID的列表,取第一个元素会将列表转为字符串,后续遍历会逐字符读取导致报错,直接删除第二行即可。
完整实现代码
首先补充导入所需依赖:
import imaplib import email import time import smtplib from email.mime.text import MIMEText
现有收信逻辑之后补充转发逻辑,完整代码如下:
IMAP_HOST = "imap.gmail.com" SMTP_PORT = 587 USERNAME = "myemail@gmail.com" PASSWORD = "mypwd" SEARCH_CRITERIA = "ALL" FROM_ADDRESS = "myemail@gmail.com" TO_ADDRESS = "To@gmail.com" FORWARD_TIME_DELAY = 5 EXCEPTION_TIME_DELAY = 60 VERBOSE = True # Open IMAP connection imap_client = imaplib.IMAP4_SSL(IMAP_HOST) imap_client.login(USERNAME, PASSWORD) # Fetch messages' ID list status, _ = imap_client.select("INBOX", readonly=True) if status != "OK": raise Exception("Could not select connect to INBOX.") status, data = imap_client.search(None, SEARCH_CRITERIA) if status != "OK": raise Exception("Could not search for emails.") messages_id_list = data[0].decode("utf-8").split(' ') # 已删除错误的取第一个元素逻辑 if VERBOSE: print("{} messages were found. Forwarding will start immediately.".format(len(messages_id_list))) print("Messages ids: {}".format(messages_id_list)) print() # Fetch each message data messages_sent = [] while len(messages_sent) < len(messages_id_list): msg_id = messages_id_list[len(messages_sent)] status, msg_data = imap_client.fetch(msg_id, '(RFC822)') if status != "OK": raise Exception("Could not fetch email with id {}".format(msg_id)) # 解析原始邮件 for response_part in msg_data: if isinstance(response_part, tuple): original_msg = email.message_from_bytes(response_part[1]) # 提取原始邮件核心元数据 original_from = original_msg.get('From', '') original_date = original_msg.get('Date', '') original_subject = original_msg.get('Subject', '') original_to = original_msg.get('To', '') # 提取原始邮件正文 original_body = '' if original_msg.is_multipart(): # 多部分邮件优先取纯文本正文 for part in original_msg.walk(): if part.get_content_type() == 'text/plain': charset = part.get_content_charset() or 'utf-8' original_body = part.get_payload(decode=True).decode(charset) break else: charset = original_msg.get_content_charset() or 'utf-8' original_body = original_msg.get_payload(decode=True).decode(charset) # 构造标准转发前缀 forward_prefix = f"""---------- Forwarded message --------- From: {original_from} Date: {original_date} Subject: {original_subject} To: {original_to} """ # 拼接完整转发正文 full_forward_body = forward_prefix + original_body # 构造转发邮件对象 forward_msg = MIMEText(full_forward_body, 'plain', 'utf-8') forward_msg['From'] = FROM_ADDRESS forward_msg['To'] = TO_ADDRESS forward_msg['Subject'] = f'Fwd: {original_subject}' # 发送邮件 smtp_host = IMAP_HOST.replace('imap', 'smtp') with smtplib.SMTP(smtp_host, SMTP_PORT) as smtp_client: smtp_client.starttls() smtp_client.login(USERNAME, PASSWORD) smtp_client.sendmail(FROM_ADDRESS, TO_ADDRESS, forward_msg.as_string()) # 标记已发送 messages_sent.append(msg_id) if VERBOSE: print(f"成功转发邮件ID:{msg_id},原主题:{original_subject}") # 转发间隔 time.sleep(FORWARD_TIME_DELAY) imap_client.logout()
可选优化点
- 如果需要保留HTML格式的邮件内容,只需提取
text/html类型的正文,构造MIMEText时将第二个参数改为html即可 - 谷歌邮箱使用该代码时,建议开启应用专用密码登录,避免安全拦截导致SMTP鉴权失败
- 可以添加异常捕获逻辑,单封邮件转发失败时跳过继续处理后续邮件,避免整体流程中断
内容的提问来源于stack exchange,提问作者ibrahim
相关产品推荐
相关产品推荐

