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

通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:10:59