导读:本期聚焦于赵六创作的《C#如何使用SmtpClient发送邮件?完整代码示例与常见问题详解》,敬请观看详情。邮件功能在业务系统里出现的频率相当高,比如注册验证、订单通知、日志告警等场景都离不开它。本文围绕C#中SmtpClient类的使用展开,从命名空间引入、MailMessage邮件内容构造,到SmtpClient的Host、Port、Credentials等核心属性配置,给出可直接运行的完整代码。同时介绍SSL加密连接、异步发送、附件添加、HTML正文以及多收件人抄送等进阶用法,并整理了端口选择错误、认证失败、中文乱码、被识别为垃圾邮件等高频踩坑点的排查思路,帮你快速稳定地跑通C#发信功能。

在C#中发送邮件,最经典也是最直接的方式就是使用.NET Framework自带的SmtpClient类。它封装了SMTP协议的交互细节,开发者只需要配置服务器地址、端口、账号密码,再组装好一封MailMessage对象,几行代码就能把邮件发出去。这篇文章会从最基础的同步发送讲起,逐步扩展到附件、HTML正文、异步发送等常用功能,最后把实际项目中容易踩到的坑逐一说明,看完基本可以覆盖绝大多数发信需求。

C#如何使用SmtpClient发送邮件?完整代码示例与常见问题详解

一、SmtpClient发送邮件的基本用法

先来看最简单的例子。发送邮件主要涉及两个类:一个是MailMessage,负责描述邮件本身,包括发件人、收件人、主题、正文等;另一个是SmtpClient,负责和SMTP服务器通信,把邮件真正投递出去。这两个类都位于System.Net.Mail命名空间下,使用前记得先引入。

using System;
using System.Net;
using System.Net.Mail;

class Program
{
    static void Main()
    {
        // 1. 构造邮件对象
        MailMessage mail = new MailMessage();
        mail.From = new MailAddress("sender@ipipp.com", "系统通知");
        mail.To.Add("receiver@example.net");
        mail.Subject = "测试邮件";
        mail.Body = "这是一封来自C#程序的测试邮件。";
        mail.SubjectEncoding = System.Text.Encoding.UTF8;
        mail.BodyEncoding = System.Text.Encoding.UTF8;

        // 2. 配置SMTP客户端
        SmtpClient smtp = new SmtpClient("smtp.ipipp.com", 25);
        smtp.Credentials = new NetworkCredential("sender@ipipp.com", "你的密码或授权码");

        // 3. 发送
        smtp.Send(mail);
        Console.WriteLine("发送成功");
    }
}

这段代码里有几个点值得注意。首先是SubjectEncoding和BodyEncoding,如果收件内容包含中文,强烈建议显式设置为UTF-8,否则在某些客户端上可能出现乱码。其次是Credentials属性,它接受一个NetworkCredential对象,用来完成SMTP身份认证。现在大多数邮件服务商(比如QQ邮箱、163邮箱)都不再允许直接使用登录密码,而是要求使用授权码,在邮箱设置里开启SMTP服务后可以获取。

关于端口的选择,这里多说一句。25端口是SMTP的传统端口,明文传输,很多云服务器厂商出于反垃圾邮件考虑已经封禁了它。465端口是隐式SSL端口,但SmtpClient对这个端口的支持并不好,经常出现连接超时。实际项目中最推荐的是587端口,配合EnableSsl = true使用显式SSL(STARTTLS),兼容性和安全性都比较理想。

二、发送HTML正文、附件与多收件人

实际业务中的邮件往往不是纯文本那么简单。营销通知需要漂亮的HTML排版,订单确认需要附带PDF账单,告警邮件可能要同时发给好几个运维人员。这些需求通过MailMessage的相关属性都能轻松实现。

MailMessage mail = new MailMessage();
mail.From = new MailAddress("sender@ipipp.com", "订单系统");
mail.To.Add("user1@example.net");           // 收件人,可以添加多个
mail.CC.Add("user2@example.net");           // 抄送
mail.Bcc.Add("boss@example.net");           // 密送
mail.Subject = "您的订单已发货";

// HTML正文
mail.IsBodyHtml = true;
mail.Body = "<h2>订单发货通知</h2>" +
            "<p>您的订单 <strong>SO-20240001</strong> 已发出,预计3天送达。</p>";

// 添加附件
Attachment att = new Attachment(@"D:\orders\SO-20240001.pdf",
                                System.Net.Mime.ContentTypeNames.Application.Pdf);
att.Name = "发货单.pdf";
mail.Attachments.Add(att);

using (SmtpClient smtp = new SmtpClient("smtp.ipipp.com", 587))
{
    smtp.EnableSsl = true;
    smtp.Credentials = new NetworkCredential("sender@ipipp.com", "授权码");
    smtp.Send(mail);
}

IsBodyHtml设为true之后,Body属性中的内容会被当作HTML渲染。如果同一封邮件既想要HTML版本又想兼容不支持HTML的客户端,可以使用AlternateView创建纯文本备用视图,这是比较规范的做法。附件部分要注意,Attachment对象持有文件句柄,发送完毕后最好及时释放,用mail.Dispose()或者对附件单独调用Dispose都可以。

To、CC、Bcc三个集合都支持添加多个地址,直接连续调用Add方法即可。区别在于抄送人的地址对所有收件人可见,而密送人的地址是隐藏的。如果收件人列表很长,建议分批发送或者把地址放在Bcc中,一次性发送几十上百个地址很容易触发服务商的反垃圾机制。

三、异步发送与常见报错排查

在Web项目或者接口服务中发送邮件时,同步的Send方法会阻塞当前线程,SMTP服务器响应慢的时候整个请求都会被拖住。这时候应该使用异步方法SendAsync,或者基于任务的写法把发送动作丢到后台。

public static async Task SendMailAsync(string to, string subject, string body)
{
    using (MailMessage mail = new MailMessage())
    {
        mail.From = new MailAddress("sender@ipipp.com", "系统通知");
        mail.To.Add(to);
        mail.Subject = subject;
        mail.Body = body;
        mail.SubjectEncoding = System.Text.Encoding.UTF8;
        mail.BodyEncoding = System.Text.Encoding.UTF8;

        using (SmtpClient smtp = new SmtpClient("smtp.ipipp.com", 587))
        {
            smtp.EnableSsl = true;
            smtp.Credentials = new NetworkCredential("sender@ipipp.com", "授权码");
            await smtp.SendMailAsync(mail);
        }
    }
}

SendMailAsync返回Task对象,配合await使用非常自然,也不会像老的SendAsync那样需要处理SendCompleted事件回调。有一点需要留意:SmtpClient本身不是线程安全的,不要让多个线程共用同一个实例并发发送,正确做法是每次发送都创建新的对象,或者用完即释放。

最后整理几个高频报错。第一类是认证失败,报错信息通常包含authentication failed或者535代码,绝大多数原因是用了登录密码而不是授权码,或者授权码输入有多余空格。第二类是连接超时,优先检查端口是否正确、防火墙是否放行,尤其是用465端口连接失败时,换成587加EnableSsl往往就解决了。第三类是发送成功但收不到,多半是进了垃圾箱,可以从几个方面改善:让发件域名配置SPF、DKIM记录,邮件标题和正文避免大量敏感营销词汇,控制发送频率。第四类是中文乱码,前面提到的编码设置没做的话就容易出现,把SubjectEncoding和BodyEncoding都设为UTF8即可。

另外提一下,微软官方已经将SmtpClient标记为不推荐在新项目中使用,建议的替代方案是MailKit这个开源库。它对现代SMTP特性支持更完整,465隐式SSL没有兼容问题,异步模型也更完善。不过SmtpClient依然能用,对于简单的发信场景或者老项目维护,它的上手成本是最低的。如果项目对邮件功能要求不高,继续使用SmtpClient完全没问题;如果涉及复杂的邮件处理需求,可以考虑迁移到MailKit。

C#发邮件SmtpClientSMTP修改时间:2026-09-16 11:40:36

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0916/57918.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。