Ai
1 Star 0 Fork 0

go-better/go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
message.go 3.19 KB
一键复制 编辑 原始数据 按行查看 历史
proce 提交于 2022-03-20 18:50 +08:00 . save
package email
import (
"bytes"
"crypto/rand"
"encoding/base64"
)
// Message implements Internet Message as defined in RFC2822 and RFC2045 ~ RFC2049.
type Message struct {
Headers []Header
Body []byte // body for Content-Type: plain, image, audio, video or application.
BodyParts []Message // body for Content-Type: multipart or message.
}
type properties struct {
isComposite bool
isMultipart bool
multipartBoundary string
contentTransferEncoding string
}
// Bytes is the most important entrance func, it calls all the logic to convert a Message to bytes.
func (m *Message) Bytes() ([]byte, error) {
m.Headers = setupMIMEVersion(m.Headers)
buf := &bytes.Buffer{}
if err := m.write(buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (m *Message) write(buf *bytes.Buffer) error {
p, err := m.getProperties()
if err != nil {
return err
}
if err := m.writeHeaders(&p, buf); err != nil {
return err
}
// write empty line seperator
if err := writeLine("", buf); err != nil {
return err
}
return m.writeBody(p, buf)
}
func (m *Message) writeHeaders(p *properties, buf *bytes.Buffer) error {
if err := validateHeaders(m.Headers); err != nil {
return err
}
if headers, err := setupEntityHeaders(m.Headers, p); err != nil {
return err
} else {
m.Headers = headers
}
return writeHeadersTo(m.Headers, buf)
}
func (m *Message) writeBody(p properties, buf *bytes.Buffer) error {
if len(m.BodyParts) > 0 {
return m.writeBodyParts(p, buf)
} else {
return writeBodyTo(m.Body, p, buf)
}
}
func (m *Message) writeBodyParts(p properties, buf *bytes.Buffer) error {
for _, bodyPart := range m.BodyParts {
if err := writeMultipartBoundary(p, false, buf); err != nil {
return err
}
if err := bodyPart.write(buf); err != nil {
return err
}
}
return writeMultipartBoundary(p, true, buf)
}
func (m *Message) getProperties() (properties, error) {
p := properties{
isComposite: len(m.BodyParts) > 0,
isMultipart: m.IsMultipart(),
}
if p.isMultipart {
if boundary, err := multipartBoundary(); err != nil {
return properties{}, err
} else {
p.multipartBoundary = boundary
}
}
return p, nil
}
// IsMultipart return if this is a multipart message.
func (m *Message) IsMultipart() bool {
switch len(m.BodyParts) {
case 0:
// When has no body parts, it must not be a multipart message.
return false
case 1:
// When has only one body part, it's a multipart message
// if the "Content-Type" Header is not provided or multipart.
h := findHeader(m.Headers, ContentType)
return h.isEmpty() || h.isMultipart()
default:
// When has more than one body parts, it must be a multipart message.
return true
}
}
func writeMultipartBoundary(p properties, end bool, buf *bytes.Buffer) error {
if !p.isMultipart {
return nil
}
line := "\n--" + p.multipartBoundary
if end {
line += "--"
}
return writeLine(line, buf)
}
func multipartBoundary() (string, error) {
var a [30]byte
b := a[:]
if _, err := rand.Read(b); err != nil {
return "", err
}
return "=_" + base64.URLEncoding.EncodeToString(b), nil
}
func writeLine(content string, buf *bytes.Buffer) error {
_, err := buf.WriteString(content + "\n")
return err
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/go-better/go.git
git@gitee.com:go-better/go.git
go-better
go
go
d31700df43a9

搜索帮助