// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. // // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. // Package gsmtp provides a simple SMTP client to access remote mail server. // // Eg: // s := smtp.New("smtp.exmail.qq.com:25", "notify@a.com", "password") // glog.Println(s.SendMail("notify@a.com", "ulric@b.com;rain@c.com", "subject", "body, red")) package gsmtp import ( "encoding/base64" "fmt" "github.com/gogf/gf/util/gconv" "net/smtp" "strings" ) // SMTP is the structure for smtp connection type SMTP struct { Address string Username string Password string } // New creates and returns a new SMTP object. func New(address, username, password string) *SMTP { return &SMTP{ Address: address, Username: username, Password: password, } } var ( // contentEncoding is the BASE64 encoding object for mail content. contentEncoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") ) // SendMail connects to the server at addr, switches to TLS if // possible, authenticates with the optional mechanism a if possible, // and then sends an email from address , to addresses , with // message msg. // // The parameter specifies the content type of the mail, eg: html. func (s *SMTP) SendMail(from, tos, subject, body string, contentType ...string) error { var ( server = "" address = "" hp = strings.Split(s.Address, ":") ) if s.Address == "" || len(hp) > 2 { return fmt.Errorf("server address is either empty or incorrect: %s", s.Address) } else if len(hp) == 1 { server = s.Address address = server + ":25" } else if len(hp) == 2 { if (hp[0] == "") || (hp[1] == "") { return fmt.Errorf("server address is either empty or incorrect: %s", s.Address) } server = hp[0] address = s.Address } var ( tosArr []string arr = strings.Split(tos, ";") ) for _, to := range arr { // TODO: replace with regex if strings.Contains(to, "@") { tosArr = append(tosArr, to) } } if len(tosArr) == 0 { return fmt.Errorf("tos if invalid: %s", tos) } if !strings.Contains(from, "@") { return fmt.Errorf("from is invalid: %s", from) } header := map[string]string{ "From": from, "To": strings.Join(tosArr, ";"), "Subject": fmt.Sprintf("=?UTF-8?B?%s?=", contentEncoding.EncodeToString(gconv.UnsafeStrToBytes(subject))), "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "base64", } if len(contentType) > 0 && contentType[0] == "html" { header["Content-Type"] = "text/html; charset=UTF-8" } message := "" for k, v := range header { message += fmt.Sprintf("%s: %s\r\n", k, v) } message += "\r\n" + contentEncoding.EncodeToString(gconv.UnsafeStrToBytes(body)) return smtp.SendMail( address, smtp.PlainAuth("", s.Username, s.Password, server), from, tosArr, gconv.UnsafeStrToBytes(message), ) }