Golang:如何使用base64字符串作为附件内容发送带有图像的html正文电子邮件

Golang: how to send html body email with image using base64 string as attachment content

我在我的 golang 处理程序中收到以下消息:

{"fromDisplayName":"ForgottenPassword","to":["example@gmail.com"],"cc":[],"bcc":[],"subject":"ForgottenPassword","body":" \t<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html> \t<head> \t\t<meta http-equiv=\"Content-Type\" content=\"text/html charset=UTF-8\" /> \t\t<title>Forgot Password Email</title> \t</head> \t<body style=\"width:100%; border:0; padding:0; margin:0; text-align:center; background-color:#f3f3f3; font-family:Gotham, 'Helvetica Neue', Helvetica, Arial, 'sans-serif'; font-size:1em\">\t\t \t\t<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width: 100%; max-width: 680px; margin: auto; margin-top: 30px; box-shadow: 0 1px 2px rgba(0,0,0,0.3);\"> \t\t\t<tr> \t\t\t\t<td>\t\t\t\t\t \t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width: 100%;\"> \t\t\t\t\t\t<tr> \t\t\t\t\t\t\t<td style=\"background-color:#ffffff; height:4em; padding:1.5em;\"> \t\t\t\t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width: 100%;\"> \t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t<td style=\"padding-bottom: 20px; text-align: left;\"></td> \t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t<td style=\"width: 100%; height: 1px; background-color: #ccc;\"></td> \t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t</table> \t\t\t\t\t\t\t</td> \t\t\t\t\t\t</tr> \t\t\t\t\t</table> \t\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"width: 100%;\"> \t\t\t\t\t\t<tbody> \t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t<td style=\"width:100%; padding:30px; text-align: center; background-color:#ffffff\"> \t\t\t\t\t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"> \t\t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t\t<td style=\"padding: 40px 40px 0px 40px; text-align: center; font-size:2.5em; font-weight:lighter; mso-height-rule: exactly; line-height: 28px; color: #434795;\">Hi user</td> \t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t\t<td style=\"text-align: center; font-size:1em; padding-top:0.8em; padding-bottom:2em; color:#999999\">You're already a user, so there is no need to sign up.</td> \t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t\t<td style=\"text-align: center; font-size:1em; padding-top:0.8em; padding-bottom:2em; color:#999999\">If you forgot your password, you can reset it .</td> \t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t\t<td style=\"text-align: center;\"> \t\t\t\t\t\t\t\t\t\t\t\t<a><img src=\"cid:278da187427a4bdcaceb76781f4a3753\" alt=\"forgot password\" width=\"100\" height=\"60\" border=\"0\"></a> \t\t\t\t\t\t\t\t\t\t\t</td> \t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t</table> \t\t\t\t\t\t\t\t\t<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"> \t\t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t\t<td> \t\t\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\"> \t\t\t\t\t\t\t\t\t\t\t\t\t<tr> \t\t\t\t\t\t\t\t\t\t\t\t\t\t<td style = \"font-size:0.75em; padding-top:3.5em; padding-bottom:1.25em; text-align: center; color:#999999\">If you received this email by mistake, you can just delete it.</td> \t\t\t\t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t\t\t\t</table> \t\t\t\t\t\t\t\t\t\t\t</td> \t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t</table> \t\t\t\t\t\t\t\t\t<table cellspacing=\"0\" cellpadding=\"0\" text-align=\"center\" align=\"center\" bgcolor=\"#f3f3f3\" width=\"100%\" style=\"max-width: 680px\"> \t\t\t\t\t\t\t\t\t\t <tr> \t\t\t\t\t\t\t\t\t\t\t<td style=\" font-size: 0.75em; text-align: center; mso-height-rule: exactly; line-height:17px; padding-top: 20px;\"> \t\t\t\t\t\t\t\t\t\t\t\t<span style=\"color: #999999;\">We don't check this mailbox, so please don't reply to this message.</span><br> \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"mobile-link--footer;\" style=\"color: #999999;\"></span><br><br> \t\t\t\t\t\t\t\t\t\t\t</td> \t\t\t\t\t\t\t\t\t\t</tr> \t\t\t\t\t\t\t\t\t</table> \t\t\t\t\t\t\t\t</td> \t\t\t\t\t\t\t</tr> \t\t\t\t\t\t</tbody> \t\t\t\t\t</table>\t\t\t\t\t \t\t\t\t</td>\t \t\t\t</tr> \t\t</table>\t\t \t</body> </html>","isHtmlBody":true,"attachments":[{"fileName":"click_button.png","content":"iVBORw0KGgoAAAANSUhEUgAAAGQAAAA8CAYAAACQPx/OAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE92lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTktMDYtMTdUMTM6MTA6MjcrMDI6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTA2LTE3VDEzOjEzOjQwKzAyOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE5LTA2LTE3VDEzOjEzOjQwKzAyOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDplNTY1ZWM0ZC0xNWEwLTQ1YTQtOWM5Ni1hMjgxNTgzNjNmYTciIHhtcE1NOkRvY3VtZW50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","contentType":"image/png","contentDisposition":"inline","cid":"278da187427a4bdcaceb76781f4a3753"}]}

我的目的是通过 google smtp 将消息中的信息作为电子邮件发送。

我可以发送消息,但消息中的图像内容(base64 字符串)未嵌入电子邮件 html 正文中。当我使用 nodejs 和 nodemailer 发送相同的消息时 - 图像显示正确。

我怎样才能做到这一点?

这是我尝试过的方法之一的示例,但未在电子邮件正文中显示图片 ("github.com/jordan-wright/email"):

func EmailServiceBusinessLogic(receivedMsg emailModels.ReceivedMsgModel) error{


    mail := email.NewEmail()

    for _,v := range receivedMsg.Attachments{
        if v.FileName == "" {
            fmt.Println("received empty file name for attachment")
            continue
        }
        if v.Cid == "" {
            fmt.Println("received empty cid for file name: ", v.FileName)
            continue
        }
        if v.ContentType == "" {
            fmt.Println("received empty ContentType for file name: ", v.FileName)
            continue
        }
        if v.Content == "" {
            fmt.Println("received empty Content for file name: ", v.FileName)
            continue
        }

        mail.Attach(strings.NewReader(v.Content)  , v.Cid, v.ContentType)
    }

    if receivedMsg.FromDisplayName == "" {
        fmt.Println("received empty FromDisplayName: aborting send")
        return errors.New("received empty FromDisplayName: aborting send")

    }
    fromWithoutWhiteSpaces := strings.Join(strings.Fields(receivedMsg.FromDisplayName), "")


    mail.From = fromWithoutWhiteSpaces+"@dont-reply.com"
    mail.To = receivedMsg.To
    mail.Bcc = receivedMsg.Bcc
    mail.Cc = receivedMsg.Cc
    mail.Subject = receivedMsg.Subject
    if receivedMsg.IsHtmlBody {
        mail.HTML = []byte(receivedMsg.Body)
    }else {
        mail.Text = []byte(receivedMsg.Body)
    }


    err := mail.Send(emailGlobals.SmtpConf.Body[0].Value.Host+":587", smtp.PlainAuth("", emailGlobals.SmtpConf.Body[0].Value.Username, emailGlobals.SmtpConf.Body[0].Value.Password, emailGlobals.SmtpConf.Body[0].Value.Host))
    if err != nil {
        return err
    }
}

编辑:

已解决

感谢@Steffen Ullrich 的评论 因为在我的 json 中,图像内容已经进行了 base64 编码,并且库将在其之上放置另一个 base64 层,所以我必须首先像这样对其进行 base64 解码:

func EmailServiceBusinessLogic(receivedMsg emailModels.ReceivedMsgModel) error {

    mail := email.NewEmail()

    for _, v := range receivedMsg.Attachments {
        if v.FileName == "" {
            fmt.Println("received empty file name for attachment")
            continue
        }
        if v.Cid == "" {
            fmt.Println("received empty cid for file name: ", v.FileName)
            continue
        }
        if v.ContentType == "" {
            fmt.Println("received empty ContentType for file name: ", v.FileName)
            continue
        }
        if v.Content == "" {
            fmt.Println("received empty Content for file name: ", v.FileName)
            continue
        }

        // Base64 Standard Decoding <-this is the part that was missing!!
        sDec, err := base64.StdEncoding.DecodeString(v.Content)
        if err != nil {
            fmt.Printf("Error decoding Content: %s ", err.Error())
            continue
        }

        mail.Attach(strings.NewReader(string(sDec)), v.Cid, v.ContentType)
    }

    if receivedMsg.FromDisplayName == "" {
        fmt.Println("received empty FromDisplayName: aborting send")
        return errors.New("received empty FromDisplayName: aborting send")

    }
    fromWithoutWhiteSpaces := strings.Join(strings.Fields(receivedMsg.FromDisplayName), "")

    mail.From = fromWithoutWhiteSpaces + "@dont-reply.com"
    mail.To = receivedMsg.To
    mail.Bcc = receivedMsg.Bcc
    mail.Cc = receivedMsg.Cc
    mail.Subject = receivedMsg.Subject
    if receivedMsg.IsHtmlBody {
        mail.HTML = []byte(receivedMsg.Body)
    } else {
        mail.Text = []byte(receivedMsg.Body)
    }

    err := mail.Send(emailGlobals.SmtpConf.Body[0].Value.Host+":587", smtp.PlainAuth("", emailGlobals.SmtpConf.Body[0].Value.Username, emailGlobals.SmtpConf.Body[0].Value.Password, emailGlobals.SmtpConf.Body[0].Value.Host))
    if err != nil {
        return err
    }
}

要从 HTML 中引用附加图像,它必须有一个 Content-Id,即在 HTML 中它需要看起来像这样:

`<img src="cid:000001.png">

查看 "github.com/jordan-wright/emailAttach 的来源,我假设你使用它表明它是 using the given filename as Content-Id:

func (e *Email) Attach(r io.Reader, filename string, c string) (a *Attachment, err error) {
    ....
    at.Header.Set("Content-ID", fmt.Sprintf("<%s>", filename))

因此,请确保您用作附件名称的 v.FileName 实际上用作 HTML 部分中的 cid


在问题中添加了更多信息后:

... the only information i have regarding the attachments is: file name, content(string), content type(image/png) and contentDisposition atribute set to inline and cid

在这种情况下,您输入 cid 而不是文件名。


在问题中添加了更多信息:

have the following msg which i receive in my golang handler:

{"fromDisplayName":"Forg...

看起来您的图像已经进行了 base64 编码,但是您使用的库进行了额外的 base64 编码,因此您必须先对其进行解码。此外,该库明确使用 multipart/mixedContent-Type,但它必须是 multipart/related,以便图像与 HTML.

相关联

以下代码对我有用,你问题中的 JSON 存储为 mail.json。请注意,为了专注于解决方案,我在几个地方省略了错误检查。而且我不直接发送邮件,而是仅将其存储为字符串,以将其存储为 EML 文件并进行检查。您可能需要更改 Bytes function 以直接在此处设置 multipart/related

package main

import (
    "github.com/jordan-wright/email"
    "encoding/json"
    "encoding/base64"
    "fmt"
    "os"
    "bytes"
    "strings"
)

type Attachments struct {
    Filename string `json:"filename"`
    Content string `json:"content"`
    ContentType string `json:"contentType"`
    ContentDisposition string `json:"contentDisposition"`
    Cid string `json:"cid"`
}

type Mail struct {
    To []string `json:"to"`
    Subject string `json:"subject"`
    Body string `json:"body"`
    Parts []Attachments `json:"attachments"`
}

func main() {
    f,_ := os.Open("mail.json")
    d := json.NewDecoder(f)
    m := &Mail{}
    d.Decode(&m)
    // fmt.Println(m)

    e := email.NewEmail()
    e.To = m.To
    e.Subject = m.Subject
    e.HTML = []byte(m.Body)
    for _,p := range m.Parts {
        s,_ := base64.StdEncoding.DecodeString(string(p.Content))
        e.Attach(bytes.NewReader(s), p.Cid, p.ContentType)
    }
    s,_ := e.Bytes()
    mail := strings.Replace(string(s),": multipart/mixed;",": multipart/related;",1)
    fmt.Println(mail)
}