使用gomail发送邮件之解决附件名乱码的问题

在使用Go语言开发时,我们会遇到发送邮件的需求,在Go语言标准包中,也提供了邮件发送客户端smtp的封装。不过,该标准包只提供了基础的邮件发送过程,对于一些复杂的定义还需要自己去封装,封装过程就需要依据邮件协议RFC2822了。还好,github上有人专门为我们封装好了这个包:https://github.com/go-gomail/gomail。这个包封装了发送附件、图片、HTML内容模板、SSL和TLS等的支持,可以满足我们的大部分应用场景。下面,我就对gomail实现发送邮件做一下简单介绍。

1. 需要先安装gomail

$ go get -v gopkg.in/gomail.v2

2. 导入gomail

$ import "gopkg.in/gomail.v2"

3. 需要创建一个Message实例,Message提供了整个邮件协议内容的构建,默认实例采用UTF-8字符集和Quoted-printable编码。

对于Quoted-printable编码的定义,维基百科上是这样说的:Quoted-printable是使用可打印的ASCII字符(如字母、数字与“=”)表示各种编码格式下的字符,以便能在7-bit数据通路上传输8-bit数据, 或者更一般地说在非8-bit clean媒体上正确处理数。

m := gomail.NewMessage()

4. 构造邮件内容,包括:发件人信息、收件人、主题、内容,更多内容设定可参考协议:RFC2822

// 发件人信息
m.SetHeader("From", m.FormatAddress("user@example.com", "张三"))
// 收件人
m.SetHeader("To", "user@qq.com")
// 主题
m.SetHeader("Subject", "邮件标题")
// 内容
m.SetBody("text/html", "系统邮件请勿回复")

特殊说明,构造From(发件人信息)时需要使用m.FormatAddress方法,因为发件人指定中文名或特殊字符时,需要进行编码

5. 构造附件信息,同时对附件进行重命名

比如,我有一个临时文件:/tmp/foo.txt,我需要将这个文件以邮件附件的方式进行发送,同时指定附件名为:附件.txt

name := "附件.txt"
m.Attach("/tmp/foo.txt",
    gomail.Rename(name),
)

6. 创建SMTP客户端,连接到远程的邮件服务器,需要指定服务器地址、端口号、用户名、密码,如果端口号为465的话,自动开启SSL,这个时候需要指定TLSConfig

这里的用户名和密码指的是能够登录该邮箱的邮箱地址和密码

d := gomail.NewDialer("smtp.example.com", 465, "user@example.com", "password")
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}

7. 执行邮件发送

err := d.DialAndSend(m)
if err != nil {
    // 处理错误
}

至此,邮件已经发送成功了,整个邮件的内容为(其中,附件内容为foo.bar):

Mime-Version: 1.0
Date: Sat, 10 Nov 2018 21:40:13 +0800
From: =?UTF-8?q?=E5=BC=A0=E4=B8=89?= <user@example.com>
To: user@qq.com
Subject: =?UTF-8?q?=E9=82=AE=E4=BB=B6=E6=A0=87=E9=A2=98?=
Content-Type: multipart/mixed;
 boundary=92142f9522a20d2f4feffce957bf68b46ad1a620e68fbecbf35669266e9a

--92142f9522a20d2f4feffce957bf68b46ad1a620e68fbecbf35669266e9a
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

=E7=B3=BB=E7=BB=9F=E9=82=AE=E4=BB=B6=E8=AF=B7=E5=8B=BF=E5=9B=9E=E5=A4=8D
--92142f9522a20d2f4feffce957bf68b46ad1a620e68fbecbf35669266e9a
Content-Disposition: attachment; filename="附件.txt"
Content-Transfer-Encoding: base64
Content-Type: text/plain; charset=utf-8; name="附件.txt"

Zm9vLmJhcgo=
--92142f9522a20d2f4feffce957bf68b46ad1a620e68fbecbf35669266e9a--

打印邮件内容,可以将Message写入到一个缓冲区中,代码如下:

buf := new(bytes.Buffer)
m.WriteTo(buf)
fmt.Println(buf.String())

解决gomail v2.0.0版本下中文附件名乱码的问题

在不同的邮件服务器中,对于中文附件名的编码存在不同的规范,我们可以尝试一下,将上面的邮件附件发送到QQ邮箱,附件名显示正常,发送到126的邮箱就是乱码(这是我测试的结果)。对此,我们可以通过给附件名进行编码的方式来解决这个问题。

    name := "附件.txt"
    m.Attach("/tmp/foo.txt",
        gomail.Rename(name),
        gomail.SetHeader(map[string][]string{
            "Content-Disposition": []string{
                fmt.Sprintf(`attachment; filename="%s"`, mime.QEncoding.Encode("UTF-8", name)),
            },
        }),
    )
    

将邮件内容更改为Base64编码


    m := gomail.NewMessage(
        gomail.SetEncoding(gomail.Base64),
    )

// ...


    name := "附件.txt"
    m.Attach("/tmp/foo.txt",
        gomail.Rename(name),
        gomail.SetHeader(map[string][]string{
            "Content-Disposition": []string{
                fmt.Sprintf(`attachment; filename="%s"`, mime.BEncoding.Encode("UTF-8", name)),
            },
        }),
    )

使用Base64编码后的邮件内容为:

Mime-Version: 1.0
Date: Sat, 10 Nov 2018 21:53:22 +0800
From: =?UTF-8?b?5byg5LiJ?= <user@example.com>
To: user@qq.com
Subject: =?UTF-8?b?6YKu5Lu25qCH6aKY?=
Content-Type: multipart/mixed;
 boundary=42839966777f27ebe3861a73eabbf615036ea57b3222968e21519c64cdd5

--42839966777f27ebe3861a73eabbf615036ea57b3222968e21519c64cdd5
Content-Transfer-Encoding: base64
Content-Type: text/html; charset=UTF-8

57O757uf6YKu5Lu26K+35Yu/5Zue5aSN
--42839966777f27ebe3861a73eabbf615036ea57b3222968e21519c64cdd5
Content-Disposition: attachment; filename="=?UTF-8?b?6ZmE5Lu2LnR4dA==?="
Content-Transfer-Encoding: base64
Content-Type: text/plain; charset=utf-8; name="附件.txt"

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

推荐阅读更多精彩内容