[TOC]
应用 GOLANG 发送邮件
咱们一起来回顾一下上一次咱们说到的GO 的验证码案例
- 验证码品种梳理
- 验证码库的装置
- 验证码库的源码介绍
- 实操,编码
- 验证码成果展现
想看看 GO 咋做验证码的,欢送查看文章 GO 的验证码案例
生存和工作中,咱们 都离不开邮件的收发,要么在手机上查收和发送,要么在本人的电脑前面进行邮件编辑和解决
可是,咱们会发现,很多时候,某类邮件,咱们 每天都必须要在同一个时刻收回去,并且内容也是大同小异的,
而且,有时候因为各种各种各样的起因,不能准时的发送邮件,这个时候,咱们如果能够 写一个定制化的发送邮件的程序 那能够说还是很香的
那么,咱们还是先来看看一些根本的常识吧
邮件是什么?
邮件是指经传递形式解决的文件
邮件进行传递的过程称为
邮递
,而从事邮递服务的机构或零碎,则称为邮政邮件有
国内邮件
和国内邮件两类
那么电子邮件又是个啥?
电子邮件是—种用电子伎俩提供 信息替换
的通信形式是互联网利用最广的服务
电子邮件的劣势是啥?
电子邮件依靠于网络的电子邮件系统,有如下劣势:
- 价格十分低廉
不论发送到哪里,都只需累赘网费
- 传输疾速
几秒钟之内能够发送到世界上任何指定的目的地,与世界上任何一个角落的网络用户分割
电子邮件的模式是啥样的?
- 文字
- 图像
- 声音等
想一想每次发邮件都须要经验如下的步骤
- 关上电脑
- 进入浏览器
- 关上电子邮件
- 新建 – 编辑 – 发送
大部分内容还是复制粘贴的,
妥妥的一个工具人,好滴,当初就来看看 应用 GOLang
咋发邮件
邮件协定
咱们应用编程语言须要恪守编程语言的标准,咱们在浏览器外面浏览网页也是一样,须要遵循各种网络协议
那么,咱们发送邮件的必须也要先晓得有哪些邮件协定能够应用,咱们都来列举一下
- SMTP
SMTP
是 简略邮件传输协定,是一组用于从源地址到目标地址传输邮件的标准,通过它来管制邮件的直达形式
另外 SMTP
协定属于 TCP/IP
协定簇
- POP3
邮局协定的第 3 个版本,是因特网电子邮件的第一个离线协定规范
- IMAP
是一种优于 POP
的新协定
和 POP
一样,IMAP
也能下载邮件、从服务器中删除邮件或询问是否有新邮件
IMAP
可让用户在服务器上创立并治理邮件文件夹或邮箱、删除邮件、查问某封信的一部分或全部内容
最终实现所有这些工作都不须要把邮件从服务器下载到用户的集体计算机上
OK,让咱们开始进入到编码环节
开始编码发邮件
咱们明天就应用 SMTP
协定来发送邮件,有如下几个步骤
- 在 QQ 邮箱下面,拿到受权码
- 编码,并装置
email
邮件库 - 开始发送邮件
在 QQ
邮箱下面,拿到受权码
- 进入
QQ
邮箱,点击 设置 -> 账户
- 下滑页面,看到 POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务
- 开启
POP3/SMTP
服务 - 开启
IMAP/SMTP
服务 - 生成受权码,这个受权码本人找中央保存起来
编码,并装置email
邮件库
咱们本次写的邮件小案例,用到的 GO 的包是 "github.com/jordan-wright/email"
,咱们能够这样来手动装置
go get github.com/jordan-wright/email
不进行手动装置也没有问题,咱们能够当初看看 写一个初版的发送邮件小案例
package main
import (
"github.com/jordan-wright/email"
"log"
"net/smtp"
)
func main() {
// 简略设置 log 参数
log.SetFlags(log.Lshortfile | log.LstdFlags)
em := email.NewEmail()
// 设置 sender 发送方 的邮箱,此处能够填写本人的邮箱
em.From = "xx <xxx@qq.com>"
// 设置 receiver 接管方 的邮箱 此处也能够填写本人的邮箱,就是本人发邮件给本人
em.To = []string{"xxx@qq.com"}
// 设置主题
em.Subject = "小魔童给你发邮件了"
// 简略设置文件发送的内容,临时设置成纯文本
em.Text = []byte("hello world,咱们用 golang 发个邮件!!")
// 设置服务器相干的配置
err := e.Send("smtp.qq.com:25", smtp.PlainAuth(""," 本人的邮箱账号 "," 本人邮箱的受权码 ","smtp.qq.com"))
if err != nil {log.Fatal(err)
}
log.Println("send successfully ...")
}
运行上述代码的成果如下:
2021/06/xx xx:36:28 main.go:28: send successfully ...
阐明发送邮件胜利了,咱们来看看咱们的邮箱
果然是发送胜利了,窃喜
那么明天的文章分享就到这里了吧,这时你会问,我想发表格,想发 html
内容,还想发附件,甚至我想机密抄送给某些人
好的安顿
发送 HTML
内容 + 附件
咱们能够先来看看 这个库反对的哪些字段,上述NewEmail
办法时候返回一个指针
// NewEmail creates an Email, and returns the pointer to it.
func NewEmail() *Email {return &Email{Headers: textproto.MIMEHeader{}}
}
这个指针是指向了一个邮件的数据结构,咱们一起来瞅瞅
// Email is the type used for email messages
type Email struct {ReplyTo []string
From string // 发送者
To []string // 接收者
Bcc []string // 密送
Cc []string // 抄送
Subject string // 主题
Text []byte // Plaintext message (optional)
HTML []byte // Html message (optional)
Sender string // override From as SMTP envelope sender (optional)
Headers textproto.MIMEHeader // 协定头
Attachments []*Attachment // 附件
ReadReceipt []string}
看了上述构造,咱们是不是发送邮件的时候,就能够抄送,密送,增加附件,或者发 HTML
的内容了呢,咱们革新一下上述的代码
func main() {
// 简略设置 l og 参数
log.SetFlags(log.Lshortfile | log.LstdFlags)
em := email.NewEmail()
// 设置发送方的邮箱
em.From = "xx <xxx@qq.com>"
// 设置接管方的邮箱
em.To = []string{"xxx@qq.com"}
// 抄送
em.Cc = []string{"xxx@qq.com"}
// 密送
em.Bcc = []string{"xxx@qq.com"}
// 设置主题
em.Subject = "小魔童给你发邮件了"
// 设置文件发送的内容
em.HTML = []byte(`
<h3><a href="https://juejin.cn/user/3465271329953806"> 欢送来到小魔童哪吒的主页 </a></h3>
<br/>
<table border="0" style="font-family:' 微软雅黑 Light';" cellpadding="3px">
<tr>
<td> 1 </td>
<td><a href="https://juejin.cn/post/6975686540601245709">GO 中 defer 的实现原理 </a></td>
</tr>
<tr>
<td> 2 </td>
<td><a href="https://juejin.cn/post/6975280009082568740">GO 中 Chan 实现原理分享 </a></td>
</tr>
<tr>
<td> 3 </td>
<td><a href="https://juejin.cn/post/6974908615232585764">GO 中 map 的实现原理 </a></td>
</tr>
<tr>
<td> 4 </td>
<td><a href="https://juejin.cn/post/6974539862800072718">GO 中 slice 的实现原理 </a></td>
</tr>
<tr>
<td> 5 </td>
<td> <a href="https://juejin.cn/post/6974169270624190495">GO 中 string 的实现原理 </a></td>
</tr>
<tr>
<td> 6 </td>
<td><a href="https://juejin.cn/post/6973793593987170317">GO 中 ETCD 的编码案例分享 </a></td>
</tr>
<tr>
<td> 7 </td>
<td><a href="https://juejin.cn/post/6973455825905909797"> 服务注册与发现之 ETCD</a></td>
</tr>
<tr>
<td> 8 </td>
<td> <a href="https://juejin.cn/post/6973108979777929230">GO 通道和 sync 包的分享 </a></td>
</tr>
<tr>
<td> 9 </td>
<td> <a href="https://juejin.cn/post/6972846349968474142">GO 的锁和原子操作分享 </a></td>
</tr>
</table>
`)
// 增加附件
em.AttachFile("./test.html")
// 设置服务器相干的配置
err := e.Send("smtp.qq.com:25", smtp.PlainAuth(""," 本人的邮箱账号 "," 本人邮箱的受权码 ","smtp.qq.com"))
if err != nil {log.Fatal(err)
}
log.Println("send successfully ...")
}
运行之后,咱们去查收一下邮件
抄送,密送,增加附件,发送 HTML
内容,全副满上
如何进步发送邮件的性能
get github.com/jordan-wright/email
包外面为咱们提供了连接池,你就说香不香,咱们能够复用上一次的网络连接来发送邮件,而不是每发送一次邮件,就建设一次连贯
咱们都晓得,建设连贯是会消耗工夫和资源的,咱们得尽可能的优化
再来一个 DEMO,连接池的,咱们使用连接池,创立 一个 有 5 个缓冲的通道,让 3 个协程去通道外面获取数据,而后发送邮件
func main() {
// 简略设置 l og 参数
log.SetFlags(log.Lshortfile | log.LstdFlags)
// 创立有 5 个缓冲的通道,数据类型是 *email.Email
ch := make(chan *email.Email, 5)
// 连接池
p, err := email.NewPool(
"smtp.qq.com:25",
3, // 数量设置成 3 个
smtp.PlainAuth(""," 本人的邮箱 "," 本人邮箱的受权码 ","smtp.qq.com"),
)
if err != nil {log.Fatal("email.NewPool error :", err)
}
// sync 包,管制同步
var wg sync.WaitGroup
wg.Add(3)
for i := 0; i < 3; i++ {go func() {defer wg.Done()
// 若 ch 无数据,则阻塞,若 ch 敞开,则退出循环
for e := range ch {
// 超时工夫 10 秒
err := p.Send(e, 10*time.Second)
if err != nil {log.Printf( "p.Send error : %v , e = %v , i = %d\n", err , e, i)
}
}
}()}
for i := 0; i < 5; i++ {e := email.NewEmail()
// 设置发送邮件的根本信息
e.From = "xx <xxx@qq.com>"
e.To = []string{"xxx@qq.com"}
e.Subject = "test email.NewPool" + fmt.Sprintf("the %d email",i)
e.Text = []byte(fmt.Sprintf("test email.NewPool , the %d email !", i))
ch <- e
}
// 敞开通道
close(ch)
// 期待子协程退出
wg.Wait()
log.Println("send successfully ...")
}
运行上述代码后,咱们查看邮箱
咱们能够看到,邮件并不是依照程序发送进去的,这就对了
要是对于上述的sync
应用有疑难的话,欢送查看文章 GO 通道和 sync 包的分享
总结
- 分享了邮件,电子邮件是什么
- 邮件协定有哪些
- 如何应用 GOLANG 发送电子邮件
- 发送电子邮件如何携带纯文本,
HTML
内容,附件等 - 发送邮件,如何抄送,如何密送
- 如何进步发送邮件的性能
之前咱们也简略分享了 GOLANG 如何发送邮件,大家能够比照一下,哪一种更加不便 golang 如何发送邮件(qq 邮箱)|Go 主题月
欢送点赞,关注,珍藏
敌人们,你的反对和激励,是我保持分享,提高质量的能源
好了,本次就到这里,下一次 分享一波 GO 的爬虫
技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。
我是 小魔童哪吒,欢送点赞关注珍藏,下次见~