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

huangapple go评论77阅读模式
英文:

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--

huangapple
  • 本文由 发表于 2021年12月10日 03:23:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/70295590.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定