英文:
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
文件内容编码有什么问题吗?感谢您的帮助!
英文:
I'm creating an email client using Golang, to send email with a CSV file attached. Everything is working fine except that in the received email attachment, I can see some unwanted extra characters at the end of the file.
My code snippet:
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
}
Expected csv file:
column1,column2,column3
AAA,BBB,CCC
DDD,EEE,FFF
Obtained csv file:
column1,column2,column3
AAA,BBB,CCC
DDD,EEE,FFF
5k§xõí»ã}8
Anything wrong in the file contents encoding? Any help will be appreciated, thanks!
答案1
得分: 1
这段代码至少有两个问题:缺少空行来分隔MIME头和正文,并且在结尾添加了一些MIME边界,尽管这不是多部分邮件。当前创建的邮件看起来像这样:
发件人:me@example.com
收件人:you@example.com
主题:test
MIME版本:1.0
内容类型:text/plain
内容传输编码:base64
内容分隔:附件;文件名=test-filename
Y29sdW1uMSxjb2x1bW4yLGNvbHVtbjNcbkFBQSxCQkIsQ0NDXG5EREQsRUVFLEZGRlxu
--973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086--
结尾处错误的边界会被解码为包含无效base64字符的base64。这导致输出末尾出现垃圾字符。
相反,它应该像单个部分一样。请注意缺少(错误的)结束边界和MIME头和正文之间的空行。
发件人:me@example.com
收件人:you@example.com
主题:test
MIME版本:1.0
内容类型:text/plain
内容传输编码:base64
内容分隔:附件;文件名=test-filename
Y29sdW1uMSxjb2x1bW4yLGNvbHVtbjNcbkFBQSxCQkIsQ0NDXG5EREQsRUVFLEZGRlxu
或者,可以将其作为多部分邮件完成,如下所示。请注意主MIME头中的不同内容类型。
发件人:me@example.com
收件人:you@example.com
主题:test
MIME版本:1.0
内容类型:multipart/mixed;
分隔符=973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086
--973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086
内容类型:text/plain
内容传输编码:base64
内容分隔:附件;文件名=test-filename
Y29sdW1uMSxjb2x1bW4yLGNvbHVtbjNcbkFBQSxCQkIsQ0NDXG5EREQsRUVFLEZGRlxu
--973d0754ef322150f1977af176c9e1917c6dea9dfa0390e8e99af038c086--
英文:
This code has at least two problems: missing empty line to separate MIME header and body and then adding some MIME boundary at the end even though this is no multipart mail. Currently the created mail looks like this:
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--
The wrong boundary at the end gets decoded as base64 with invalid base64 characters like "-" simply being ignored. This causes the garbage at the end of the output.
It should instead look like this as a single part. Note the missing (wrong) end-boundary and note the empty line between MIME header and 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
Alternatively it should be done as a multipart mail as shown below. Note the different Content-Type in the main MIME header.
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--
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论