如何使用 GOLANG 发送邮件

使用 GOLANG 发送邮件

使用GOLANG发送邮件.jpg

我们一起来回顾一下上一次咱们说到的GO 的验证码案例

  • 验证码种类梳理
  • 验证码库的安装
  • 验证码库的源码介绍
  • 实操,编码
  • 验证码效果展示

想看看GO 咋做验证码的,欢迎查看文章 GO 的验证码案例

[图片上传失败...(image-db4892-1624318771417)]

生活和工作中,咱们都离不开邮件的收发,要么在手机上查收和发送,要么在自己的电脑前面进行邮件编辑和处理

可是,我们会发现,很多时候,某类邮件,咱们每天都必须要在同一个时刻发出去,并且内容也是大同小异的,

而且,有时候因为各种各种各样的原因,不能准时的发送邮件,这个时候,咱们如果可以写一个定制化的发送邮件的程序那可以说还是很香的

那么,咱们还是先来看看一些基本的常识吧

[图片上传失败...(image-c0dadc-1624318771417)]

邮件是什么?

邮件是指经传递方式处理的文件

邮件进行传递的过程称为邮递,而从事邮递服务的机构或系统,则称为邮政

邮件有国内邮件和国际邮件两类

那么电子邮件又是个啥?

电子邮件是—种用电子手段提供信息交换的通信方式是互联网应用最广的服务

电子邮件的优势是啥?

电子邮件依托于网络的电子邮件系统,有如下优势:

  • 价格非常低廉

不管发送到哪里,都只需负担网费

  • 传输快速

几秒钟之内可以发送到世界上任何指定的目的地,与世界上任何一个角落的网络用户联系

电子邮件的形式是啥样的?

  • 文字
  • 图像
  • 声音等

想一想每次发邮件都需要经历如下的步骤

  • 打开电脑
  • 进入浏览器
  • 打开电子邮件
  • 新建 - 编辑 - 发送

大部分内容还是复制粘贴的,[图片上传失败...(image-42acb4-1624318771417)]

妥妥的一个工具人,好滴,现在就来看看 使用 GOLang 咋发邮件

邮件协议

咱们使用编程语言需要遵守编程语言的规范,我们在浏览器里面浏览网页也是一样,需要遵循各种网络协议

那么,我们发送邮件的必须也要先知道有哪些邮件协议可以使用,咱们都来列举一下

  • SMTP

SMTP是 简单邮件传输协议,是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式

另外 SMTP 协议属于TCP/IP协议簇

  • POP3

邮局协议的第3个版本,是因特网电子邮件的第一个离线协议标准

  • IMAP

是一种优于POP的新协议

POP一样,IMAP也能下载邮件、从服务器中删除邮件或询问是否有新邮件

IMAP可让用户在服务器上创建并管理邮件文件夹或邮箱、删除邮件、查询某封信的一部分或全部内容

最终完成所有这些工作都不需要把邮件从服务器下载到用户的个人计算机上

OK,让我们开始进入到编码环节

image

开始编码发邮件

咱们今天就使用 SMTP 协议来发送邮件,有如下几个步骤

  • 在 QQ 邮箱上面,拿到授权码
  • 编码,并安装email 邮件库
  • 开始发送邮件

QQ 邮箱上面,拿到授权码

  • 进入 QQ邮箱,点击 设置 -> 账户
image
  • 下滑页面,看到 POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务
image
  • 开启 POP3/SMTP服务
  • 开启 IMAP/SMTP服务
  • 生成授权码,这个授权码自己找地方保存起来
    image

编码,并安装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 ...

说明发送邮件成功了,咱们来看看我们的邮箱

image
image

果然是发送成功了 , 窃喜
image

那么今天的文章分享就到这里了吧 ,这时你会问,我想发表格,想发html内容,还想发附件,甚至我想秘密抄送给某些人

image

好的安排

发送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 的内容了呢 ,咱们改造一下上述的代码

image
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 ... ")
}

运行之后,咱们去查收一下邮件

image

抄送,密送,添加附件,发送 HTML 内容,全部满上

image

如何提高发送邮件的性能

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 ... ")
}

运行上述代码后,咱们查看邮箱

image

咱们可以看到,邮件并不是按照顺序发送出来的,这就对了

要是对于上述的sync 使用有疑问的话, 欢迎查看文章GO通道和 sync 包的分享

image

总结

  • 分享了邮件,电子邮件是什么
  • 邮件协议有哪些
  • 如何使用GOLANG 发送电子邮件
  • 发送电子邮件如何携带纯文本,HTML内容,附件等
  • 发送邮件,如何抄送,如何密送
  • 如何提高发送邮件的性能

之前我们也简单分享了GOLANG如何发送邮件,大家可以对比一下,哪一种更加方便golang如何发送邮件(qq邮箱) |Go主题月

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

image

好了,本次就到这里,下一次 分享一波GO的爬虫

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容