结论:必须用mimemultipart("related")包裹html正文和图片两个mimebodypart,图片setcontentid("xxx")须与html中src="cid:xxx"严格一致,且html setcontent需指定"text/html;charset=utf-8",否则客户端因找不到content-id而显示“broken image”。

直接说结论:用 MimeMultipart 嵌套结构 + cid: 引用 + 正确的 Content-ID 和 Content-Type 设置,才能让内嵌图在邮件正文中显示,而不是变成附件或乱码。
为什么图片不显示,只显示“broken image”图标?
常见错误是把图片当成普通附件加进去,没走 multipart/related 流程。邮件客户端看到 <img src="cid:xxx"> 但找不到对应 Content-ID: xxx 的 MimeBodyPart,就放弃渲染。
- 必须用
MimeMultipart("related")包裹文本和图片两个MimeBodyPart -
MimeBodyPart加图片时,setContentID("xxx")的值要和 HTML 中src="cid:xxx"完全一致(区分大小写、无空格) - HTML 部分的
setContent必须指定"text/html"类型,不能漏掉charset(推荐UTF-8) - 图片
MimeBodyPart的DataHandler必须指向真实可读文件路径,否则运行时报FileNotFoundException
如何把附件和内嵌图同时加进一封邮件?
关键在于两层嵌套:related 包正文+图,外层 mixed 再包它和附件。顺序不能错,否则 Outlook 等客户端会忽略内嵌图。
- 先构建
MimeMultipart("related"):里面放 HTML 文本MimeBodyPart和图片MimeBodyPart - 再新建一个
MimeMultipart("mixed"):把上面整个related部分封装成一个MimeBodyPart加进去,然后再加附件MimeBodyPart - 附件部分调用
setFileName(),否则某些客户端(如 Apple Mail)会显示为 “untitled attachment” - 最终调用
message.setContent(mixedMultipart),不是setText()或setContent(..., "text/html")
JavaMail 中 alternative 和 related 的区别在哪?
别混用:alternative 是给同一内容提供纯文本和 HTML 两种版本(客户端自动选),related 是让 HTML 正文能引用同封邮件里的资源(比如图)。它们解决的是完全不同的问题。
-
multipart/alternative:用于text/plain+text/html共存,结构扁平,两个 part 并列 -
multipart/related:用于 HTML + 其依赖的内联资源(图片/CSS),HTML part 必须在前,资源 part 在后,且通过cid:关联 - 实际邮件往往三层:外层
mixed(含附件)、中间related(含 HTML+图)、内层alternative(可选,给 HTML 配纯文本 fallback) - 不要试图用
alternative直接塞图片——它不支持资源关联逻辑
真正容易被忽略的点是:所有 MimeBodyPart 必须属于某个 MimeMultipart,而 MimeMultipart 必须设 setSubType();漏掉这个调用,JVM 不报错,但生成的 .eml 文件里 boundary 缺失,导致绝大多数邮件客户端无法解析内嵌图。











