使用Go语言net/mail库解析多格式邮件的求助
解决Go net/mail解析Apple Mail多部分邮件并通过SendGrid正常转发的问题
核心问题分析
Apple Mail发送的HTML邮件通常是multipart/alternative或multipart/mixed类型,net/mail库仅会将邮件解析为*mail.Message结构,其中的Body是带分隔符的原始多部分内容。直接转发该内容会导致SendGrid无法正确识别各部分的边界与类型,进而引发显示异常、附件失效等问题。
正确解析与处理步骤
1. 拆分多部分邮件结构
不要直接使用msg.Body,需先解析Content-Type提取边界,再拆分出各个独立部分:
import ( "io" "mime" "mime/multipart" "net/mail" "strings" ) func parseMultipartMessage(msg *mail.Message) ([]*multipart.Part, error) { contentType := msg.Header.Get("Content-Type") mediaType, params, err := mime.ParseMediaType(contentType) if err != nil { return nil, err } // 非多部分邮件直接封装为单部分返回 if !strings.HasPrefix(mediaType, "multipart/") { part := &multipart.Part{Header: msg.Header} part.SetBody(msg.Body) return []*multipart.Part{part}, nil } boundary := params["boundary"] reader := multipart.NewReader(msg.Body, boundary) var parts []*multipart.Part for { part, err := reader.NextPart() if err == io.EOF { break } if err != nil { return nil, err } parts = append(parts, part) } return parts, nil }
2. 重组内容适配SendGrid转发
遍历拆分后的部分,分类处理正文与附件,再用SendGrid SDK构建标准邮件结构:
import ( "github.com/sendgrid/sendgrid-go" "github.com/sendgrid/sendgrid-go/helpers/mail" "io/ioutil" "mime" ) func forwardWithSendGrid(originalMsg *mail.Message, parts []*multipart.Part) error { from := mail.NewEmail(originalMsg.Header.Get("From"), originalMsg.Header.Get("From")) to := mail.NewEmail(originalMsg.Header.Get("To"), originalMsg.Header.Get("To")) subject := originalMsg.Header.Get("Subject") var plainContent, htmlContent string var attachments []*mail.Attachment for _, part := range parts { contentType := part.Header.Get("Content-Type") mediaType, _, err := mime.ParseMediaType(contentType) if err != nil { continue } body, err := ioutil.ReadAll(part) if err != nil { continue } switch mediaType { case "text/plain": plainContent = string(body) case "text/html": htmlContent = string(body) default: // 处理附件,提取文件名与 disposition disp := part.Header.Get("Content-Disposition") _, params, err := mime.ParseMediaType(disp) if err != nil { continue } filename := params["filename"] attachment := mail.NewAttachment() attachment.SetContent(string(body)) attachment.SetFilename(filename) attachment.SetType(contentType) attachment.SetDisposition(disp) attachments = append(attachments, attachment) } } message := mail.NewSingleEmail(from, subject, to, plainContent, htmlContent) message.Attachments = attachments client := sendgrid.NewSendClient("YOUR_SENDGRID_API_KEY") _, err := client.Send(message) return err }
3. 处理嵌套多部分与编码
若遇到嵌套的多部分结构(比如multipart/mixed包含multipart/alternative),需递归解析所有子部分;net/mail的Part会自动处理quoted-printable或base64编码,直接读取内容即可,无需手动解码。
关键注意事项
- 禁止直接转发原始
msg.Body,必须拆分后重组; - 保留原始邮件的字符编码(从Content-Type的
charset参数获取),避免正文乱码; - SendGrid会自动生成新的多部分边界,无需手动添加原始分隔符;
- 测试时需覆盖Apple Mail发送的HTML+纯文本+附件场景,验证转发后的显示与附件完整性。
内容的提问来源于stack exchange,提问作者Jomy
相关产品推荐
相关产品推荐

