带 CSV 附件的 SMTP 电子邮件 - 文件末尾出现额外字符

SMTP email with CSV attachment - extra characters coming in at the end of file

我正在使用 Golang 创建一个电子邮件客户端,以发送附有 CSV 文件的电子邮件。一切正常,除了在收到的电子邮件附件中,我可以在文件末尾看到一些不需要的额外字符。

我的代码片段:


import (
    "bytes"
    "encoding/base64"
    "fmt"
    "mime/multipart"
    "net/smtp"

    ...
)

func SendEmail(cfg Config) error {

    body := bytes.NewBuffer(nil)
    body.WriteString(fmt.Sprintf("From: %s\n", cfg.EmailFrom))
    body.WriteString(fmt.Sprintf("To: %s\n", cfg.EmailTo))
    body.WriteString(fmt.Sprintf("Subject: %s\n", cfg.EmailSubject))

    // csv file to attach
    fileContents := `column1,column2,column3\nAAA,BBB,CCC\nDDD,EEE,FFF\n`
    fileContentBytes := []byte(fileContents)

    body.WriteString("MIME-Version: 1.0\n")
    writer := multipart.NewWriter(body)
    boundary := writer.Boundary()

    // attach file
    body.WriteString("Content-Type: text/plain\n")
    body.WriteString("Content-Transfer-Encoding: base64\n")
    body.WriteString(fmt.Sprintf("Content-Disposition: attachment; filename=%s\n", "test-filename"))

    encodedBytes := make([]byte, base64.StdEncoding.EncodedLen(len(fileContentBytes)))
    base64.StdEncoding.Encode(encodedBytes, fileContentBytes)
    body.Write(encodedBytes)
    body.WriteString(fmt.Sprintf("\n--%s--", boundary))

    err = smtp.SendMail(cfg.EmailSMTPHost+":"+cfg.EmailSMTPPort,
        nil, cfg.EmailFrom, []string{cfg.EmailTo}, body.Bytes())
    if err != nil {
        return errors.Wrap(err, "smtp.SendMail failed")
    }

    return nil
}

预期的 csv 文件:

column1,column2,column3
AAA,BBB,CCC
DDD,EEE,FFF

获取的csv文件:

column1,column2,column3
AAA,BBB,CCC
DDD,EEE,FFF
5k§xõí»ã}8

文件内容编码有问题吗?任何帮助将不胜感激,谢谢!

此代码至少有两个问题:缺少分隔 MIME header 和 body 的空行,然后在末尾添加一些 MIME 边界,即使这不是多部分邮件。目前创建的邮件如下所示:

From: me@example.com
To: you@example.com
Subject: test
MIME-Version: 1.0
Content-Type: text/plain
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=test-filename
Y29sdW1uMSxjb2x1bW4yLGNvbHVtbjNcbkFBQSxCQkIsQ0NDXG5EREQsRUVFLEZGRlxu
--973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086--

最后的错误边界被解码为 base64,无效的 base64 字符如“-”被简单地忽略了。这会导致输出末尾出现垃圾。

作为一个单独的部分,它应该看起来像这样。注意丢失的(错误的)end-boundary 并注意 MIME header 和 body.

之间的空行
From: me@example.com
To: you@example.com
Subject: test
MIME-Version: 1.0
Content-Type: text/plain
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=test-filename

Y29sdW1uMSxjb2x1bW4yLGNvbHVtbjNcbkFBQSxCQkIsQ0NDXG5EREQsRUVFLEZGRlxu

或者,它应该作为一个多部分邮件来完成,如下所示。请注意主 MIME header.

中的不同 Content-Type
From: me@example.com
To: you@example.com
Subject: test
MIME-Version: 1.0
Content-Type: multipart/mixed; 
   boundary=973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086

--973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086
Content-Type: text/plain
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=test-filename

Y29sdW1uMSxjb2x1bW4yLGNvbHVtbjNcbkFBQSxCQkIsQ0NDXG5EREQsRUVFLEZGRlxu
--973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086--