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

发送带PDF附件的SMTP邮件是否必须使用Base64编码?

SMTP发送带PDF附件的邮件:是否必须Base64编码?

我想发送一封带PDF附件的邮件,找到一个可用的Golang示例,运行正常,但我觉得Base64编码没必要,就省略了该步骤并修改了邮件头,新的BuildMail函数如下:

func BuildMail(mail Mail) []byte {
    var buf bytes.Buffer

    buf.WriteString(fmt.Sprintf("From: %s\r\n", mail.Sender))
    buf.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(mail.To, ";")))
    buf.WriteString(fmt.Sprintf("Subject: %s\r\n", mail.Subject))

    boundary := "my-boundary-779"
    buf.WriteString("MIME-Version: 1.0\r\n")
    buf.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s\n",
    boundary))

    buf.WriteString(fmt.Sprintf("\r\n--%s\r\n", boundary))
    buf.WriteString("Content-Type: text/plain; charset=\"utf-8\"\r\n")
    buf.WriteString(fmt.Sprintf("\r\n%s", mail.Body))

    buf.WriteString(fmt.Sprintf("\r\n--%s\r\n", boundary))
    buf.WriteString("Content-Type: application/pdf\r\n")
    buf.WriteString("Content-Disposition: attachment; filename=words.pdf\r\n")
    buf.WriteString("Content-ID: <words.pdf>\r\n\r\n")

    data := readFile("words.pdf")
    buf.Write(data)
    buf.WriteString(fmt.Sprintf("\r\n--%s", boundary))

    buf.WriteString("--")

    return buf.Bytes()
}

但运行后收到的PDF附件是空的,请问通过SMTP发送邮件时,附件是否必须进行Base64编码?原因是什么?


回答

是的,二进制附件(比如PDF)必须进行Base64编码,核心原因有两个:

  1. SMTP协议的文本传输限制:SMTP本质是基于ASCII文本的协议,只能安全传输0-127范围内的字符。PDF这类二进制文件包含大量128-255的非ASCII字节,直接发送会被SMTP服务器识别为非法字符,要么被截断、篡改,要么直接丢弃,导致接收端拿到空附件或损坏文件。

  2. MIME规范的强制要求:MIME(多用途互联网邮件扩展)明确规定,对于application/pdf这类二进制内容,必须通过Content-Transfer-Encoding头声明编码方式,并使用Base64将二进制数据转换为ASCII兼容格式。Base64会把3字节二进制数据转成4个ASCII字符,完美适配SMTP的文本传输规则,保证数据完整无损。

你省略编码后,邮件客户端无法解析乱码的二进制数据,自然会显示附件为空。修复方法很直接:

  • 给PDF附件的头部加上Content-Transfer-Encoding: base64
  • 用Go标准库的encoding/base64包把读取到的PDF数据编码后再写入缓冲区

修改后的附件段代码示例:

buf.WriteString(fmt.Sprintf("\r\n--%s\r\n", boundary))
buf.WriteString("Content-Type: application/pdf\r\n")
buf.WriteString("Content-Disposition: attachment; filename=words.pdf\r\n")
buf.WriteString("Content-ID: <words.pdf>\r\n")
buf.WriteString("Content-Transfer-Encoding: base64\r\n\r\n")

data := readFile("words.pdf")
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
encoder.Write(data)
encoder.Close()
buf.WriteString(fmt.Sprintf("\r\n--%s", boundary))

这样就能确保PDF附件被正确传输和解析了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:02:12