Go语言使用net/smtp发送电子邮件完整示例

落日邮差
落日邮差
发布时间:2026-10-16 | 5人浏览过
原创

利用Go标准库net/smtp实现电子邮件发送功能。文章详细解析了SendMail和PlainAuth函数的用法,提供了包含服务器配置、认证处理、多收件人循环及HTML内容拼接的完整代码示例,并针对网易邮箱常见的反垃圾邮件拦截错误给出了符合RFC规范的解决方案。

核心函数原理

第1步:理解底层机制

net/smtp包提供了基于简单邮件传输协议(SMTP)的低级接口,具体遵循RFC 5321标准。它主要包含两个关键函数:

  • PlainAuth:创建身份验证机制。使用指定的用户名和密码,通过TLS连接到指定主机。参数中identity通常设为空字符串以直接使用用户名作为身份标识。
  • SendMail:执行发送动作。连接服务器,开启TLS(若支持),进行身份认证,并以指定发件人地址将消息发送至目标列表。

注意:SendMail属于低级机制,不直接支持DKIM签名或MIME附件构造,高级邮件功能需自行组装消息体。

功能实现步骤

第2步:定义数据结构

为了清晰管理配置与内容,建议定义结构体。配置信息包含SMTP服务器地址、端口及授权密码;邮件内容包含发件人、主题、正文及多个收件人地址。

type configInfo struct {
	smtpAddr string
	smtpPort string
	secret   string // 通常为授权码而非登录密码
}

type emailContent struct {
	fromAddr    string
	contentType string // "html" 或 "plain"
	theme       string
	message     string
	toAddr      []string
}

第3步:组装符合RFC 822的消息体

大多数SMTP报错(如网易邮箱的SPM拦截)源于消息头格式不规范。必须严格遵循“头部 + 空行 + 正文”且行尾为CRLF(\r\n)的格式。对于HTML邮件,需在头部声明正确的Content-Type。

func sendEmail(c *configInfo, e *emailContent) error {
	// 1. 拼接服务器地址
	smtpAddr := c.smtpAddr + ":" + c.smtpPort
	
	// 2. 创建认证对象
	auth := smtp.PlainAuth("", e.fromAddr, c.secret, c.smtpAddr)
	
	// 3. 确定内容类型头
	var contentTypeHeader string
	if e.contentType == "html" {
		contentTypeHeader = "Content-Type: text/html; charset=UTF-8"
	} else {
		contentTypeHeader = "Content-Type: text/plain; charset=UTF-8"
	}
	
	// 4. 循环发送给每个收件人
	for _, to := range e.toAddr {
		// 严格按照 RFC 822 格式构建 msg
		msg := "To: " + to + "\r\n" +
			"From: " + e.fromAddr + "\r\n" +
			"Subject: " + e.theme + "\r\n" +
			contentTypeHeader + "\r\n" +
			"\r\n" +
			e.message // 此处可直接填入HTML片段
		
		err := smtp.SendMail(smtpAddr, auth, e.fromAddr, []string{to}, []byte(msg))
		if err != nil {
			return err
		}
	}
	return nil
}

第4步:调用示例与防拦截优化

在实际使用中,需注意以下细节以避免被标记为垃圾邮件:

  • 标题与发件人一致性:确保邮件主题和发件人地址合理,避免使用纯测试占位符。
  • CRLF规范:Go字符串中的\r\n会自动转为CRLF,但切勿混用\n。
  • 多收件人处理:虽然SendMail支持一次性发送多个to参数,但在某些严格的服务器策略下,逐个发送或保持头部清晰更佳。

以下是完整的初始化与调用流程:

func main() {
	config := configInfo{
		smtpAddr: "smtp.yeah.net",
		smtpPort: "25",
		secret:   "your_authorization_code",
	}
	
	content := emailContent{
		fromAddr:    "sender@yeah.net",
		toAddr:      []string{"recipient@qq.com", "other@126.com"},
		contentType: "html",
		theme:       "测试邮件主题",
		message:     "<h1>Hello</h1><p>这是一封通过Go发送的HTML邮件</p>",
	}
	
	if err := sendEmail(&config, &content); err != nil {
		log.Fatal(err)
	}
	fmt.Println("发送成功")
}

常见问题排错

在使用网易系(163/Yeah)邮箱时,常遇到如下错误:

554 DT:SPM ... please see http://mail.163.com/help/help_spam_16.htm

这通常意味着邮件未通过反垃圾系统检查。主要原因包括:

  1. 头部缺失或不规范:缺少标准的From、To或Subject字段,或未正确换行。
  2. 内容被识别为垃圾特征:包含大量链接、敏感词或纯文本形式可疑。
  3. IP信誉问题:本地服务器IP可能被列入黑名单。

解决方法:确保严格按照上述代码结构拼接头部,并在Message-ID等可选头部中添加唯一标识,同时保证From地址与实际发送账户一致。

总结

Go语言通过net/smtp提供了简洁高效的邮件发送能力。关键在于手动构建符合RFC 822标准且带有正确CRLF结尾的消息体,并妥善处理身份验证。对于需要复杂MIME附件的场景,可结合mime/multipart包进行进一步扩展。以上就是Go语言实现SMTP邮件发送的详细内容,更多关于Go网络编程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表