好久沒有更新博客了,來記錄一個smtp的實例。
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: "[email protected]", password: "啦啦啦啦這個當然假的密碼", host: "smtp.qq.com", port: "25"}
message := Message{
from: "[email protected]",
to: []string{"[email protected]"},
cc: []string{},
bcc: []string{},
subject: "test", //郵件標題
body: "msg body!", //正文內容
contentType: "text/plain;charset=utf-8",
attachment: Attachment{
name: []string{"sin.png", "sin.png"}, //可以放入多張圖片
contentType: "image/png",
withFile: true,
},
}
mail.Send(message)
}
實例二:
package main
import (
"strings"
"github.com/go-gomail/gomail"
)
type EmailParam struct {
// ServerHost 郵箱服務器地址,如騰訊郵箱爲smtp.qq.com
ServerHost string
// ServerPort 郵箱服務器端口,如騰訊郵箱爲465
ServerPort int
// FromEmail 發件人郵箱地址
FromEmail string
// FromPasswd 發件人郵箱密碼(注意,這裏是明文形式),TODO:如果設置成密文?
FromPasswd string
// Toers 接收者郵件,如有多個,則以英文逗號(“,”)隔開,不能爲空
Toers string
// CCers 抄送者郵件,如有多個,則以英文逗號(“,”)隔開,可以爲空
CCers string
}
// 全局變量,因爲發件人賬號、密碼,需要在發送時才指定
// 注意,由於是小寫,外面的包無法使用
var serverHost, fromEmail, fromPasswd string
var serverPort int
var m *gomail.Message
func InitEmail(ep *EmailParam) {
toers := []string{}
serverHost = ep.ServerHost
serverPort = ep.ServerPort
fromEmail = ep.FromEmail
fromPasswd = ep.FromPasswd
m = gomail.NewMessage()
if len(ep.Toers) == 0 {
return
}
for _, tmp := range strings.Split(ep.Toers, ",") {
toers = append(toers, strings.TrimSpace(tmp))
}
// 收件人可以有多個,故用此方式
m.SetHeader("To", toers...)
//抄送列表
if len(ep.CCers) != 0 {
for _, tmp := range strings.Split(ep.CCers, ",") {
toers = append(toers, strings.TrimSpace(tmp))
}
m.SetHeader("Cc", toers...)
}
// 發件人
// 第三個參數爲發件人別名,如"李大錘",可以爲空(此時則爲郵箱名稱)
m.SetAddressHeader("From", fromEmail, "")
}
// SendEmail body支持html格式字符串
func SendEmail(subject, body string) {
// 主題
m.SetHeader("Subject", subject)
// 正文
m.SetBody("text/html", body)
d := gomail.NewPlainDialer(serverHost, serverPort, fromEmail, fromPasswd)
// 發送
err := d.DialAndSend(m)
if err != nil {
panic(err)
}
}
func main() {
serverHost := "smtp.qq.com"
serverPort := 25
fromEmail := "[email protected]" //發件人郵箱
fromPasswd := "啦啦啦啦這個當然假的密碼" //授權碼
myToers := "[email protected],[email protected],[email protected]" // 收件人郵箱,逗號隔開
myCCers := "" //"[email protected]"
subject := "這是主題"
body := `這是正文<br>
Hello <a href = "http://wwww.yqun.xyz/">gdl</a>`
// 結構體賦值
myEmail := &EmailParam{
ServerHost: serverHost,
ServerPort: serverPort,
FromEmail: fromEmail,
FromPasswd: fromPasswd,
Toers: myToers,
CCers: myCCers,
}
InitEmail(myEmail)
SendEmail(subject, body)
}
關於"github.com/go-gomail/gomail":
直接 go get github.com/go-gomail/gomail
然後你的GOPATH下面就有了
關於授權碼:
打開qq郵箱,然後->設置->自己看就好了
關於smtp協議和其擴展MIME直接rfc看官方文檔就大概瞭解了
http://www.360doc.com/content/13/0116/10/3200886_260466636.shtml