Go 每日一库之 email

简介

程序中时常有发送邮件的需求。有异常状况了须要通知管理员和负责人,用户下单后可能须要通知订单信息,电商平台、中国移动和联通都有每个月帐单,这些均可以经过邮件来推送。还有咱们平时收到的垃圾邮件大都也是经过这种方式发送的😭。那么如何在 Go 语言发送邮件?本文咱们介绍一下email库的使用。git

快速使用

这个库的使用快不了,为何呢?github

先安装库,这个自没必要说:golang

$ go get github.com/jordan-wright/email
复制代码

咱们须要额外一些工做。咱们知道邮箱使用SMTP/POP3/IMAP等协议从邮件服务器上拉取邮件。邮件并非直接发送到邮箱的,而是邮箱请求拉取的。 因此,咱们须要配置SMTP/POP3/IMAP服务器。从头搭建当然可行,并且也有现成的开源库,可是比较麻烦。如今通常的邮箱服务商都开放了SMTP/POP3/IMAP服务器。 我这里拿 126 邮箱来举例,使用SMTP服务器。固然,用 QQ 邮箱也能够。web

  • 首先,登陆邮箱;
  • 点开顶部的设置,选择POP3/SMTP/IMAP
  • 点击开启IMAP/SMTP服务,按照步骤开启便可,有个密码设置,记住这个密码,后面有用。

而后就能够编码了:安全

package main

import (
  "log"
  "net/smtp"

  "github.com/jordan-wright/email"
)

func main() {
  e := email.NewEmail()
  e.From = "dj <xxx@126.com>"
  e.To = []string{"935653229@qq.com"}
  e.Subject = "Awesome web"
  e.Text = []byte("Text Body is, of course, supported!")
  err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "xxx@126.com", "yyy", "smtp.126.com"))
  if err != nil {
    log.Fatal(err)
  }
}
复制代码

这里为了个人信息安全,我把真实信息都隐藏了。代码中xxx替换成你的邮箱帐号,yyy替换成上面设置的密码。服务器

代码步骤比较简单清晰:微信

  • 先调用NewEmail建立一封邮件;
  • 设置From发送方,To接收者,Subject邮件主题(标题),Text设置邮件内容;
  • 而后调用Send发送,参数1是 SMTP 服务器的地址,参数2为验证信息。

运行程序将会向个人 QQ 邮箱发送一封邮件:网络

有的邮箱会把这种邮件放在垃圾箱中,例如 QQ😭。若是收件箱找不到,记获得垃圾箱瞅瞅。性能

抄送

日常咱们发邮件的时候可能会抄送给一些人,还有一些人要秘密抄送😄,即 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 <xxx@126.com>"
  e.To = []string{"935653229@qq.com"}
  e.Cc = []string{"test1@126.com", "test2@126.com"}
  e.Bcc = []string{"secret@126.com"}
  e.Subject = "Awesome web"
  e.Text = []byte("Text Body is, of course, supported!")
  err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "xxx@126.com", "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 <xxx@126.com>"
  e.To = []string{"935653229@qq.com"}
  e.Cc = []string{"xxx@126.com"}
  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("", "xxx@126.com", "yyy", "smtp.126.com"))
  if err != nil {
    log.Fatal("failed to send email:", err)
  }
}
复制代码

发送结果:

注意,126 的 SMTP 服务器检测比较严格,加上 HTML 以后,很容易被识别为垃圾邮件不让发送,这时 CC 本身就 OK 了。

附件

添加附件也很容易,直接调用AttachFile便可:

package main

import (
  "log"
  "net/smtp"

  "github.com/jordan-wright/email"
)

func main() {
  e := email.NewEmail()
  e.From = "dj <xxx@126.com>"
  e.To = []string{"935653229@qq.com"}
  e.Subject = "Go 每日一库"
  e.Text = []byte("请看附件")
  e.AttachFile("test.txt")
  err := e.Send("smtp.126.com:25", smtp.PlainAuth("", "xxx@126.com", "yyy", "smtp.126.com"))
  if err != nil {
    log.Fatal("failed to send email:", err)
  }
}
复制代码

收到的邮件:

链接池

实际上每次调用Send时都会和 SMTP 服务器创建一次链接,若是发送邮件不少很频繁的话可能会有性能问题。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("", "leedarjun@126.com", "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 <leedarjun@126.com>"
    e.To = []string{"935653229@qq.com"}
    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 上github.com/darjun/go-d…。全部代码都经过测试,你们请放心食用~

你们若是发现好玩、好用的 Go 语言库,欢迎到 Go 每日一库 GitHub 上提交 issue😄

参考

  1. email GitHub:github.com/jordan-wrig…
  2. Go 每日一库 GitHub:github.com/darjun/go-d…

个人博客

欢迎关注个人微信公众号【GoUpUp】,共同窗习,一块儿进步~

本文由博客一文多发平台 OpenWrite 发布!

相关文章
相关标签/搜索