linux smtp 发送邮件乱码,使用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?=

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?=

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--

Go语言自身并不内置提供直接发送电子邮件的功能,但你可以利用第三方库如`net/smtp`、`golang.org/x/net/html`等来进行基本的SMTP通信,完成邮件发送任务。此外,还可以考虑使用一些成熟的邮件发送库简化流程,比如Gopkg.in/alecthomas/gometalinter.v1 或者 go-mailgun。 ### 使用`smtp`库发送邮件的基本步骤: 假设你需要通过SMTP服务器发送一封邮件,首先需要设置好以下几项内容: 1. **SMTP服务器地址**:通常为你的邮件服务提供商提供的SMTP服务器地址(例如 Gmail 的 SMTP 地址是 smtp.gmail.com)。 2. **端口号**:默认的端口通常是 587 或者 465 (TLS 和 SSL 加密连接)。 3. **身份验证信息**:用户(即邮箱地址)和密码(如果需要)。 4. **发件人**、**收件人**及**邮件内容**。 下面是一个简单的示例代码: ```go package main import ( "mime" "net/smtp" "os" ) func sendEmail(smtpServer string, fromAddr string, toAddrs []string, subject string, body string) error { auth := smtp.PlainAuth("", "your-email@example.com", "your-password", smtpServer) mIMEPart := mime.NewMultipartForm(mime.MultipartRelated) mIMEPart.SetBoundary("b") mIMEPart.Write(os.Stdout) // 添加邮件标题部分 hdr := make(http.Header) hdr.Set("Content-Disposition", `form-data; name="subject"; filename=""`) hdr.Set("Content-Type", `text/plain; charset=utf-8`) mIMEPart.Write([]byte(`subject=` + subject)) // 添加邮件正文部分 hdr = http.Header{} hdr.Set("Content-Disposition", `form-data; name="body"; filename=""`) hdr.Set("Content-Type", `text/plain; charset=utf-8`) mIMEPart.Write([]byte(`body=` + body)) for _, toAddr := range toAddrs { // 构建邮件头部并发送 header := "To:" + toAddr + "\r\n" + "From:" + fromAddr + "\r\n" + "MIME-Version: 1.0\r\n" + "Subject:" + subject + "\r\n" + "Content-Type: multipart/mixed; boundary=b\r\n" err := smtp.SendMail(smtpServer+":"+os.Getenv("SMTP_PORT"), auth, fromAddr, append(toAddrs, fromAddr), []byte(header)) if err != nil { return err } } return nil } func main() { smtpServer := "smtp.example.com" fromAddr := "your-email@example.com" toAddrs := []string{"recipient-email@example.com"} subject := "Test Email" body := "This is a test email." err := sendEmail(smtpServer, fromAddr, toAddrs, subject, body) if err != nil { fmt.Println("Error sending email:", err) } else { fmt.Println("Email sent successfully.") } } ``` ### 相关问题: 1. 是否有更便捷的库可以用来发送邮件,而不是手动编写SMTP代码? - 可以考虑使用如`github.com/james-hunter/gmail`, `gopkg.in/mail.v2`, 或 `gopkg.in/gomail.v2` 等库,它们提供了更高层次的API用于处理邮件发送过程,使得代码更为简洁易懂。 2. 在生产环境中如何安全地管理邮箱账号的登录凭证? - 可以将密码存储在环境变量中,并在代码中通过`os.Getenv`获取。另一种更安全的做法是使用云服务(如AWS Secrets Manager)、本地键值数据库或加密文件存储。 3. 发送大量邮件时需要注意哪些事项以避免被封禁或被视为垃圾邮件? - 遵守邮件服务商的政策,合理安排邮件发送频率,使用正确的`X-Mailer`头标记软件称,检查邮件的内容是否合法(无恶意链接),以及使用单检查工具确认邮件接收方的安全性和合法性。同时监控发送失败的数量并及时调整策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值