阿里云邮件推送服务


阿里云邮件推送服务

定义

在邮箱注册,邮箱验证或者邮箱发送通知的时候,就需要用到邮箱推送服务来实现。邮箱推送除了各个平台的sdk之外,基于stmp协议的写法更加的灵活

Golang
// 邮箱信息 type SendMail struct { User string // 发件人 “xxx.@163.com” Password string // smtp的密码 Host string // smtpdm.aliyun.com 使用了阿里云的服务 Port string // 80 SmtpAuth smtp.Auth } // 附件 type Attachment struct { Name string // 附件名 FileUrl string // 附件地址 ContentType string // text/html;charset=utf-8 WithFile bool // true } // 邮件信息 type Message struct { From string // 发件人名 FromAlias string // 发件人别名 To []string // 收件人邮箱列表 Cc []string // Bcc []string Subject string // 邮件标题 Body string // 邮件内容 ReplyTo string // 回件地址 ContentType string // text/html;charset=utf-8 (body为html格式) Attachments []Attachment // 附件 TagName string // aliyun邮件追踪,通过tagName统计邮件数据 } func (mail *SendMail) Auth() { mail.SmtpAuth = LoginAuth(mail.User, mail.Password) } func (mail SendMail) Send(message Message) error { mail.Auth() buffer := bytes.NewBuffer(nil) boundary := "GoBoundary" Header := make(map[string]string) Header["From"] = fmt.Sprintf("(%s)<%s>", message.FromAlias, message.From) Header["To"] = strings.Join(message.To, ";") Header["Cc"] = strings.Join(message.Cc, ";") Header["Bcc"] = strings.Join(message.Bcc, ";") Header["Subject"] = mime.BEncoding.Encode("UTF-8", message.Subject) Header["Reply-To"] = message.ReplyTo Header["Content-Type"] = "multipart/mixed;boundary=" + boundary Header["Mime-Version"] = "1.0" Header["Date"] = time.Now().String() trace := make(map[string]string) trace["OpenTrace"] = "1" trace["LinkTrace"] = "1" trace["TagName"] = message.TagName traceString, err := utils.JSONMarshal(trace) if err != nil { return err } Header["X-AliDM-Trace"] = base64.StdEncoding.EncodeToString(traceString) mail.writeHeader(buffer, Header) body := "\r\n--" + boundary + "\r\n" body += "Content-Type:" + message.ContentType + "\r\n" body += "\r\n" + message.Body + "\r\n" buffer.WriteString(body) if len(message.Attachments) > 0 { attachment := "\r\n--" + boundary + "\r\n" attachment += "Content-Transfer-Encoding:base64\r\n" attachment += "Content-Disposition:attachment\r\n" for _, messageAttachment := range message.Attachments { if messageAttachment.WithFile { attachment += "Content-Type:" + messageAttachment.ContentType + ";name=\"" + mime.BEncoding.Encode("UTF-8", messageAttachment.Name) + "\"\r\n" buffer.WriteString(attachment) defer func() { if err := recover(); err != nil { log.Fatalln(err) } }() err := mail.writeFile(buffer, messageAttachment.FileUrl) if err != nil { return err } } } } to_address := MergeSlice(message.To, message.Cc) to_address = MergeSlice(to_address, message.Bcc) buffer.WriteString("\r\n--" + boundary + "--") err = smtp.SendMail(mail.Host+":"+mail.Port, mail.SmtpAuth, message.From, to_address, buffer.Bytes()) return err } func MergeSlice(s1 []string, s2 []string) []string { slice := make([]string, len(s1)+len(s2)) copy(slice, s1) copy(slice[len(s1):], s2) return slice } 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 } // read and write the file to buffer func (mail SendMail) writeFile(buffer *bytes.Buffer, fileUrl string) error { filePath := fmt.Sprintf("/tmp/files/%s", utils.MD5(fileUrl)+utils.UUID()) defer os.Remove(filePath) err := utils.DownloadFile(filePath, fileUrl) if err != nil { return err } file, err := ioutil.ReadFile(filePath) 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") } } return nil } type loginAuth struct { username, password string } func LoginAuth(username, password string) smtp.Auth { return &loginAuth{username, password} } func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { return "LOGIN", []byte(a.username), nil } func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { if more { switch string(fromServer) { case "Username:": return []byte(a.username), nil case "Password:": return []byte(a.password), nil } } return nil, nil }

调用

var mail smtpMail.Mail
mail = &smtpMail.SendMail{User: EMAIL_USER, Password: EMAIL_SMTP_PWD, Host: EMAIL_HOST, Port: EMAIL_PORT}

var attachments []smtpMail.Attachment
attachments = append(attachments, smtp_mail.Attachment{
	Name:        "附件名",
	FileUrl:     "xxx附件地址",
	WithFile:    true,
	ContentType: "text/html;charset=utf-8",
})

message := smtp_mail.Message{
	From:        EMAIL_USER,
	FromAlias:   EMAIL_USER_ALIAS,
	ReplyTo:     strategy.ReplyTo,
	To:          []string{author.Email},
	Subject:     subject,
	Body:        body,
	ContentType: "text/html;charset=utf-8",
	Attachments: attachments,
	TagName:     getEmailSendStrategyTagName(strategy.ID),
}

err = mail.Send(message)

文章作者: Wanheng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wanheng !
评论
  目录