通过Google SMTP发送HTML邮件样式异常及嵌入图片问题咨询
问题描述
- 场景:通过Google SMTP服务器发送带图片的HTML邮件,已生成包含内联CSS的HTML代码,在浏览器中显示正常,但使用Scala代码发送后,Gmail接收的邮件样式异常。已确认Content-Type设为
text/html且HTML内容完整。 - 咨询:嵌入图片是否需要发送多部分(Multipart)邮件
相关HTML代码:
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html charset=UTF-8" /> </head> <body> <style> body{ padding: 24px; display: flex; justify-content: center; font-family: Arial } .content{ padding: 24px; background-color: #2b2b2b; color: #cfcfd0 ; } .row{ display: flex; flex-direction: row; } .center{ justify-content: center; } .code{ padding: 8px; background-color: #1c1c1c; border: solid 1px #bababa; border-radius: 2px; font-size: 42px; color: #b81414; flex-grow: 1; text-align: center; font-weight: bold; font-family: helvetica } .link { color: #a10000; &:hover{ color: #ef0000; text-decoration: none; } } </style> <div class="content"> <p>Hello <b>example user</b <p>your new account is almost ready<br> to validate your email please use the code</p> <div class="row center"> <span class="code">123123</span> </div><p>Or simply click <a class="link" href="http://localhost:80/verify?id=45&code=123123"><b>Here</b></a></p> <p>If this was not you, you can safely ignore this email</p> </div> </body> </html>
邮件发送Scala代码:
import java.util.Properties import javax.mail._ import javax.mail.internet._ import org.slf4j.{Logger, LoggerFactory} import play.api.Configuration import play.api.libs.json.{JsValue, Json} import scalaj.http.{Http, HttpOptions, HttpResponse} def sendMail(recipient: String, subject: String, content: String): Option[Int] = { refreshAccessToken() try { val message = new MimeMessage(session) message.setFrom(new InternetAddress(mimeSender)) message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient)) message.setSubject(subject) message.setHeader("Content-Type", "text/html") message.setContent(content, "text/html; charset=UTF-8") val transport = session.getTransport("smtp") transport.connect(hostName, senderEmail, accessToken) transport.sendMessage(message, message.getAllRecipients) logger.info("Email Sent!!") Some(recipient.length) } catch { case exception: Exception => logger.error("Mail delivery failed. " + exception) None } }
解决方案
一、样式异常修复
1. 问题根源
Gmail对HTML邮件的CSS支持有严格限制:
- 不支持Flexbox布局(
display:flex、flex-direction等属性会被过滤) - 不支持SCSS嵌套语法(如
.link里的&:hover) - 部分CSS属性会被拦截(如
border-radius可能失效) - HTML语法错误(如未闭合的
<b>标签)也会导致渲染异常
2. 修复步骤
(1)替换Flex布局为表格布局
邮件客户端对表格布局兼容性最佳,重构布局代码:
<table width="100%" cellpadding="0" cellspacing="0"> <tr> <td align="center"> <span style="padding:8px; background-color:#1c1c1c; border:solid 1px #bababa; border-radius:2px; font-size:42px; color:#b81414; font-weight:bold; font-family:helvetica;">123123</span> </td> </tr> </table>
(2)完全内联CSS样式
不要使用<style>标签定义类选择器,直接将样式写在元素的style属性中,同时去掉不支持的:hover伪类:
<div style="padding:24px; background-color:#2b2b2b; color:#cfcfd0;"> <!-- ... --> <a style="color:#a10000;" href="http://localhost:80/verify?id=45&code=123123"><b>Here</b></a>
(3)修正HTML语法错误
将未闭合的<p>Hello <b>example user</b改为<p>Hello <b>example user</b></p>
3. 修复后完整HTML示例
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body style="padding:24px; font-family:Arial;"> <div style="padding:24px; background-color:#2b2b2b; color:#cfcfd0;"> <p>Hello <b>example user</b></p> <p>your new account is almost ready<br> to validate your email please use the code</p> <table width="100%" cellpadding="0" cellspacing="0"> <tr> <td align="center"> <span style="padding:8px; background-color:#1c1c1c; border:solid 1px #bababa; border-radius:2px; font-size:42px; color:#b81414; font-weight:bold; font-family:helvetica;">123123</span> </td> </tr> </table> <p>Or simply click <a style="color:#a10000;" href="http://localhost:80/verify?id=45&code=123123"><b>Here</b></a></p> <p>If this was not you, you can safely ignore this email</p> </div> </body> </html>
二、嵌入图片的处理
是的,嵌入图片需要发送多部分(Multipart)邮件,具体实现如下:
1. Scala代码修改
使用MimeMultipart构建包含HTML和内嵌图片的邮件:
def sendMailWithEmbeddedImage(recipient: String, subject: String, htmlContent: String, imagePath: String, imageCid: String): Option[Int] = { refreshAccessToken() try { val message = new MimeMessage(session) message.setFrom(new InternetAddress(mimeSender)) message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient)) message.setSubject(subject) // 创建关联型多部分内容 val multipart = new MimeMultipart("related") // 添加HTML内容部分 val htmlPart = new MimeBodyPart() htmlPart.setContent(htmlContent, "text/html; charset=UTF-8") multipart.addBodyPart(htmlPart) // 添加内嵌图片部分 val imagePart = new MimeBodyPart() val ds = new FileDataSource(imagePath) imagePart.setDataHandler(new DataHandler(ds)) imagePart.setHeader("Content-ID", s"<$imageCid>") imagePart.setDisposition(MimeBodyPart.INLINE) multipart.addBodyPart(imagePart) message.setContent(multipart) val transport = session.getTransport("smtp") transport.connect(hostName, senderEmail, accessToken) transport.sendMessage(message, message.getAllRecipients) logger.info("Email with embedded image sent!!") Some(recipient.length) } catch { case exception: Exception => logger.error("Mail delivery failed. " + exception) None } }
2. 对应HTML图片标签
HTML中引用内嵌图片需使用cid:图片ID的格式:
<img src="cid:logo.png" alt="Email Logo">
(其中logo.png需与代码中imageCid参数值一致)
内容的提问来源于stack exchange,提问作者Arthur
相关产品推荐
相关产品推荐

