golang发送邮件
邮箱服务商地址
项目 | POP | SMTP |
---|---|---|
阿里企业邮箱 | pop3.mxhichina.com(:110/995) | smtp.mxhichina.com(:25/465) |
腾讯企业邮箱 | pop.exmail.qq.com(:110/995) | smtp.exmail.qq.com(:25/465) |
net/smtp模块给出了直接进行邮件发送和简单的带密码验证的邮件的发送。但是不进行TLS安全认证的smtp协议,容易在网络传输中被抓包获取用户名密码,所以目前各大主流QQ邮箱,阿里邮箱,163邮箱 等不再支持明文传输。
踩的坑
//准备邮件报文
email := "To: " + to + "\n" +
"From: " + username + "\n" +
"Subject: " + subject + "\n" +
"Content-Type: text/html; charset=utf-8" + "\n" +
"Content-Transfer-Encoding: base64" + "\n\n" + //坑在此 "\n\n"
base64.StdEncoding.EncodeToString(buf.Bytes())
解释一哈: stmp 是一种邮件发送协议,所有的协议都是有格式的,stmp也不例外。协议格式基本是由协议头,空行,协议体组成。
协议头 |
---|
空行(必须存在! \n\n 就是添加空行,否则邮件服务不能解析邮件体) |
协议体 |
明文传输 25端口 不推荐
//目录结构
//100
// |--src/main/main.go
// |--src/test/mail.go
// |--template/active.html
//mail.go
//author: richard
package test
import (
"bytes"
"encoding/base64"
"fmt"
"html/template"
"log"
"net/smtp"
)
func SendEmail(subject string, to string, smtpHost string, smtpPort string, username string, password string) error {
//认证邮件
auth := smtp.PlainAuth("", username, password, smtpHost)
//解析模版
body, err := template.ParseFiles("template/active.html")
if err != nil {
log.Println(err.Error())
return err
}
//将数据传入模版
data := struct {
Name string
}{
Name: "richard",
}
buf := new(bytes.Buffer)
err = body.Execute(buf, data)
if err != nil {
log.Println(err.Error())
return err
}
//准备邮件报文
email := "To: " + to + "\n" +
"From: " + username + "\n" +
"Subject: " + subject + "\n" +
"Content-Type: text/html; charset=utf-8" + "\n" +
"Content-Transfer-Encoding: base64" + "\n\n" +
base64.StdEncoding.EncodeToString(buf.Bytes())
err = smtp.SendMail(fmt.Sprintf("%s:%s", smtpHost, smtpPort), auth, username, []string{to}, []byte(email))
if err != nil {
log.Println(err.Error())
return err
}
return nil
}
//-- main.go
//author: richard
package main
import (
"fmt"
"test"
)
//xxx 需要填入自己的邮箱及密码
func main() {
err := test.SendEmail("通知邮件", "xxx@xxx.com", "smtp.mxhichina.com", "25", "xxxxx@xxxx.com", "xxxx")
fmt.Println(err.Error())
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#header,#container,#footer {
width: 100%;
height: 100px;
border: 1px solid blue;
}
</style>
</head>
<body>
<div id="header">{{.Name}}</div>
<div id="container"></div>
<div id="footer"></div>
</body>
</html>
密文传输 465端口 推荐
func SendEmail(subject string, to string, smtpHost string, smtpPort string, username string, password string) error {
//认证邮件
auth := smtp.PlainAuth("", username, password, smtpHost)
//解析模版
body, err := template.ParseFiles("template/active.html")
if err != nil {
log.Println(err.Error())
return err
}
//将数据传入模版
data := struct {
Name string
}{
Name: "richard",
}
buf := new(bytes.Buffer)
err = body.Execute(buf, data)
if err != nil {
log.Println(err.Error())
return err
}
//准备邮件报文
email := "To: " + to + "\n" +
"From: " + username + "\n" +
"Subject: " + subject + "\n" +
"Content-Type: text/html; charset=utf-8" + "\n" +
"Content-Transfer-Encoding: base64" + "\n\n" +
base64.StdEncoding.EncodeToString(buf.Bytes())
//加密tls
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%s", smtpHost, smtpPort), nil)
if err != nil {
return err
}
defer conn.Close()
c, err := smtp.NewClient(conn, smtpHost)
if err != nil {
return err
}
//auth
if auth != nil {
if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(auth); err != nil {
return err
}
}
}
// from
if err = c.Mail(username); err != nil {
return err
}
// to
if err = c.Rcpt(to); err != nil {
return err
}
// data
w, err := c.Data()
if err != nil {
return err
}
// write
_, err = w.Write([]byte(email))
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
// quit
return c.Quit()
}
参考文献
[1] https://golang.google.cn/pkg/
[2] https://sendgrid.com/blog/what-is-starttls/
[3] https://www.361way.com/golang-send-email/5853.html