

Go 每日一库之 email
source link: https://segmentfault.com/a/1190000021761747
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

简介
程序中时常有发送邮件的需求。有异常情况了需要通知管理员和负责人,用户下单后可能需要通知订单信息,电商平台、中国移动和联通都有每月账单,这些都可以通过邮件来推送。还有我们平时收到的垃圾邮件大都也是通过这种方式发送的:sob:。那么如何在 Go 语言发送邮件?本文我们介绍一下 email
库的使用。
快速使用
这个库的使用快不了,为什么呢?
先安装库,这个自不必说:
$ go get github.com/jordan-wright/email
我们需要额外一些工作。我们知道邮箱使用 STMP/POP3/IMAP
等协议从邮件服务器上拉取邮件。邮件并不是直接发送到邮箱的,而是邮箱请求拉取的。
所以,我们需要配置 STMP/POP3/IMAP
服务器。从头搭建固然可行,而且也有现成的开源库,但是比较麻烦。现在一般的邮箱服务商都开放了 STMP/POP3/IMAP
服务器。
我这里拿 126 邮箱来举例,使用 STMP
服务器。当然,用 QQ 邮箱也可以。
POP3/STMP/IMAP IMAP/STMP
然后就可以编码了:
package main import ( "log" "net/smtp" "github.com/jordan-wright/email" ) func main() { e := email.NewEmail() e.From = "dj <[email protected]>" e.To = []string{"[email protected]"} e.Subject = "Awesome web" e.Text = []byte("Text Body is, of course, supported!") err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "[email protected]", "yyy", "smtp.126.com")) if err != nil { log.Fatal(err) } }
这里为了我的信息安全,我把真实信息都隐藏了。代码中 xxx
替换成你的邮箱账号, yyy
替换成上面设置的密码。
代码步骤比较简单清晰:
- 先调用
NewEmail
创建一封邮件; - 设置
From
发送方,To
接收者,Subject
邮件主题(标题),Text
设置邮件内容; - 然后调用
Send
发送,参数1是 STMP 服务器的地址,参数2为验证信息。
运行程序将会向我的 QQ 邮箱发送一封邮件:
有的邮箱会把这种邮件放在垃圾箱中,例如 QQ:sob:。如果收件箱找不到,记得到垃圾箱瞅瞅。
抄送
平常我们发邮件的时候可能会抄送给一些人,还有一些人要 秘密抄送 :smile:,即 CC(Carbon Copy)和 BCC (Blind Carbon Copy)。
email
我们也可以设置这两个参数:
package main import ( "log" "net/smtp" "github.com/jordan-wright/email" ) func main() { e := email.NewEmail() e.From = "dj <[email protected]>" e.To = []string{"[email protected]"} e.Cc = []string{"[email protected]", "[email protected]"} e.Bcc = []string{"[email protected]"} e.Subject = "Awesome web" e.Text = []byte("Text Body is, of course, supported!") err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "[email protected]", "yyy", "smtp.126.com")) if err != nil { log.Fatal(err) } }
还是一样的,抄送的邮箱自己替换 test1/test2/secret
用自己的。
运行程序将会向我的 QQ 邮件发送一封邮件,同时抄送一封到我另一个 126 邮箱:
HTML 格式
发送纯文本,邮件不太美观。 email
支持发送 HTML 格式的内容。与发送纯文本类似,直接设置对象的 HTML
字段:
package main import ( "log" "net/smtp" "github.com/jordan-wright/email" ) func main() { e := email.NewEmail() e.From = "dj <[email protected]>" e.To = []string{"[email protected]"} e.Cc = []string{"[email protected]"} e.Subject = "Go 每日一库" e.HTML = []byte(` <ul> <li><a "https://darjun.github.io/2020/01/10/godailylib/flag/">Go 每日一库之 flag</a></li> <li><a "https://darjun.github.io/2020/01/10/godailylib/go-flags/">Go 每日一库之 go-flags</a></li> <li><a "https://darjun.github.io/2020/01/14/godailylib/go-homedir/">Go 每日一库之 go-homedir</a></li> <li><a "https://darjun.github.io/2020/01/15/godailylib/go-ini/">Go 每日一库之 go-ini</a></li> <li><a "https://darjun.github.io/2020/01/17/godailylib/cobra/">Go 每日一库之 cobra</a></li> <li><a "https://darjun.github.io/2020/01/18/godailylib/viper/">Go 每日一库之 viper</a></li> <li><a "https://darjun.github.io/2020/01/19/godailylib/fsnotify/">Go 每日一库之 fsnotify</a></li> <li><a "https://darjun.github.io/2020/01/20/godailylib/cast/">Go 每日一库之 cast</a></li> </ul> `) err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "[email protected]", "yyy", "smtp.126.com")) if err != nil { log.Fatal("failed to send email:", err) } }
发送结果:
注意,126 的 STMP 服务器检测比较严格,加上 HTML 之后,很容易被识别为垃圾邮件不让发送,这时 CC 自己就 OK 了。
附件
添加附件也很容易,直接调用 AttachFile
即可:
package main import ( "log" "net/smtp" "github.com/jordan-wright/email" ) func main() { e := email.NewEmail() e.From = "dj <[email protected]>" e.To = []string{"[email protected]"} e.Subject = "Go 每日一库" e.Text = []byte("请看附件") e.AttachFile("test.txt") err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "[email protected]", "yyy", "smtp.126.com")) if err != nil { log.Fatal("failed to send email:", err) } }
收到的邮件:
连接池
实际上每次调用 Send
时都会和 STMP 服务器建立一次连接,如果发送邮件很多很频繁的话可能会有性能问题。 email
提供了连接池,可以复用网络连接:
package main import ( "fmt" "log" "net/smtp" "os" "sync" "time" "github.com/jordan-wright/email" ) func main() { ch := make(chan *email.Email, 10) p, err := email.NewPool( "smtp.126.com:25", 4, smtp.PlainAuth("", "[email protected]", "358942617ldj", "smtp.126.com"), ) if err != nil { log.Fatal("failed to create pool:", err) } var wg sync.WaitGroup wg.Add(4) for i := 0; i < 4; i++ { go func() { defer wg.Done() for e := range ch { err := p.Send(e, 10*time.Second) if err != nil { fmt.Fprintf(os.Stderr, "email:%v sent error:%v\n", e, err) } } }() } for i := 0; i < 10; i++ { e := email.NewEmail() e.From = "dj <[email protected]>" e.To = []string{"[email protected]"} e.Subject = "Awesome web" e.Text = []byte(fmt.Sprintf("Awesome Web %d", i+1)) ch <- e } close(ch) wg.Wait() }
上面程序中,我们创建 4 goroutine 共用一个连接池发送邮件,发送 10 封邮件后程序退出。为了等邮件都发送完成或失败,程序才退出,我们使用了 sync.WaitGroup
。
邮箱被轰炸了:
由于使用了 goroutine,邮件顺序不能保证。
总结
本文介绍了如何使用 Go 程序发送邮件,程序代码都已经放在 GitHub 上 https://github.com/darjun/go-daily-lib/tree/master/email 。所有代码都通过测试,大家请放心食用~
大家如果发现好玩、好用的 Go 语言库,欢迎到 Go 每日一库 GitHub 上提交 issue:smile:
参考
- email GitHub: https://github.com/jordan-wright/email
- Go 每日一库 GitHub: https://github.com/darjun/go-daily-lib
我
欢迎关注我的微信公众号【GoUpUp】,共同学习,一起进步~
本文由博客一文多发平台 OpenWrite 发布!
Recommend
-
32
简介 今天我们来看一个很小,很实用的库 go-homedir 。顾名思义, go-homedir 用来获取用户的主目录。 实际上,使用标准库 os/user
-
46
简介 ini 是 Windows 上常用的配置文件格式。MySQL 的 Windows 版就是使用 ini 格式存储配置的。 go-ini 是 Go 语言中用于操作 ini 文件的第三方库。 本文...
-
23
简介 cobra 是一个命令行程序库,可以用来编写命令行程序。同时,它也提供了一个脚手架, 用于生成基于 cobra 的应用程序框架。非常多知名的开源项目使用了 cobra 库...
-
34
简介 上一篇文章介绍 cobra 的时候提到了 viper ,今天我们就来介绍一下这个库。 viper 是一...
-
29
简介 上一篇文章 Go 每日一库之 viper 中,我们介绍了 viper 可以监听文件修改进而自动重新加载。 其内部使用的就是 fsnotify 这...
-
32
简介 今天我们再来介绍 spf13 大神的另一个库 cast 。 cast 是一个小巧、实用的类型转换库,用于将一个类型转为另一个类型。 最初开发 cast
-
39
简介 在日常开发中,日志是必不可少的功能。虽然有时可以用 fmt 库输出一些信息,但是灵活性不够。Go 标准库提供了一个日志库 log 。本文介绍 log 库的使用。 快速使用
-
23
简介 前一篇文章 介绍了 Go 标准库中的日志库 log 。最后我们也提到, log 库只提供了三组接口,功能过于简单了。 ...
-
42
简介 一线开发人员每天都要使用日期和时间相关的功能,各种定时器,活动时间处理等。标准库 time 使用起来不太灵活,特别是日期时间的创建和运算。
-
24
简介 今天我们来介绍 Go 语言的一个依赖注入(DI)库—— dig 。dig 是 uber 开源的库。Java 依赖注入的库有很多,相信即使不是做 Java 开发的童鞋也听过大名鼎鼎的 Spring。相比...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK