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

如何在ASP .NET Core 7中发送含CSS与图片的HTML邮件

问题描述

我正在用ASP .NET Core 7结合SMTP和MailKit发送带HTML标签的邮件,目前能发送简单HTML邮件,但现在需要发送包含页眉、页脚和Logo图片的HTML邮件。尝试插入相关HTML代码后遇到了错误,想解决以下问题:

  • 如何在邮件正文中插入包含CSS和图片的HTML代码?
  • 这个错误是我的API代码导致的吗?
  • 有没有其他实现方式?

我的.NET邮件服务代码

using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using MimeKit.Text;

namespace AgrarianTradeSystemWebAPI.Services.EmailService
{
    public class EmailService : IEmailService
    {
        private readonly IConfiguration _config;

        public EmailService(IConfiguration config)
        {
            _config = config;
        }

        public void SendEmail(EmailDto request)
        {
            var email = new MimeMessage();
            email.From.Add(MailboxAddress.Parse(_config.GetSection("EmailConfig:EmailUsername").Value));
            email.To.Add(MailboxAddress.Parse(request.To));
            email.Subject = request.Subject;
            email.Body = new TextPart(TextFormat.Html) { Text = request.Body };
            using var smtp = new SmtpClient();
            smtp.Connect(_config.GetSection("EmailConfig:EmailHost").Value, 587, SecureSocketOptions.StartTls);
            smtp.Authenticate(_config.GetSection("EmailConfig:EmailUsername").Value, _config.GetSection("EmailConfig:EmailPassword").Value);
            smtp.Send(email);
            smtp.Disconnect(true);
        }
    }
}

DTO类代码

public class EmailDto
{
    public string To { get; set; } = string.Empty;
    public string Subject { get; set; } = string.Empty;
    public string Body { get; set; } = string.Empty;
}

React端发送请求代码

try {
        const response = await axios.post('https://localhost:7144/Auth/register', formData);
        console.log('Server Response:', response.data);
        if (response.status === 200) {
            const emailResponse = await axios.post('https://localhost:7144/api/Email', emaildata);
            console.log('Email Response:', emailResponse.data);
        }
    } catch (error) {
        console.error('Error:', error.response.data);
        if(error.response.data === "Email exist"){
            alert('Error: Email already exists and you can not register from existing email address');
        }
    }

解决方案

1. 错误原因分析

你遇到的问题核心是:直接用TextPart无法处理内嵌图片资源,且邮件客户端对外部CSS/内嵌样式块的支持有限;另外如果HTML中存在未转义的特殊字符(如引号、换行),也会触发解析错误。

2. 实现带内嵌图片和CSS的HTML邮件

要发送包含Logo和样式的邮件,需要用MultipartRelated构建邮件体,将图片作为内嵌资源嵌入,同时优先使用内联CSS保证兼容性。

修改后的邮件服务代码

using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using MimeKit.Text;

namespace AgrarianTradeSystemWebAPI.Services.EmailService
{
    public class EmailService : IEmailService
    {
        private readonly IConfiguration _config;

        public EmailService(IConfiguration config)
        {
            _config = config;
        }

        // 改为异步方法,避免阻塞主线程
        public async Task SendEmailWithEmbeddedContentAsync(EmailWithEmbeddedContentDto request)
        {
            var email = new MimeMessage();
            email.From.Add(MailboxAddress.Parse(_config["EmailConfig:EmailUsername"]));
            email.To.Add(MailboxAddress.Parse(request.To));
            email.Subject = request.Subject;

            // 创建关联容器,存放HTML和内嵌资源
            var multipart = new MultipartRelated();

            // 添加HTML内容
            var htmlPart = new TextPart(TextFormat.Html)
            {
                Text = request.HtmlBody
            };
            multipart.Add(htmlPart);

            // 嵌入Logo图片(需保证服务器有文件读取权限)
            if (!string.IsNullOrEmpty(request.LogoLocalPath))
            {
                var imagePart = new MimePart("image", "png")
                {
                    Content = new MimeContent(File.OpenRead(request.LogoLocalPath)),
                    ContentId = "email-logo", // 需与HTML中的src="cid:email-logo"对应
                    ContentDisposition = new ContentDisposition(ContentDisposition.Inline),
                    ContentTransferEncoding = ContentEncoding.Base64
                };
                multipart.Add(imagePart);
            }

            email.Body = multipart;

            using var smtp = new SmtpClient();
            await smtp.ConnectAsync(_config["EmailConfig:EmailHost"], 587, SecureSocketOptions.StartTls);
            await smtp.AuthenticateAsync(_config["EmailConfig:EmailUsername"], _config["EmailConfig:EmailPassword"]);
            await smtp.SendAsync(email);
            await smtp.DisconnectAsync(true);
        }
    }
}

对应的DTO类

public class EmailWithEmbeddedContentDto
{
    public string To { get; set; } = string.Empty;
    public string Subject { get; set; } = string.Empty;
    public string HtmlBody { get; set; } = string.Empty;
    public string LogoLocalPath { get; set; } = string.Empty; // Logo在服务器上的本地路径
}

兼容的HTML示例

<!DOCTYPE html>
<html>
<body>
    <!-- 用内联样式保证邮件客户端兼容 -->
    <div style="background-color: #f5f5f5; padding: 15px;">
        <img src="cid:email-logo" alt="平台Logo" width="120" height="60">
    </div>
    <div style="padding: 20px;">
        <p style="font-size: 16px; color: #333;">您好,欢迎注册我们的平台!</p>
    </div>
    <div style="text-align: center; color: #666; font-size: 12px; margin-top: 30px; padding-top: 15px; border-top: 1px solid #eee;">
        <p>© 2024 您的平台名称 版权所有</p>
    </div>
</body>
</html>

3. 关键注意事项

  • 图片引用规则:必须用cid:前缀关联内嵌图片的ContentId,不能直接用本地路径或相对路径;如果使用公网图片,可直接写完整URL。
  • CSS兼容性:90%以上的邮件客户端不支持<style>块和复杂选择器,务必把样式内联到HTML元素上。
  • 特殊字符处理:前端传入HTML时,要转义双引号、换行等特殊字符;后端接收后可通过HttpUtility.HtmlEncode二次处理。
  • 异步优化:将同步方法改为异步,避免占用服务器线程资源。

4. 错误排查方向

如果仍报错,检查以下几点:

  • Logo文件路径是否正确,服务器是否有读取权限。
  • HTML中的cid:值是否与代码中设置的ContentId完全一致(大小写敏感)。
  • HTML是否存在未闭合标签、语法错误。
  • SMTP服务器配置(主机、端口、账号密码)是否正确。

内容的提问来源于stack exchange,提问作者Rashmina Amarasinghe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 11:44:52