You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 07:15:07