带 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--
我正在使用 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-TypeFrom: 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--