1.入门案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package main
import (
"crypto/tls"
"fmt"
"gopkg.in/gomail.v2"
"time"
)
func main() {
m := gomail.NewMessage()
m.SetHeader("From", "sender@example.com")
m.SetHeader("To", "recipient1@example.com", "recipient2@example.com")
m.SetHeader("Cc", "cc1@example.com", "cc2@example.com")
m.SetHeader("Subject", "Hello!")
m.SetBody("text/html", fmt.Sprintf("This is a test email, from go language program, current time is %s", time.Now().Format("2006-01-02 15:04:05")))
m.Attach("./gomail/test.png") // 添加附件
// 设置邮件服务器信息(以163邮箱为例)
d := gomail.NewDialer("smtp.163.com", 465, "sender@example.com", "XXXXXXXXXXXXXXXX") // 这个需要要对应的邮件去申请SMTP授权密码
// 跳过TLS证书验证,设置InsecureSkipVerify为true(生产环境不建议这样使用)
// d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil {
panic(err)
}
fmt.Println("Mail sent successfully!")
}
|
注意,163 邮箱的 SMTP 服务器地址是 smtp.163.com
,端口为 465
,并且可以选择是否启用TLS证书验证(设置 TLSConfig)。
这个需要根据邮箱的类型进行更改。
2.读取配置文件
通过ini文件,配置发送方邮箱,密码、smtp服务器、smtp端口,接收方、抄送方邮箱等信息。
ini文件示例:
1
2
3
4
5
6
7
8
9
10
11
|
; 发送邮件的配置信息
[sender]
email = sender@example.com
password = XXXXXXXXXXXXXXXX
smtp_server = smtp.163.com
smtp_port = 465
[recipient]
to_list = recipient1@example.com,recipient2@example.com
cc_list = cc2@example.com,cc2@example.com
|
接收方和抄送方可以有多个,用逗号分隔即可。
这里使用ini
库读取ini配置文件
。
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package main
import (
"crypto/tls"
"fmt"
"gopkg.in/gomail.v2"
"gopkg.in/ini.v1"
"log"
"strings"
"time"
)
func main() {
// 初始化邮件发送配置
cfg, err := ini.Load("./gomail/email_config.ini")
if err != nil {
log.Fatalf("Failed to load email config: %v", err)
}
// 读取发送邮箱信息
senderEmail := cfg.Section("sender").Key("email").String()
password := cfg.Section("sender").Key("password").String()
smtpServer := cfg.Section("sender").Key("smtp_server").String()
smtpPort := cfg.Section("sender").Key("smtp_port").MustInt(587)
// 连接到 SMTP 服务器
d := gomail.NewDialer(smtpServer, smtpPort, senderEmail, password)
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
// 读取接收方和抄送方邮箱信息
toListStr := cfg.Section("recipient").Key("to_list").String()
toLists := strings.Split(toListStr, ",")
ccListStr := cfg.Section("recipient").Key("cc_list").String()
if len(ccLists[0]) > 0 {
m.SetHeader("Cc", ccLists...)
}
// 设置发送方、接收方、抄送方邮箱
m := gomail.NewMessage()
m.SetHeader("From", senderEmail)
m.SetHeader("To", toLists...)
m.SetHeader("Cc", ccLists...)
// 设置邮件内容
m.SetHeader("Subject", "Hello!")
m.SetBody("text/html", fmt.Sprintf("This is a test email, from go language program, current time is %s", time.Now().Format("2006-01-02 15:04:05")))
m.Attach("./gomail/test.png")
// 发送邮件
if err := d.DialAndSend(m); err != nil {
log.Fatalf("Failed to send email, err: %v", err)
}
log.Println("Email sent successfully!")
}
|
这段代码演示了如何使用 Go 语言的 gomail
包发送邮件,其中邮件配置信息从一个 INI 文件中加载。
以下是代码的解释:
-
导入必要的包:代码中使用了多个包,包括 crypto/tls
、gopkg.in/gomail.v2
、gopkg.in/ini.v1
等,用于处理加密通信、发送邮件以及读取配置文件。
-
从 INI 配置文件加载邮件发送配置:代码中使用 ini.Load
函数加载配置文件 ./gomail/email_config.ini
,该配置文件包含了发送邮件所需的信息,如发送方邮箱、SMTP 服务器信息、接收方邮箱等。
-
读取配置信息:通过使用 ini
包读取 INI 文件的各个部分,获取发送邮箱、SMTP 服务器、接收方邮箱等的信息。
-
连接到 SMTP 服务器:使用 gomail.NewDialer
创建一个用于与 SMTP 服务器通信的 Dialer
对象,并设置 SMTP 服务器地址、端口、发送邮箱地址以及密码。此处还设置了 InsecureSkipVerify
为 true
,以允许跳过 TLS 证书验证。这是一个不安全的设置,通常用于测试或开发环境。
-
读取接收方和抄送方邮箱信息:通过读取配置文件中的接收方邮箱列表和抄送方邮箱列表,并使用逗号分隔字符串,将它们转换为字符串切片。
-
创建邮件消息:使用 gomail.NewMessage
创建一个邮件消息对象,并设置发送方、接收方、抄送方、主题、正文内容以及可能的附件等信息。
-
发送邮件:使用 d.DialAndSend(m)
方法将邮件消息 m
发送给 SMTP 服务器。如果发送过程中出现错误,将通过 log.Fatalf
记录错误信息。
-
最后,如果邮件成功发送,代码将输出一条成功的消息。
3.邮件发送验证码
2023.11.05
1.初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
func initInfo() (dialer *gomail.Dialer, senderEmail string, toLists []string, ccLists []string) {
// 初始化邮件发送配置
cfg, err := ini.Load("./send_email/email_config.ini")
if err != nil {
log.Fatalf("Failed to load email config: %v", err)
}
// 读取发送邮箱信息
senderEmail = cfg.Section("sender").Key("email").String()
password := cfg.Section("sender").Key("password").String()
smtpServer := cfg.Section("sender").Key("smtp_server").String()
smtpPort := cfg.Section("sender").Key("smtp_port").MustInt(587)
// 连接到 SMTP 服务器
dialer = gomail.NewDialer(smtpServer, smtpPort, senderEmail, password)
// 读取接收方和抄送方邮箱信息
toListStr := cfg.Section("recipient").Key("to_list").String()
toLists = strings.Split(toListStr, ",")
ccListStr := cfg.Section("recipient").Key("cc_list").String()
ccLists = strings.Split(ccListStr, ",")
return dialer, senderEmail, toLists, ccLists
}
|
读取配置文件中的信息,初始化dialer,并返回。同时将配置文件中的senderEmail,toLists,ccLists信息一并返回,供后面的步骤使用。
2.html模板文件
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<!doctype html>
<html>
<head>
<meta charset='UTF-8'>
<style>
.content {text-indent:20px;}
</style>
</head>
<body style="font-size: 18px;">
<p><strong>尊敬的 Ecodego 用户,您好:</strong></p>
<div class="content">
<p>您的帐号 <strong>xxxxx</strong> 正在进行注册操作,请确认为本人操作。以下是您的验证码,请在10分钟内完成验证:</p>
<p style="font-size: 22px;"><strong>{{.VerificationCode}}</strong></p>
<p>(如非本人操作,请忽略此邮件)</p>
</div>
<p>感谢您的使用!</p>
<p><a href='https://www.ecodego.com/'>Ecodego</a></p>
<p>{{.CurrentTime}}</p>
<hr />
<p style="font-size: 15px;">此为系统邮件,请勿回复。</p>
</body>
</html>
|
上面的的模板中,设置了两个模板参数{{.VerificationCode}}
、{{.CurrentTime}}
,它们是动态变化的,需要后端传入。
用户名 xxxxx 也应该是动态变化的,这里为了方便,做了简化处理。
3.对模板进行渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
func renderHtmlContent(verificationCode string) string {
// 读取 HTML 模板文件
templateBytes, err := os.ReadFile("./send_email/注册模板.html")
if err != nil {
panic(err)
}
// 创建 HTML 模板
tmpl, err := template.New("emailTemplate").Parse(string(templateBytes))
if err != nil {
panic(err)
}
// 创建缓冲区来存储模板渲染后的内容
var renderedEmailContent string
buffer := &bytes.Buffer{}
// 将验证码插入到模板
data := struct {
VerificationCode string
CurrentTime string
}{
VerificationCode: verificationCode,
CurrentTime: time.Now().Format("2006-01-02 15:04:05"),
}
// 渲染模板
err = tmpl.Execute(buffer, data)
if err != nil {
panic(err)
}
// 获取渲染后的 HTML 内容
renderedEmailContent = buffer.String()
return renderedEmailContent
}
|
4.随机数验证码
1
2
3
4
5
6
7
|
func generateRandomCode() string {
r := rand.New(rand.NewSource(time.Now().UnixNano())) // 指定随机种子
minVal := 100000 // 最小的六位数
maxVal := 999999 // 最大的六位数
code := minVal + r.Intn(maxVal-minVal+1)
return fmt.Sprintf("%06d", code) // 将随机数格式化为六位数的字符串
}
|
生成随机数验证码,将返回结果传入模板渲染函数renderHtmlContent()
中。
5.添加邮件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func addEmailContent(senderEmail string, toLists []string, ccLists []string, emailContent string) *gomail.Message {
// 添加邮件内容
mail := gomail.NewMessage()
mail.SetHeader("From", senderEmail)
mail.SetHeader("To", toLists...)
if len(ccLists[0]) > 0 {
mail.SetHeader("Cc", ccLists...)
}
mail.SetHeader("Subject", "【Ecodego】邮箱验证码")
mail.SetBody("text/html", emailContent)
return mail
}
|
使用gomail包新生成一个邮件信息对象mail
,设置mail
的Header
(From
、To
、Cc
、Subject
等)、Body
信息(将前面renderHtmlContent()
函数得到的渲染之后的html文件内容传入到mail
的Body
中),然后返回mail
对象。
这里使用len(ccLists[0]) > 0
来判断ccLists
是否为空而不是len(ccLists)>0
,原因:
前面读取ini配置文件时:
1
2
|
ccListStr := cfg.Section("recipient").Key("cc_list").String()
ccLists = strings.Split(ccListStr, ",")
|
如果recipient.cc_list
标签没写,或者改标签值为空时,得到的ccLists
为包含一个空字符的切片,其长度len=1
,如果recipient.cc_list
标签设置了一个对象(即无逗号分隔),则ccLists
的长度也为1,所以我们不能通过判断len(ccLists)==1
来判断recipient.cc_list
标签是否为空。
故我们需要取出ccLists
的第0个元素,判断其长度是否为0(等于0则说明recipient.cc_list
标签为空,否则不为空)
6.main函数
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func main() {
dialer, senderEmail, toLists, ccLists := initInfo() // 初始化dialer,并从配置文件中获取senderEmail,toLists,ccLists
verificationCode := generateRandomCode() // 生成随机验证码
emailContent := renderHtmlContent(verificationCode) // 渲染html内容
mail := addEmailContent(senderEmail, toLists, ccLists, emailContent) // 添加邮件内容
if err := dialer.DialAndSend(mail); err != nil { // 发送邮件
log.Fatalf("Failed to send email, err: %v", err)
}
log.Println("Email sent successfully!")
}
|
在main
函数中调用前面的几个函数(包括初始化dialer
、读取配置文件、生成随机验证码、渲染html
内容,添加邮件内容),并通过dialer
发送邮件内容mail
。