当前位置:首页 > 技术知识 > 正文内容

Go语言库系列之email_go语言发邮件

maynowei8个月前 (09-18)技术知识108

1.1.1. 介绍

电子邮件的应用非常广泛,常见的如在某网站注册了一个账户,自动发送一封激活邮件,通过邮件找回密码,自动批量发送活动信息等。很显然这些应用不可能和我们自己平时发邮件一样,先打开浏览器,登录邮箱,创建邮件再发送。本文将简单介绍如何通过go代码来创建电子邮件,并连接邮件服务器发送邮件。

电子邮件在网络中传输和网页一样需要遵从特定的协议,常用的电子邮件协议包括 SMTP,POP3,IMAP。其中邮件的创建和发送只需要用到 SMTP协议,所以本文也只会涉及到SMTP协议。SMTP 是 Simple Mail Transfer Protocol 的简称,即简单邮件传输协议。

1.1.2. 特征

  • 发件人,收件人,密件抄送和抄送字段
  • 文字和HTML邮件正文
  • 附件
  • 阅读收据
  • 自定义标题

1.1.3. 安装

    go get github.com/jordan-wright/email

注意:此库的版本需要Go v1.5或更高版本。 如果需要与以前的Go版本兼容,则可以在
gopkg.in/jordan-wright/email.v1中使用以前的软件包。

我们需要额外一些工作。我们知道邮箱使用SMTP/POP3/IMAP等协议从邮件服务器上拉取邮件。邮件并不是直接发送到邮箱的,而是邮箱请求拉取的。所以,我们需要配置SMTP/POP3/IMAP服务器。从头搭建固然可行,而且也有现成的开源库,但是比较麻烦。现在一般的邮箱服务商都开放了SMTP/POP3/IMAP服务器。我这里拿 QQ 邮箱来举例。

  • 首先我们登录QQ邮箱,设置->账户 找到图片的位置开启POP3/SMTP/IMAP并且按照要求生产授权码

1.1.4. 代码

1.实现简单的邮件发送:

package main

import (
    "log"
    "net/smtp"

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

func main() {
    e := email.NewEmail()
    //设置发送方的邮箱
    e.From = "dj <XXX@qq.com>"
    // 设置接收方的邮箱
    e.To = []string{"XXX@qq.com"}
    //设置主题
    e.Subject = "这是主题"
    //设置文件发送的内容
    e.Text = []byte("www.topgoer.com是个不错的go语言中文文档")
    //设置服务器相关的配置
    err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "你的邮箱账号", "这块是你的授权码", "smtp.qq.com"))
    if err != nil {
        log.Fatal(err)
    }
}

运行程序就会给你设置的邮箱发送一个邮件,有的邮箱会把邮件当成垃圾邮件发到垃圾箱里面,如果找不到邮件可以去垃圾箱看下。

2.实现抄送功能

该插件有两种抄送模式即 CC(Carbon Copy)和 BCC (Blind Carbon Copy)

抄送功能只需要添加两个参数就好了

    e.Cc = []string{"XXX@qq.com",XXX@qq.com}
    e.Bcc = []string{"XXX@qq.com"}

全部代码:

package main

import (
    "log"
    "net/smtp"

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

func main() {
    e := email.NewEmail()
    //设置发送方的邮箱
    e.From = "dj <XXX@qq.com>"
    // 设置接收方的邮箱
    e.To = []string{"XXX@qq.com"}
    //设置抄送如果抄送多人逗号隔开
    e.Cc = []string{"XXX@qq.com",XXX@qq.com}
    //设置秘密抄送
    e.Bcc = []string{"XXX@qq.com"}
    //设置主题
    e.Subject = "这是主题"
    //设置文件发送的内容
    e.Text = []byte("www.topgoer.com是个不错的go语言中文文档")
    //设置服务器相关的配置
    err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "你的邮箱账号", "这块是你的授权码", "smtp.qq.com"))
    if err != nil {
        log.Fatal(err)
    }
}

3.发送html代码的邮件

代码实现:

package main

import (
    "log"
    "net/smtp"

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

func main() {
    e := email.NewEmail()
    //设置发送方的邮箱
    e.From = "dj <XXX@qq.com>"
    // 设置接收方的邮箱
    e.To = []string{"XXX@qq.com"}
    //设置主题
    e.Subject = "这是主题"
    //设置文件发送的内容
    e.HTML = []byte(`
    <h1><a href="http://www.topgoer.com/">go语言中文网站</a></h1>    
    `)
    //设置服务器相关的配置
    err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "你的邮箱账号", "这块是你的授权码", "smtp.qq.com"))
    if err != nil {
        log.Fatal(err)
    }
}

4.实现邮件附件的发送

直接调用AttachFile即可

package main

import (
    "log"
    "net/smtp"

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

func main() {
    e := email.NewEmail()
    //设置发送方的邮箱
    e.From = "dj <XXX@qq.com>"
    // 设置接收方的邮箱
    e.To = []string{"XXX@qq.com"}
    //设置主题
    e.Subject = "这是主题"
    //设置文件发送的内容
    e.HTML = []byte(`
    <h1><a href="http://www.topgoer.com/">go语言中文网站</a></h1>    
    `)
    //这块是设置附件
    e.AttachFile("./test.txt")
    //设置服务器相关的配置
    err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "你的邮箱账号", "这块是你的授权码", "smtp.qq.com"))
    if err != nil {
        log.Fatal(err)
    }
}

5.连接池

实际上每次调用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.qq.com:25",
        4,
        smtp.PlainAuth("", "XXX@qq.com", "你的授权码", "smtp.qq.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 <XXX@qq.com>"
        e.To = []string{"XXX@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,邮件顺序不能保证。

参考:
https://github.com/darjun/go-daily-lib

相关文章

从零搭建网站?5个步骤详解网站建设全流程

在数字化时代,拥有一个专业网站已成为企业或个人品牌展示的核心竞争力。但对于新手而言,网站建设往往显得复杂难懂。本文梳理出5大关键步骤,手把手带你完成从策划到上线的全流程,省时省力不踩坑!一、前期准备:...

真来了,iOS 16.6 beta 利用,隐藏 Dock 栏

昨天提到!iOS 16.5 kfd 漏洞可以隐藏 Dock 栏消息,现在已经确定 iOS 16.6 beta 内测也是支持使用 kfd 漏洞,当然!也是支持隐藏 Dock 栏,主要验证该系统是否可用。...

分析 Rust 程序的火焰图(rust火吗)

分析 Rust 程序的火焰图(Flame Graph)是定位性能瓶颈的核心手段,其核心是通过可视化的函数调用栈和时间分布,找到 CPU 耗时、内存分配、锁竞争等热点。以下是详细的分析方法和步骤,结合...

如何正确理解Java领域中的并发锁,我们应该具体掌握到什么程度?

苍穹之边,浩瀚之挚,眰恦之美; 悟心悟性,善始善终,惟善惟道! —— 朝槿《朝槿兮年说》写在开头对于Java领域中的锁,其实从接触Java至今,我相信每一位Java Developer都会有这样的一个...

Oracle中泄露“天机”的TNS(在oracle中发出的下列查询)

数据库的安全是长期存在的问题。在目前大量的数据泄露事件以及漏洞面前,大家看到的大都是SQl注入、越权操作、缓冲区溢出等这些具体漏洞。往往却忽视了造成这些问题的前提,黑客想要入侵数据库一定会尝试获取数据...

python-oracledb——利用python连接Oracle数据库的好用方法

这篇文章最早发布在CSDN了,最近想尝试使用一下头条,重新转移过来了。背景介绍之前使用的数据库一直是MySql,偶尔使用PostgreSQL,都是利用的数据库连接池使用;最近需要在Oracle数据库取...