golang流式处理互联网消息格式和邮件消息插件库go-message的使用
golang流式处理互联网消息格式和邮件消息插件库go-message的使用
go-message 是一个用于处理互联网消息格式的 Go 库。它实现了以下 RFC 标准:
- RFC 5322: 互联网消息格式
- RFC 2045, RFC 2046 和 RFC 2047: 多用途互联网邮件扩展(MIME)
- RFC 2183: Content-Disposition 头字段
特性
- 流式 API
- 自动编码和字符集处理(要解码所有字符集,需要在应用中添加
import _ "github.com/emersion/go-message/charset"
) - 包含
mail
子包用于读写邮件消息 - 支持 DKIM
- 包含
textproto
子包实现有线格式
示例代码
1. 创建简单的邮件消息
package main
import (
"bytes"
"fmt"
"github.com/emersion/go-message"
"github.com/emersion/go-message/mail"
"io"
"time"
)
func main() {
// 创建一个缓冲区来存储消息
var b bytes.Buffer
// 创建邮件消息头
h := mail.NewHeader()
h.SetDate(time.Now())
h.SetAddressList("From", []*mail.Address{{Name: "发件人", Address: "from@example.com"}})
h.SetAddressList("To", []*mail.Address{{Name: "收件人", Address: "to@example.com"}})
h.SetSubject("测试邮件")
// 创建邮件消息
w, err := mail.CreateWriter(&b, h)
if err != nil {
panic(err)
}
// 添加文本部分
tw, err := w.CreateInline()
if err != nil {
panic(err)
}
th := mail.NewTextHeader()
th.Set("Content-Type", "text/plain; charset=UTF-8")
if _, err := tw.WriteHeader(th); err != nil {
panic(err)
}
if _, err := io.WriteString(tw, "这是一封测试邮件。"); err != nil {
panic(err)
}
// 关闭写入器
if err := w.Close(); err != nil {
panic(err)
}
// 输出生成的邮件
fmt.Println(b.String())
}
2. 解析邮件消息
package main
import (
"fmt"
"github.com/emersion/go-message"
"github.com/emersion/go-message/mail"
"io"
"strings"
)
func main() {
// 示例邮件内容
rawMessage := `From: from@example.com
To: to@example.com
Subject: 测试邮件
Date: Wed, 11 May 2022 10:00:00 +0800
Content-Type: multipart/alternative; boundary="boundary"
--boundary
Content-Type: text/plain; charset=UTF-8
这是一封测试邮件。
--boundary--`
// 创建邮件阅读器
r := strings.NewReader(rawMessage)
e, err := message.Read(r)
if err != nil {
panic(err)
}
// 解析为邮件消息
mr, err := mail.CreateReader(e)
if err != nil {
panic(err)
}
// 打印邮件头信息
fmt.Println("From:", mr.Header.Get("From"))
fmt.Println("To:", mr.Header.Get("To"))
fmt.Println("Subject:", mr.Header.Get("Subject"))
fmt.Println("Date:", mr.Header.Get("Date"))
// 处理邮件正文
for {
p, err := mr.NextPart()
if err == io.EOF {
break
} else if err != nil {
panic(err)
}
switch h := p.Header.(type) {
case *mail.InlineHeader:
// 内联文本部分
body, _ := io.ReadAll(p.Body)
fmt.Printf("Text content: %s\n", body)
case *mail.AttachmentHeader:
// 附件部分
filename, _ := h.Filename()
fmt.Printf("Attachment: %s\n", filename)
}
}
}
3. 处理 MIME 消息
package main
import (
"bytes"
"fmt"
"github.com/emersion/go-message"
"io"
)
func main() {
// 示例 MIME 消息
rawMessage := `Content-Type: multipart/mixed; boundary="boundary"
--boundary
Content-Type: text/plain; charset=UTF-8
这是文本部分。
--boundary
Content-Type: application/json
{"key": "value"}
--boundary--`
// 创建消息阅读器
r := strings.NewReader(rawMessage)
e, err := message.Read(r)
if err != nil {
panic(err)
}
// 检查是否是 multipart 消息
if mr := e.MultipartReader(); mr != nil {
// 遍历所有部分
for {
p, err := mr.NextPart()
if err == io.EOF {
break
} else if err != nil {
panic(err)
}
// 获取内容类型
contentType, _, _ := p.Header.ContentType()
body, _ := io.ReadAll(p.Body)
fmt.Printf("Content-Type: %s\n", contentType)
fmt.Printf("Content: %s\n", body)
}
}
}
许可证
MIT
更多关于golang流式处理互联网消息格式和邮件消息插件库go-message的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang流式处理互联网消息格式和邮件消息插件库go-message的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-message库使用指南:流式处理互联网消息与邮件
go-message是一个用于处理互联网消息格式(如MIME)和邮件消息的Go语言库。它提供了流式处理能力,非常适合处理大消息而不消耗过多内存。
基本概念
go-message支持以下功能:
- 解析和生成MIME消息
- 处理邮件消息(RFC 5322)
- 流式读写
- 支持附件和内联内容
- 处理多部分消息
安装
go get github.com/emersion/go-message
基本使用示例
1. 创建简单文本邮件
package main
import (
"bytes"
"fmt"
"github.com/emersion/go-message"
"github.com/emersion/go-message/mail"
"io"
"time"
)
func createSimpleEmail() (string, error) {
var b bytes.Buffer
// 创建邮件头
h := mail.NewHeader()
h.SetAddressList("From", []*mail.Address{{Name: "张三", Address: "zhangsan@example.com"}})
h.SetAddressList("To", []*mail.Address{{Name: "李四", Address: "lisi@example.com"}})
h.Set("Subject", "测试邮件")
h.SetDate("Date", time.Now())
// 创建邮件实体
w, err := mail.CreateTextWriter(&b, h)
if err != nil {
return "", err
}
// 写入邮件正文
_, err = io.WriteString(w, "这是一封测试邮件。\r\n")
if err != nil {
return "", err
}
err = w.Close()
if err != nil {
return "", err
}
return b.String(), nil
}
func main() {
email, err := createSimpleEmail()
if err != nil {
panic(err)
}
fmt.Println(email)
}
2. 解析邮件
func parseEmail(email string) error {
// 创建消息读取器
r := strings.NewReader(email)
mr, err := message.Read(r)
if err != nil {
return err
}
// 解析为邮件消息
mailReader, err := mail.CreateReader(mr)
if err != nil {
return err
}
// 打印头信息
fmt.Println("From:", mailReader.Header.Get("From"))
fmt.Println("To:", mailReader.Header.Get("To"))
fmt.Println("Subject:", mailReader.Header.Get("Subject"))
// 处理邮件正文
for {
p, err := mailReader.NextPart()
if err == io.EOF {
break
} else if err != nil {
return err
}
switch h := p.Header.(type) {
case *mail.InlineHeader:
fmt.Println("Inline text part:")
body, _ := io.ReadAll(p.Body)
fmt.Println(string(body))
case *mail.AttachmentHeader:
filename, _ := h.Filename()
fmt.Println("Attachment:", filename)
}
}
return nil
}
3. 创建带附件的邮件
func createEmailWithAttachment() (string, error) {
var b bytes.Buffer
// 创建多部分消息
h := mail.NewHeader()
h.SetAddressList("From", []*mail.Address{{Name: "张三", Address: "zhangsan@example.com"}})
h.SetAddressList("To", []*mail.Address{{Name: "李四", Address: "lisi@example.com"}})
h.Set("Subject", "带附件的测试邮件")
// 创建多部分写入器
mw, err := mail.CreateWriter(&b, h)
if err != nil {
return "", err
}
// 添加文本部分
tw, err := mw.CreateInline()
if err != nil {
return "", err
}
th := mail.NewTextHeader()
th.Set("Content-Type", "text/plain; charset=UTF-8")
_, err = io.WriteString(tw, "这是一封带附件的测试邮件。\r\n")
tw.Close()
// 添加附件
aw, err := mw.CreateAttachment("report.pdf", "application/pdf")
if err != nil {
return "", err
}
_, err = io.WriteString(aw, "PDF文件内容...")
aw.Close()
mw.Close()
return b.String(), nil
}
高级特性
1. 流式处理大附件
func streamLargeAttachment(dest io.Writer, attachmentPath string) error {
// 创建邮件头
h := mail.NewHeader()
// 设置头信息...
mw, err := mail.CreateWriter(dest, h)
if err != nil {
return err
}
// 添加文本部分
tw, err := mw.CreateInline()
// 写入文本内容...
tw.Close()
// 添加大附件
aw, err := mw.CreateAttachment("largefile.bin", "application/octet-stream")
if err != nil {
return err
}
// 这里可以替换为实际的文件读取
file, err := os.Open(attachmentPath)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(aw, file)
if err != nil {
return err
}
aw.Close()
mw.Close()
return nil
}
2. 处理HTML邮件
func createHTMLEmail() (string, error) {
var b bytes.Buffer
h := mail.NewHeader()
// 设置头信息...
// 创建多部分替代消息(同时包含HTML和纯文本)
mw, err := mail.CreateWriter(&b, h)
if err != nil {
return "", err
}
// 纯文本版本
tw, err := mw.CreateInline()
th := mail.NewTextHeader()
th.Set("Content-Type", "text/plain; charset=UTF-8")
io.WriteString(tw, "这是纯文本版本...")
tw.Close()
// HTML版本
hw, err := mw.CreateInline()
hh := mail.NewTextHeader()
hh.Set("Content-Type", "text/html; charset=UTF-8")
io.WriteString(hw, "<html><body><h1>这是HTML版本</h1></body></html>")
hw.Close()
mw.Close()
return b.String(), nil
}
注意事项
- 流式处理:go-message设计用于流式处理,适合处理大消息而不会耗尽内存
- 内存效率:尽可能使用io.Copy而不是读取整个内容到内存
- 错误处理:始终检查Close()方法的返回值
- 并发安全:消息读取器和写入器通常不是并发安全的
go-message是一个功能强大且高效的库,特别适合需要处理大量邮件或大附件的应用场景。通过流式处理,它可以保持低内存占用,同时提供灵活的API来处理各种消息格式。