我正在尝试在Go(Golang)中发送包含电子邮件正文和文件附件(CSV文件)的电子邮件。
我遵循的是多部分邮件的mime
标准,但是我对遵循该标准的邮件的结构不是很熟悉。我隐约跟随一位同事的Python代码段作为使用Python库email
的指南(我认为这来自标准库),例如MIMEText
和MIMEMultipart
。
执行以下Go代码时,电子邮件正文未显示:
此函数应返回一个字节片,用作从Go标准库调用smtp.SendMail
的参数。请参阅下面的注释,以解释收到的电子邮件消息(THIS DOES NOT SHOW UP [...]
和THIS ALSO DOES NOT SHOW UP [...]
)的变化。
func msgWithAttachment(subject, filePath string) ([]byte, error) {
// this is the separator used for the various parts of the MIME message structure
// identified as "boundary"
bPlaceholder := "our-custom-separator"
// the message setup of the common/standard initial part
mime := bytes.NewBuffer(nil)
mime.WriteString(fmt.Sprintf("Subject: %s\r\nMIME-Version: 1.0\r\n", subject))
mime.WriteString(fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s\r\n", bPlaceholder))
// THIS DOES NOT SHOW UP AS THE BODY OF THE EMAIL...
// mime.WriteString("\r\n")
// mime.WriteString(fmt.Sprintf("--%s\r\n", bPlaceholder))
// mime.WriteString("This should be the email message body (v1)...")
// mime.WriteString("\r\n")
// THIS ALSO DOES NOT SHOW UP AS THE BODY OF THE EMAIL...
// BUT IS NEEDED OTHERWISE THE EMAIL MESSAGE SEEMS TO CONTAIN AS ATTACHMENT THE EMAIL MESSAGE ITSELF
// (CONTAINING ITSELF THE REAL ATTACHMENT)
mime.WriteString(fmt.Sprintf("--%s\r\n", bPlaceholder))
mime.WriteString("Content-Type: text/plain; charset=utf-8\r\n")
mime.WriteString("This should be the email message body (v2)...")
// attach a file from the filesystem
_, msgFilename := filepath.Split(filePath)
mime.WriteString(fmt.Sprintf("\n--%s\r\n", bPlaceholder))
mime.WriteString("Content-Type: application/octet-stream\r\n")
mime.WriteString("Content-Description: " + msgFilename + "\r\n")
mime.WriteString("Content-Transfer-Encoding: base64\r\n")
mime.WriteString("Content-Disposition: attachment; filename=\"" + msgFilename + "\"\r\n\r\n")
fileContent, err := ioutil.ReadFile(filePath) // read and encode the content of the file
if err != nil {
return nil, err
}
b := make([]byte, base64.StdEncoding.EncodedLen(len(fileContent)))
base64.StdEncoding.Encode(b, fileContent)
mime.Write(b)
// footer of the email message
mime.WriteString("\r\n--" + bPlaceholder + "--\r\n\r\n")
return mime.Bytes(), nil
}
答案 0 :(得分:1)
巧合的是,前几天我遇到了类似的问题。我需要在正文内容类型和正文本身的开头之间留空行。以下是此部分代码的更新行:
mime.WriteString("Content-Type: text/plain; charset=utf-8\r\n")
mime.WriteString("\r\nThis should be the email message body (v2)...")
为清楚起见,此换行符(\ r \ n)不必完全在此处,可以将其追加到上面的内容类型行中。只需在内容类型和正文的开头之间看到一条空白行即可。
我假设附件没有问题,对吗?我的假设是,因为在添加附件数据之前,内容处置行的末尾有双换行符。
答案 1 :(得分:0)
阅读 RFC 规范对我有帮助:https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
<块引用>请注意,封装边界必须出现在一行的开头,即在 CRLF 之后,并且初始 CRLF 被认为是封装边界的一部分,而不是前面部分的一部分。边界后面必须紧跟另一个 CRLF 和下一部分的头字段,或者两个 CRLF,在这种情况下,下一部分没有头字段(因此假定它是 Content-Type 文本/普通)。