掘金 后端 ( ) • 2024-03-30 10:21

经常我们使用邮件来通知、报表或是信息发送等,本文将简介SMTP协议以及Go如何发送Email 。

SMTP POP3 IMAP

  1. Simple Mail Transfer Protocol(简单邮件传输协定) ,主要负责邮件的传输协议
  2. POP3(Post Office Protocol – Version 3)、IMAP(Internet Message Access Protocol), 负责接收邮件的过程协议

邮件发送流程拓扑图

image.png

1. 使用标准库 net/smtp 发送邮件

在Go语言中,可以使用标准库net/smtp来发送邮件。下面是一个简单的例子:发送QQ邮件 (PS: qq邮箱需要预先开启 POP3/SMTP服务 IMAP/SMTP服务 两个服务,可参考文末【附1】)

package main

import (
    "fmt"
    "log"
    "net/mail"
    "net/smtp"
)

const (
    smtpServer     = "smtp.qq.com"
    smtpPort       = 25
    senderEmail    = "[email protected]"
    senderPassword = "pwd"
)

func main() {
    recipientEmail := "[email protected]"
    subject := "Verification code!"
    body := "Your verification code is 9587"

    err := SendEmail(senderEmail, senderPassword, recipientEmail, subject, body)
    if err != nil {
       log.Fatal(err)
    }

    fmt.Println("Success")
}

func SendEmail(fromEmail, password, toEmail, subject, body string) error {
    from := mail.Address{Name: "Jeff", Address: fromEmail}
    to := mail.Address{Name: "", Address: toEmail}

    message := fmt.Sprintf("From: %s\r\n", from.String())
    message += fmt.Sprintf("To: %s\r\n", to.String())
    message += fmt.Sprintf("Subject: %s\r\n\r\n%s", subject, body)

    auth := smtp.PlainAuth("", fromEmail, password, smtpServer)
    err := smtp.SendMail(fmt.Sprintf("%s:%d", smtpServer, smtpPort), auth, fromEmail, []string{toEmail}, []byte(message))
    if err != nil {
       return err
    }

    return nil
}
 

在邮箱里,将受到一封邮件,内容如下 1711640862434(1).png

上例中,

  1. 配置SMTP服务器信息:qq邮箱的SMTP服务器的地址、端口号,认证信息:用户名和密码
  2. 进行身份验证:通过调用smtp.PlainAuth进行身份验证。
  3. 设置发件人和收件人电子邮件地址
  4. 编写邮件内容,包括: 主题、正文和附件等
  5. 发送邮件:使用SendMail方法发送邮件

基础库的封装相对简单,接着我们介绍一些第三方库,并通过重写上面的例子,来演示如何使用

2. pkg: gomail.v2

Gomail 是一个简单而高效的电子邮件发送包。Gomail 只能使用 SMTP 服务器发送电子邮件。但 API 很灵活,很容易实现使用本地 Postfix、API 等发送电子邮件的其他方法。

重写SendEmail后的例子如下:

package main

import (
    "fmt"
    "gopkg.in/gomail.v2"
)

func SendEmailByGoail(fromEmail, password, toEmail, subject, body string) error {
    m := gomail.NewMessage()
    m.SetHeader("From", m.FormatAddress(fromEmail, "jeff"))
    m.SetHeader("To", toEmail)
    m.SetHeader("Subject", subject)
    m.SetBody("text/plain", body)
    d := gomail.NewDialer(
       smtpServer,
       smtpPort,
       fromEmail,
       password,
    )
    if err := d.DialAndSend(m); err != nil {
       return err
    }
    return nil
}

3. pkg: jordan-wright/email

email软件包设计得易于使用,但又足够灵活,不会受到限制。

feature:

  • 发件人、收件人、密件抄送和抄送字段
  • 电子邮件地址采用“ [email protected] ”和“First Last < [email protected] >”格式
  • 文本和 HTML 消息正文
  • 附件
  • 已读收据
  • 自定义标头

重写SendEmail后的例子如下:

package main

import (
    "fmt"
    "github.com/jordan-wright/email"
    "mime"
    "net/smtp"
    "strconv"
)

func SendEmailByJordanWright(senderEmail, senderPassword, recipientEmail, subject, body string) error {
    e := email.NewEmail()
    e.From = mime.QEncoding.Encode("UTF-8", "Jeff") + fmt.Sprintf("<%s>", senderEmail)
    e.To = []string{recipientEmail}
    e.Subject = subject
    e.HTML = []byte(body)
    auth := smtp.PlainAuth("", senderEmail, senderPassword, smtpServer)
    err := e.Send(smtpServer+":"+strconv.Itoa(smtpPort), auth)
    if err != nil {
       return err
    }
    return nil
}

附1: 开启qq邮箱 POP3/SMTP服务 IMAP/SMTP服务

打开qq邮箱,通过以下操作路径打开

设置-- 账号 -- 打开 POP3/SMTP服务 IMAP/SMTP服务 两个服务开启

1711553790953.png

管理服务--生成授权码

1711554005175.png

image.png

<注意>安全性和限制

  1. 加密通信:使用TLS/SSL协议进行加密通信
  2. HTML转义和处理,以防止安全漏洞和跨站脚本攻击(XSS)
  3. 频率限制:邮件服务有频率限制,注意使用频率

小结

本文简介邮件发送流程,主要由SMTP、POP3/IMAP协议进行邮件的发送、接收。文中分别通过Go原生net/smtp和第三方库gomail.v2、jordan-wright/email 基于smtp协议发送邮件的例子,演示了Go是如何发送邮件的。

参考

  • what-is-smtp-server https://serversmtp.com/what-is-smtp-server/
  • Golang官方文档:net/smtp https://pkg.go.dev/net/smtp
  • jordan-wright/email https://github.com/jordan-wright/email
  • gomail.v2 https://gopkg.in/gomail.v2
  • 使用gomail.v2库调用邮箱的SMTP服务发送邮件 https://juejin.cn/post/7236337121912897573?searchId=2024032723210828312C2F29F7E0BAB4AB
  • Go 每日一库之 email https://juejin.cn/post/6844904065957101582?searchId=20240327231915A8AE5761F745F7B453C8