Golang 通过net/smtp发送邮件 在正文中添加图片(附件/非附件)

背景

遇到一个需求 需要发送带有图片的邮件
于是参考:http://www.cnblogs.com/zengchunyun/p/9485444.html
完成了带图片附件的邮件发送功能
但是!!
产品竟然说 图片需要在正文里!!正文!! 个人觉得在附件里很好呀0.0



**尝试**

产品说什么就是什么吧。。
于是疯狂尝试怎么把图片从附件里显示到正文当中

multipart类型,有三种子类型:mixed、alternative、related
multipart/mixed可以包含附件。
multipart/related可以包含内嵌资源。
multipart/alternative 纯文本与超文本共存
multipart可以发送若干个内容 并使用boundary来分割

一开始以为是mixed的缘故 改成了related
但是一点都没用。。该在附件里的还是出现在了附件了

最后自己本地发邮件抓包 发现了原来可以发送html格式的邮件 把图片放到‘’img‘’中来实现正文中添加图片的功能

废话不多说 上代码



**代码** ```golang package main

import (
“bytes”
“encoding/base64”
“fmt”
“io/ioutil”
“net/smtp”
“strings”
“time”
)

type SendMail struct {
user string
password string
host string
port string
auth smtp.Auth
}

type Attachment struct {
name []string
contentType string
withFile bool
}

type Message struct {
from string
to []string
cc []string
bcc []string
subject string
body string
contentType string
attachment Attachment
}

func (mail *SendMail) Auth() {
mail.auth = smtp.PlainAuth("", mail.user, mail.password, mail.host)
}

func (mail SendMail) Send(message Message) error {
mail.Auth()
buffer := bytes.NewBuffer(nil)
boundary := “GoBoundary”
Header := make(map[string]string)
Header[“From”] = message.from
Header[“To”] = strings.Join(message.to, “;”)
Header[“Cc”] = strings.Join(message.cc, “;”)
Header[“Bcc”] = strings.Join(message.bcc, “;”)
Header[“Subject”] = message.subject
Header[“Content-Type”] = “multipart/related;boundary=” + boundary
Header[“Date”] = time.Now().String()
mail.writeHeader(buffer, Header)

var imgsrc string
if message.attachment.withFile {
	//多图片发送
	for _, graphname := range message.attachment.name {
		attachment := "\r\n--" + boundary + "\r\n"
		attachment += "Content-Transfer-Encoding:base64\r\n"
		attachment += "Content-Type:" + message.attachment.contentType + ";name=\"" + graphname + "\"\r\n"
		attachment += "Content-ID: <" + graphname + "> \r\n\r\n"
		buffer.WriteString(attachment)
		
		//拼接成html
		imgsrc += "<p><img src=\"cid:" + graphname + "\" height=200 width=300></p><br>\r\n\t\t\t"

		defer func() {
			if err := recover(); err != nil {
				fmt.Printf(err.(string))
			}
		}()
		mail.writeFile(buffer, graphname)
	}
}

//需要在正文中显示的html格式
var template = `
<html>
	<body>
		<p>text:%s</p><br>
		%s			
	</body>
</html>
`
var content = fmt.Sprintf(template, message.body, imgsrc)
body := "\r\n--" + boundary + "\r\n"
body += "Content-Type: text/html; charset=UTF-8 \r\n"
body += content
buffer.WriteString(body)

buffer.WriteString("\r\n--" + boundary + "--")
fmt.Println(buffer.String())
smtp.SendMail(mail.host+":"+mail.port, mail.auth, message.from, message.to, buffer.Bytes())
return nil

}

func (mail SendMail) writeHeader(buffer *bytes.Buffer, Header map[string]string) string {
header := “”
for key, value := range Header {
header += key + “:” + value + “\r\n”
}
header += “\r\n”
buffer.WriteString(header)
return header
}

func (mail SendMail) writeFile(buffer *bytes.Buffer, fileName string) {
file, err := ioutil.ReadFile(fileName)
if err != nil {
panic(err.Error())
}
payload := make([]byte, base64.StdEncoding.EncodedLen(len(file)))
base64.StdEncoding.Encode(payload, file)
buffer.WriteString("\r\n")
for index, line := 0, len(payload); index < line; index++ {
buffer.WriteByte(payload[index])
if (index+1)%76 == 0 {
buffer.WriteString("\r\n")
}
}
}

func main() {
mail := &SendMail{user: “mailaddr1@qq.com”, password: “password”, host: “smtp.qq.com”, port: “25”}
message := Message{
from: “mailaddr1@qq.com”,
to: []string{“mailaddr2@qq.com”},
cc: []string{},
bcc: []string{},
subject: “test”, //邮件标题
body: “msg body!”, //正文内容
contentType: “text/plain;charset=utf-8”,
attachment: Attachment{
name: []string{“1.png”}, //可以放入多张图片
contentType: “image/png”,
withFile: true,
},
}
mail.Send(message)
}



下面再附上最终组合成的发送格式:

From:mailaddr1@qq.com
To:mailaddr2@qq.com
Cc:
Bcc:
Subject:test
Content-Type:multipart/related;boundary=GoBoundary
Date:2018-08-22 14:42:04.529271 +0800 CST m=+0.006003700

–GoBoundary
Content-Transfer-Encoding:base64
Content-Type:image/png;name=“1.png”
Content-ID: <1.png>

//图片base64编码内容 太长就不显示了

–GoBoundary
Content-Type: text/html; charset=UTF-8

<html>
	<body>
		<p>text:msg body!</p><br>
		<p><img src="cid:1.png" height=200 width=300></p><br>
					
	</body>
</html>

–GoBoundary–


----------
<br>
<font size=5>**总结**</font>

以上代码可以实现在正文中添加多张图片的功能
当然只要修改template 想怎么发送就怎么发送~~~

因为使用的是QQ邮箱 在password中填入QQ邮箱的授权码
![这里写图片描述](https://img-blog.csdn.net/20180822154151834?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3prdDI4NjQ2ODU0MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

这个方法是将图片按原先附件的方法添加
关键就是在之后的html中通过 <font color=red>**img src="cid:1.png"**</font>  来引用附件中的图片 从而在正文中显示
![这里写图片描述](https://img-blog.csdn.net/20180822154233620?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3prdDI4NjQ2ODU0MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


这只是我通过抓包发现的一种方法 总感觉有点麻烦
感觉应该存在其它更优的方法  希望能够一起交流 谢谢!!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值