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

Python如何在电子邮件中添加多张内嵌图片并搭配对应文本

Python 邮件批量内嵌图片+配套差异化文本实现方案

你现有的单张内嵌图片逻辑可以直接扩展,核心是把单图场景下「生成唯一Content-ID、拼接HTML片段、挂载关联资源」三个步骤放到循环中批量处理即可,不需要修改底层邮件构造逻辑。

核心注意事项

  • 每张图片必须分配全局唯一的Content-ID(CID),禁止复用同一个CID,否则所有图片引用都会指向最后一个挂载的资源
  • 不要提前写死HTML正文,先遍历素材列表动态拼接每一段「文本+图片」的HTML片段,最后统一组装为完整HTML正文
  • 整个邮件只需要调用一次add_alternative挂载HTML正文,所有图片都作为关联资源挂载到该HTML对应的payload下,不要在循环中重复挂载HTML正文

完整可运行示例代码

from email.message import EmailMessage
from email.utils import make_msgid
import mimetypes
import os

# 1. 初始化邮件基础信息
msg = EmailMessage()
msg['Subject'] = '未来10天天气预报'
msg['From'] = '气象通知 <weather@example.com>'
msg['To'] = '用户 <user@example.org>'

# 2. 配置纯文本兜底正文
msg.set_content('您的邮箱客户端不支持HTML内容,请升级客户端查看完整天气预报。')

# --------------------------
# 3. 准备素材:图片+对应文本的配对列表
# 实际使用时可替换为遍历指定文件夹自动生成的逻辑
# 示例为天气预报场景,每组对应1天的天气描述+天气图标
image_text_pairs = [
    {"img_path": "./weather_img/day1.png", "desc": "10月1日:晴,气温16~26℃,东北风2级,适宜外出"},
    {"img_path": "./weather_img/day2.png", "desc": "10月2日:多云,气温17~27℃,东风2级,紫外线较强"},
    {"img_path": "./weather_img/day3.png", "desc": "10月3日:小雨,气温14~22℃,北风3级,外出请带伞"},
    # 可按需追加任意多组图片+文本配对
]
# 如果需要自动遍历文件夹,可参考以下逻辑替换上述列表:
# img_dir = "./weather_img/"
# desc_list = ["按顺序排列的对应文本1", "按顺序排列的对应文本2", ...]
# image_text_pairs = []
# for idx, img_name in enumerate(sorted(os.listdir(img_dir))):
#     if img_name.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
#         image_text_pairs.append({
#             "img_path": os.path.join(img_dir, img_name),
#             "desc": desc_list[idx]
#         })
# --------------------------

# 4. 动态拼接HTML正文,收集待挂载的图片资源
html_segments = ["<html><body style='font-family: sans-serif;'>"]
to_attach_images = []

for item in image_text_pairs:
    # 为当前图片生成唯一CID
    img_cid = make_msgid(domain='example.com')
    # 拼接当前段落:文本在上,图片在下
    html_segments.append(
        f'<div style="margin: 16px 0; padding-bottom: 12px; border-bottom: 1px solid #eee;">'
        f'<p style="font-size: 16px; margin: 0 0 8px 0;">{item["desc"]}</p>'
        f'<img src="cid:{img_cid[1:-1]}" style="max-width: 600px; border-radius: 4px;">'
        f'</div>'
    )
    # 读取图片二进制数据、识别MIME类型,暂存待挂载
    mime_type = mimetypes.guess_type(item["img_path"])[0]
    maintype, subtype = mime_type.split('/')
    with open(item["img_path"], 'rb') as f:
        img_bytes = f.read()
    to_attach_images.append( (img_bytes, maintype, subtype, img_cid) )

html_segments.append("</body></html>")
full_html_content = "\n".join(html_segments)

# 5. 挂载HTML正文
msg.add_alternative(full_html_content, subtype='html')

# 6. 批量挂载所有内嵌图片
for img_data, maintype, subtype, cid in to_attach_images:
    msg.get_payload()[1].add_related(
        img_data,
        maintype=maintype,
        subtype=subtype,
        cid=cid
    )

# 后续可直接通过smtplib发送邮件,或写入本地eml文件
# with open("weather_forecast.eml", "wb") as f:
#     f.write(msg.as_bytes())

常见问题排查

  • 如果收件方看不到图片:检查CID引用时是否去掉了前后的尖括号(即代码中cid[1:-1]的处理是否保留),尖括号是CID的标识符,不能直接写到img的src属性里
  • 如果所有图片都显示成最后一张:检查是否在循环中重复生成了同一个CID,或CID和图片的对应关系写错
  • 如果图片作为附件显示而不是内嵌:检查是否把图片add_related到了正确的payload(即HTML正文对应的payload,索引为1的子节点),不要直接调用add_attachment方法

内容的提问来源于stack exchange,提问作者zar30

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:36:17