在Golang中实现邮件发送功能不需要引入复杂的第三方库,标准库中的net/smtp包已经提供了基础的SMTP协议支持,能够满足大部分简单邮件发送的需求。如果业务场景需要发送HTML格式邮件、带附件的邮件,也可以基于标准库做扩展实现。

邮件发送的基础准备
在开始编写代码前,需要先准备好邮件发送的相关配置信息,不同邮箱服务商的配置参数略有差异,以下是常见的配置项说明:
- SMTP服务器地址:邮箱服务商提供的SMTP服务地址,比如QQ邮箱是smtp.qq.com,网易邮箱是smtp.163.com
- SMTP端口:常用端口有25、465、587,其中465端口是SSL加密端口,安全性更高,推荐优先使用
- 发件人邮箱:用于发送邮件的邮箱地址
- 邮箱授权码:不是邮箱登录密码,需要在邮箱设置中开启SMTP服务后获取,比如QQ邮箱在账户设置中开启POP3/SMTP服务即可生成授权码
普通文本邮件发送实现
使用net/smtp包发送普通文本邮件的核心步骤是建立SMTP客户端连接、构造邮件内容、调用发送方法。下面是完整的代码示例:
package main
import (
"fmt"
"net/smtp"
)
// 邮件配置结构体
type EmailConfig struct {
SMTPHost string // SMTP服务器地址
SMTPPort string // SMTP端口
Username string // 发件人邮箱
Password string // 邮箱授权码
From string // 发件人显示名称对应的邮箱,一般和Username一致
}
// 发送普通文本邮件
func SendTextEmail(config EmailConfig, to []string, subject, body string) error {
// 构造认证信息
auth := smtp.PlainAuth("", config.Username, config.Password, config.SMTPHost)
// 构造邮件头
header := make(map[string]string)
header["From"] = config.From
header["To"] = to[0]
header["Subject"] = subject
header["Content-Type"] = "text/plain; charset=UTF-8"
// 拼接邮件内容
message := ""
for key, value := range header {
message += fmt.Sprintf("%s: %srn", key, value)
}
message += "rn" + body
// 发送邮件
addr := fmt.Sprintf("%s:%s", config.SMTPHost, config.SMTPPort)
err := smtp.SendMail(addr, auth, config.Username, to, []byte(message))
if err != nil {
return err
}
return nil
}
func main() {
// 初始化邮件配置,这里是QQ邮箱的配置示例,替换为自己的实际配置
config := EmailConfig{
SMTPHost: "smtp.qq.com",
SMTPPort: "465",
Username: "test@ipipp.com",
Password: "邮箱授权码",
From: "test@ipipp.com",
}
// 收件人列表
to := []string{"receiver@ipipp.com"}
// 发送邮件
err := SendTextEmail(config, to, "Golang邮件发送测试", "这是一封通过Golang发送的测试邮件,内容为中文测试。")
if err != nil {
fmt.Printf("邮件发送失败: %vn", err)
return
}
fmt.Println("邮件发送成功")
}
HTML格式邮件发送实现
如果需要发送HTML格式的邮件,只需要调整邮件头中的Content-Type为text/html即可,其余逻辑和普通文本邮件基本一致,代码示例如下:
package main
import (
"fmt"
"net/smtp"
)
type EmailConfig struct {
SMTPHost string
SMTPPort string
Username string
Password string
From string
}
// 发送HTML格式邮件
func SendHTMLEmail(config EmailConfig, to []string, subject, htmlBody string) error {
auth := smtp.PlainAuth("", config.Username, config.Password, config.SMTPHost)
header := make(map[string]string)
header["From"] = config.From
header["To"] = to[0]
header["Subject"] = subject
// 设置Content-Type为text/html
header["Content-Type"] = "text/html; charset=UTF-8"
message := ""
for key, value := range header {
message += fmt.Sprintf("%s: %srn", key, value)
}
message += "rn" + htmlBody
addr := fmt.Sprintf("%s:%s", config.SMTPHost, config.SMTPPort)
err := smtp.SendMail(addr, auth, config.Username, to, []byte(message))
if err != nil {
return err
}
return nil
}
func main() {
config := EmailConfig{
SMTPHost: "smtp.qq.com",
SMTPPort: "465",
Username: "test@ipipp.com",
Password: "邮箱授权码",
From: "test@ipipp.com",
}
to := []string{"receiver@ipipp.com"}
// HTML内容示例
htmlContent := `
<h1>Golang邮件发送测试</h1>
<p style="color: blue;">这是一封HTML格式的测试邮件</p>
<ul>
<li>支持HTML标签渲染</li>
<li>支持样式设置</li>
</ul>
`
err := SendHTMLEmail(config, to, "HTML格式邮件测试", htmlContent)
if err != nil {
fmt.Printf("邮件发送失败: %vn", err)
return
}
fmt.Println("HTML邮件发送成功")
}
常见问题与解决方法
认证失败问题
如果出现535 authentication failed错误,一般是授权码填写错误,或者没有正确开启邮箱的SMTP服务。需要检查授权码是否正确,同时确认SMTP服务已经开启。
端口不通问题
如果连接SMTP服务器失败,首先确认端口是否被防火墙拦截,25端口在很多云服务器上默认是封禁的,推荐使用465或者587端口。如果使用465端口,部分场景下需要开启SSL支持,标准库的smtp包默认不支持SSL,需要结合crypto/tls包做扩展,或者使用第三方库比如gopkg.in/gomail.v2来简化SSL场景的邮件发送。
中文乱码问题
邮件头中如果包含中文,需要做base64编码处理,上面的示例为了简化没有做编码,实际项目中如果主题或者发件人名称有中文,建议使用base64编码处理,避免乱码问题。
实战场景扩展
在实际项目中,可以把邮件发送功能封装成独立的工具包,通过配置文件加载邮件参数,同时可以加入重试机制、发送限流、异步发送等能力,避免邮件发送失败影响主业务流程。如果是批量发送邮件,需要注意控制发送频率,避免被邮箱服务商判定为垃圾邮件。