Python向Roundcube发送多图内嵌邮件仅显示1张图问题求解
问题诊断
代码出现仅显示1张内嵌图、其余变成异常附件的问题,核心是两个MIME配置错误:
- 所有图片的
Content-ID头全部设置为相同的<image>,CID是邮件内资源的唯一标识,重复后客户端只能匹配到第一个资源,剩余图片无法和正文的cid引用建立映射 - 遍历图片的循环中,每次都新建独立的HTML格式MIMEText节点追加到
multipart/alternative容器中,不符合MIME规范:该容器下仅允许挂载1份纯文本正文、1份HTML正文,重复追加的HTML节点会被Roundcube识别为无效附件,显示为名称异常的courriel html
修复代码
调整逻辑:提前拼接包含所有图片引用的完整HTML正文,为每张图片分配全局唯一的CID,再统一挂载MIME节点,修正后的可运行代码如下:
from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage import os import smtplib # 基础发信配置 strFrom = 'x@x.com' strTo = 'x@x.com' dest = "/home/user/Bureau/photos/" # 初始化MIME根容器 msgRoot = MIMEMultipart('related') msgRoot['Subject'] = 'test message' msgRoot['From'] = strFrom msgRoot['To'] = strTo msgRoot.preamble = 'This is a multi-part message in MIME format.' # 初始化alternative容器,挂载纯文本/HTML两种正文 msgAlternative = MIMEMultipart('alternative') msgRoot.attach(msgAlternative) msgText = MIMEText('This is the alternative plain text message.') msgAlternative.attach(msgText) # 遍历目录下的图片文件,生成唯一CID和对应HTML标签 html_content = "" dirmail = [f for f in os.listdir(dest) if f.lower().endswith(('.jpg', '.jpeg', '.png'))] print(f'(mail.py): 待嵌入图片数量{len(dirmail)}') for idx, filename in enumerate(dirmail): # 为每张图片生成唯一CID,避免重复 cid = f"image_{idx}" # 把图片引用拼到统一的HTML正文中 html_content += f'<img src="cid:{cid}"><br>' # 读取图片二进制内容,绑定对应CID file_path = os.path.join(dest, filename) with open(file_path, 'rb') as fp: msgImage = MIMEImage(fp.read(), _subtype='jpg') msgImage.add_header('Content-ID', f'<{cid}>') # 图片统一挂载到related根容器下 msgRoot.attach(msgImage) # 读取完成后再删除文件,避免读文件前删除导致报错 os.remove(file_path) print(f"remove {filename}") # 把拼接完成的完整HTML正文只挂载一次到alternative容器 msgHtml = MIMEText(html_content, 'html') msgAlternative.attach(msgHtml) # SMTP发信逻辑 session = smtplib.SMTP('x', x) session.starttls() session.login("x", "x") session.sendmail(strFrom, strTo, msgRoot.as_string()) session.quit() print('Mail Sent')
关键调整点
- 每张图片使用
image_序号生成唯一CID,和HTML中img标签的cid引用一一对应 - 所有img标签统一拼接为一个完整的HTML字符串,仅生成一次MIMEText节点挂载,避免重复节点被识别为附件
- 调整文件删除时机:读取完文件内容、挂载完MIME节点后再执行删除,避免文件操作异常导致读文件失败
- 增加文件后缀过滤,避免读取目录下非图片文件导致的解析错误
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

