golang的smtp發送實例

好久沒有更新博客了,來記錄一個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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章