MimeMessage.writeTo输出流丢失HTML单引号编码,如何解决?
问题:MIME邮件写入输出流时特殊字符(单引号)被替换为问号
我用以下代码把完整MIME邮件(含头信息)写入输出流,用来生成HTTP响应的完整字符串(getContent()仅返回正文,无法满足需求):
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); mimeMessage.writeTo(outputStream);
但当邮件正文包含如下HTML内容时,其中的单引号(’)被替换成了问号(?):
<td class="email_monthlySummaryGraph_subTitle chart-subtitle" style="border: 0; color: #1D1D1D; font-family: Arial, sans-serif; font-size: 16px; line-height: 1.4; margin: 0; padding-bottom: 20px; padding-left: 0; padding-right: 0; padding-top: 0; text-align: center;" align="center"> That’s 5 kWh less than your highest week this month </td>
我尝试过用下面的代码设置编码,但发现此时字符已经被替换,无法解决问题:
String response = new String( ((ByteArrayOutputStream) resp).toByteArray(), StandardCharsets.UTF_8);
请问怎么在写入输出流时设置正确编码,避免这个问题?
解决方案
核心原因
mimeMessage.writeTo()会按MIME邮件自身指定的编码输出内容,如果邮件的Content-Type字符编码或Content-Transfer-Encoding设置不当(比如使用ASCII而非UTF-8),特殊字符会被替换为问号。后期转字符串时再指定UTF-8已无济于事,因为字节流中已经是错误内容。
具体解决步骤
确保MIME邮件本身使用UTF-8编码
创建或解析邮件时,明确设置字符编码为UTF-8:// 创建MIME邮件时设置编码 mimeMessage.setContent(htmlContent, "text/html; charset=UTF-8"); mimeMessage.setHeader("Content-Transfer-Encoding", "quoted-printable"); // 或base64,确保支持UTF-8 // 解析已有邮件时修正编码 if (mimeMessage.getContentType() != null && !mimeMessage.getContentType().contains("charset=UTF-8")) { mimeMessage.setHeader("Content-Type", mimeMessage.getContentType() + "; charset=UTF-8"); }使用邮件声明的编码转换字节流
若邮件编码已正确,writeTo()输出的字节流符合编码要求,转字符串时需使用邮件指定的编码,而非硬编码UTF-8:ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); mimeMessage.writeTo(outputStream); // 获取邮件实际字符编码 String charset = "UTF-8"; // 默认值 if (mimeMessage.getContentType() != null) { String[] parts = mimeMessage.getContentType().split("charset="); if (parts.length > 1) { charset = parts[1].split(";")[0].trim(); } } String response = new String(outputStream.toByteArray(), charset);避免不必要的编码转换
全程保证字节流编码与邮件声明一致,若邮件Content-Transfer-Encoding为quoted-printable或base64,writeTo()会自动处理编码,无需额外干预,只需转字符串时用对字符集即可。
内容的提问来源于stack exchange,提问作者Srinidhi Murthy
相关产品推荐
相关产品推荐

