全部产品
云市场

SMTP 之 Go 调用示例

更新时间:2018-12-04 12:21:41

使用 Go 语言通过 SMTP 发送邮件,go语言的版本为1.9

  1. package main
  2. import (
  3. "fmt"
  4. "net/smtp"
  5. "strings"
  6. )
  7. func SendToMail(user, password, host, subject, body, mailtype, replyToAddress string, to, cc, bcc []string) error {
  8. hp := strings.Split(host, ":")
  9. auth := smtp.PlainAuth("", user, password, hp[0])
  10. var content_type string
  11. if mailtype == "html" {
  12. content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
  13. } else {
  14. content_type = "Content-Type: text/plain" + "; charset=UTF-8"
  15. }
  16. cc_address := strings.Join(cc, ";")
  17. bcc_address := strings.Join(bcc, ";")
  18. to_address := strings.Join(to, ";")
  19. msg := []byte("To: " + to_address + "\r\nFrom: " + user + "\r\nSubject: " + subject + "\r\nReply-To: " + replyToAddress + "\r\nCc: " + cc_address + "\r\nBcc: " + bcc_address + "\r\n" + content_type + "\r\n\r\n" + body)
  20. send_to := MergeSlice(to, cc)
  21. send_to = MergeSlice(send_to, bcc)
  22. err := smtp.SendMail(host, auth, user, send_to, msg)
  23. return err
  24. }
  25. func main() {
  26. user := "控制台创建的发信地址"
  27. password := "控制台设置的SMTP密码"
  28. host := "smtpdm.aliyun.com:25"
  29. to := []string{"收件人地址","收件人地址1"}
  30. cc := []string{"抄送地址","抄送地址1"}
  31. bcc := []string{"密送地址","密送地址1"}
  32. subject := "test Golang to sendmail"
  33. mailtype :="html"
  34. replyToAddress:="***@xxx.com"
  35. body := `
  36. <html>
  37. <body>
  38. <h3>
  39. "Test send to email"
  40. </h3>
  41. </body>
  42. </html>
  43. `
  44. fmt.Println("send email")
  45. err := SendToMail(user, password, host, subject, body, mailtype, replyToAddress, to, cc, bcc)
  46. if err != nil {
  47. fmt.Println("Send mail error!")
  48. fmt.Println(err)
  49. } else {
  50. fmt.Println("Send mail success!")
  51. }
  52. }
  53. func MergeSlice(s1 []string, s2 []string) []string {
  54. slice := make([]string, len(s1)+len(s2))
  55. copy(slice, s1)
  56. copy(slice[len(s1):], s2)
  57. return slice
  58. }

如果go语言的版本为1.9.2,出现错误提示:“unencrypted connection”,因为此版本需要加密认证,可采用LOGIN认证,则需要增加以下内容:

  1. type loginAuth struct {
  2. username, password string
  3. }
  4. func LoginAuth(username, password string) smtp.Auth {
  5. return &loginAuth{username, password}
  6. }
  7. func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
  8. // return "LOGIN", []byte{}, nil
  9. return "LOGIN", []byte(a.username), nil
  10. }
  11. func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
  12. if more {
  13. switch string(fromServer) {
  14. case "Username:":
  15. return []byte(a.username), nil
  16. case "Password:":
  17. return []byte(a.password), nil
  18. }
  19. }
  20. return nil, nil
  21. }

修改对应的调用方式:

  1. auth := LoginAuth(user, password)

使用465端,请参考:

  1. package main
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "log"
  6. "net"
  7. "net/smtp"
  8. )
  9. func main() {
  10. host := "smtpdm.aliyun.com"
  11. port := 465
  12. email := "xxx@xxx.com"
  13. password := "TExxxxxst"
  14. toEmail := "xxx@xxxxx.com"
  15. header := make(map[string]string)
  16. header["From"] = "test" + "<" + email + ">"
  17. header["To"] = toEmail
  18. header["Subject"] = "邮件标题"
  19. header["Content-Type"] = "text/html; charset=UTF-8"
  20. body := "我是一封测试电子邮件!"
  21. message := ""
  22. for k, v := range header {
  23. message += fmt.Sprintf("%s: %s\r\n", k, v)
  24. }
  25. message += "\r\n" + body
  26. auth := smtp.PlainAuth(
  27. "",
  28. email,
  29. password,
  30. host,
  31. )
  32. err := SendMailUsingTLS(
  33. fmt.Sprintf("%s:%d", host, port),
  34. auth,
  35. email,
  36. []string{toEmail},
  37. []byte(message),
  38. )
  39. if err != nil {
  40. panic(err)
  41. } else {
  42. fmt.Println("Send mail success!")
  43. }
  44. }
  45. //return a smtp client
  46. func Dial(addr string) (*smtp.Client, error) {
  47. conn, err := tls.Dial("tcp", addr, nil)
  48. if err != nil {
  49. log.Println("Dialing Error:", err)
  50. return nil, err
  51. }
  52. //分解主机端口字符串
  53. host, _, _ := net.SplitHostPort(addr)
  54. return smtp.NewClient(conn, host)
  55. }
  56. //参考net/smtp的func SendMail()
  57. //使用net.Dial连接tls(ssl)端口时,smtp.NewClient()会卡住且不提示err
  58. //len(to)>1时,to[1]开始提示是密送
  59. func SendMailUsingTLS(addr string, auth smtp.Auth, from string,
  60. to []string, msg []byte) (err error) {
  61. //create smtp client
  62. c, err := Dial(addr)
  63. if err != nil {
  64. log.Println("Create smpt client error:", err)
  65. return err
  66. }
  67. defer c.Close()
  68. if auth != nil {
  69. if ok, _ := c.Extension("AUTH"); ok {
  70. if err = c.Auth(auth); err != nil {
  71. log.Println("Error during AUTH", err)
  72. return err
  73. }
  74. }
  75. }
  76. if err = c.Mail(from); err != nil {
  77. return err
  78. }
  79. for _, addr := range to {
  80. if err = c.Rcpt(addr); err != nil {
  81. return err
  82. }
  83. }
  84. w, err := c.Data()
  85. if err != nil {
  86. return err
  87. }
  88. _, err = w.Write(msg)
  89. if err != nil {
  90. return err
  91. }
  92. err = w.Close()
  93. if err != nil {
  94. return err
  95. }
  96. return c.Quit()
  97. }