You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Golang SMTP与multipart发送邮件时出现ATT001.txt附件问题

问题原因及解决方法

你的代码里手动拼接MIME multipart内容时格式不规范,导致邮件客户端解析出无效的空附件(ATT001.txt),具体问题点和修复方案如下:

核心问题点

  • 邮件正文部分缺少必要空行:在Content-Type: text/plain; charset=utf-8之后,没有添加空行就直接写正文,违反MIME格式规范
  • 附件循环内边界处理错误:循环里重复添加边界标记,还多写了多余的--\n,导致生成了空的multipart部件,被客户端识别为0字节附件
  • 错误混用multipart.Writer和手动拼接:创建了multipart.Writer但没用来生成部件,反而手动拼接边界,容易出现格式疏漏

修复后的ToBytes方法

func (m *Message) ToBytes() []byte {
    buf := bytes.NewBuffer(nil)
    withAttachments := len(m.Attachments) > 0

    // 写入邮件头部
    buf.WriteString(fmt.Sprintf("From: %s\n", "some_email@email.com"))
    buf.WriteString(fmt.Sprintf("Subject: %s\n", m.Subject))
    buf.WriteString(fmt.Sprintf("To: %s\n", strings.Join(m.To, ",")))
    if len(m.CC) > 0 {
        buf.WriteString(fmt.Sprintf("Cc: %s\n", strings.Join(m.CC, ",")))
    }
    if len(m.BCC) > 0 {
        buf.WriteString(fmt.Sprintf("Bcc: %s\n", strings.Join(m.BCC, ",")))
    }
    buf.WriteString("MIME-Version: 1.0\n")

    if withAttachments {
        writer := multipart.NewWriter(buf)
        buf.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s\n\n", writer.Boundary()))

        // 添加邮件正文部件
        bodyPart, err := writer.CreatePart(map[string][]string{
            "Content-Type": {"text/plain; charset=utf-8"},
        })
        if err != nil {
            panic(err) // 实际场景建议返回错误,这里简化处理
        }
        bodyPart.Write([]byte(m.Body))

        // 添加附件部件
        for fileName, content := range m.Attachments {
            partHeader := map[string][]string{
                "Content-Type":        {http.DetectContentType(content)},
                "Content-Transfer-Encoding": {"base64"},
                "Content-Disposition": {fmt.Sprintf("attachment; filename=\"%s\"", fileName)},
            }
            attachmentPart, err := writer.CreatePart(partHeader)
            if err != nil {
                panic(err)
            }
            encoder := base64.NewEncoder(base64.StdEncoding, attachmentPart)
            defer encoder.Close()
            encoder.Write(content)
        }

        // 关闭writer以写入结束边界
        writer.Close()
    } else {
        buf.WriteString("Content-Type: text/plain; charset=utf-8\n\n")
        buf.WriteString(m.Body)
    }

    return buf.Bytes()
}

关键修改说明

  • 完全使用multipart.Writer的API创建各个部件,避免手动拼接边界导致的格式错误
  • 正文部件通过CreatePart创建,自动处理头部和内容的分隔空行
  • 附件使用base64编码器直接写入部件,确保编码和格式正确
  • 调用writer.Close()自动生成正确的结束边界(--boundary--)

这样修改后,邮件的MIME格式完全符合规范,不会再出现无效的空附件。

内容的提问来源于stack exchange,提问作者Rajat Goyal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 13:55:55