golang 使用ssl连接smtp发送邮件

发送邮件的流程是,先有一个邮件发送器,然后才能发邮件。对于发送器,可以用qq来申请成可以发邮件测试代码

https://jingyan.baidu.com/article/4b07be3cb2f74148b380f3e4.html

邮件SMTP的几个端口: 

25:smtp是服务器用来接收和发送邮件的,客户端来发送邮件的。(这个端口是不能更改的) 
110:是pop客户端用来接收邮件的 
143:imap客户端用来接收邮件的 
993:imap的加密端口 
465:smtp的加密端口用来发送邮件的 
587:另外的smtp端口也是用来发送邮件的 
995:pop的加密端口客户端用来接收邮件的 
2525:这个不是一个SMTP端口,有时候会用来代替587端口 

另外网页收发邮件,一般是http 80端口,可以改成其他的

邮件发送方式有:ssl加密方式  tsl加密方式

参考网址:https://my.oschina.net/u/3768573/blog/1607327

这里面ssl的例子用我公司企业号之后,死活不成功。原来ssl方式加密默认是需要证书的,如果没有证书则需要调过证书认证。就因为一个参数,废了一天真是醉了。

 

package main

import (
   "fmt"
   "net/smtp"
   "crypto/tls"
   "net"
)

func main() {
   host := "mail.xx.com:465"
   email  := "admin@xxx"
   pwd := "xxxx"  // 这里填你的授权码
   toEmail := "[email protected]"  // 目标地址

/* host :="smtp.qq.com:465"
   email  := "[email protected]"
   pwd := "yxxx"  // 这里填你的授权码
   toEmail := "[email protected]"  // 目标地址*/

   header   :=  make(map[string]string)
   header["From"] = "test"+"<" +email+">"
   header["To"] = toEmail
   header["Subject"] = "邮件标题11111"
   header["Content-Type"] = "text/html;chartset=UTF-8"
   message := ""
   body  := "这是一封golang发来的邮件"
   for k,v :=range header{
      message  += fmt.Sprintf("%s:%s\r\n",k,v)
   }
   message +="\r\n"+body

   auth := smtp.PlainAuth("", email, pwd, host)
   fmt.Println("AUTH:",auth)
  /*err := smtp.SendMail(host,auth,email,[]string{toEmail},[]byte(message))
   if err  != nil{
      fmt.Println("发送失败:",err)
      return
   }*/
   err := SendMailUsingTLS(
      host,
      auth,
      email,
      []string{toEmail},
      []byte(message),
   )
   if err  != nil{
      fmt.Println("发送失败:",err)
      return
   }
   return
}
//return a smtp client
func Dial(addr string) (*smtp.Client, error) {
   //todo 没有就跳过证书,需要参数 &tls.Config{InsecureSkipVerify:true}
    conn, err := tls.Dial("tcp",addr, nil)
  
 // conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify:true})
 if err != nil {      
fmt.Println("Dialing Error:", err)
 
   return nil, err
   }
   //分解主机端口字符串
   host, _, _ := net.SplitHostPort(addr)
   return smtp.NewClient(conn, host)
}

//参考net/smtp的func SendMail()
//使用net.Dial连接tls(ssl)端口时,smtp.NewClient()会卡住且不提示err
//len(to)>1时,to[1]开始提示是密送
func SendMailUsingTLS(addr string, auth smtp.Auth, from string,
   to []string, msg []byte) (err error) {
   fmt.Println("start SendMailUsingTLS... ")
   //create smtp client
   c, err := Dial(addr)
   fmt.Println("c:",c)
   if err != nil {
      fmt.Println("Create smpt client error:", err)
      return err
   }
   defer c.Close()
   if auth != nil {
      if ok, param := c.Extension("AUTH"); ok {
         fmt.Println("ok:", ok)
         fmt.Println("param:", param)
         if err = c.Auth(auth); err != nil {
            fmt.Println("Error during AUTH:", err)
            return err
         }
      }
   }
   if err = c.Mail(from); err != nil {
      fmt.Println(err)
      return err
   }

   for _, addr := range to {
      if err = c.Rcpt(addr); err != nil {
         fmt.Println(err)
         return err
      }
   }

   w, err := c.Data()
   if err != nil {
      fmt.Println(err)
      return err
   }

   _, err = w.Write(msg)
   if err != nil {
      fmt.Println(err)
      return err
   }

   err = w.Close()
   if err != nil {
      fmt.Println(err)
      return err
   }
   return c.Quit()
}   
 
 

 

 
刚开始我使用qq号开通来发送邮件,很顺利。网上随便一搜都是。如下:
  func main(){
m := gomail.NewMessage()
str := "[email protected],[email protected]" 
m.SetAddressHeader("From", "[email protected]", "发件人") // 发件人
 m.SetHeader("To", // 收件人
 strings.Split(str, ",")...) 
m.SetHeader("Subject", "Gomail") // 主题 
m.SetBody("text/html", "Hello test") // 正文 d := gomail.NewPlainDialer("smtp.qq.com", 465, "[email protected]", "gvjvblygnadudeac") //d := gomail.NewPlainDialer("mail.xxxx.com", 465, "[email protected]", "xxx") // 发送邮件服务器、端口、发件人账号、发件人密码 
if err := d.DialAndSend(m); err != nil 
{ panic(err)
 }}

 

后来需要使用模板来发送,这个时候又找到了模板的参考案例:

 

package main

import (
   "encoding/json"
   "fmt"
   "github.com/alecthomas/template"
   "os"
)

func main() {
   Alarm := `{"aid":122,"count":1}`
   alarm := make(map[string]interface{}, 0)
   err := json.Unmarshal([]byte(Alarm), &alarm)
   if err != nil {
      fmt.Println(err)
   }
   muban1 := `hi, {{template "aid"}}`
   tmpl, err := template.New("ONE").Parse(muban1)
   if err != nil {
      panic(err)
   }
   for k, v := range alarm {
      str, _ := json.Marshal(v)
      tmpl.New(k).Parse(string(str))
   }
   err = tmpl.Execute(os.Stdout, nil)
   if err != nil {
      panic(err)
   }
   return

}

通过两者结合,出来一个发邮件的函数

 

package common

import (
   "encoding/json"
   "net/smtp"
   "fmt"
   "bytes"
   "strings"
   "github.com/alecthomas/template"
   log "github.com/cihub/seelog"
   "strconv"
)

//通过发送器发送邮件
func SendEmailBySender(serverAddr, username ,password string,receiveAddr ,tem ,subject string,a []byte)(err error )  {
   bods := new(bytes.Buffer)
   var emails = make([]string ,0)
   con := strings.Split(serverAddr,":")
   auth := smtp.PlainAuth("",username,password,con[0])
   email := strings.Split(receiveAddr,",")
   for _,v := range email{
      emails = append(emails,v)
   }
   alarm := make(map[string]interface{}, 0)
   err = json.Unmarshal(a,&alarm)
   if err != nil {
      fmt.Println(err)
   }
   tmpl, err := template.New("template").Parse(tem)
   if err != nil {
      fmt.Println("tmpl err : ",tmpl)
      return
   }
   fmt.Println("发邮件之前接收的告警信息 :",alarm)
   for k,v := range alarm{
      str ,err := json.Marshal(v)
      if err != nil {
         log.Infof("json.Marshal err (%s)",err)
      }
      a,err  := strconv.Unquote( string(str))
      if err != nil {
         tmpl.New(k).Parse(string(str))
      }
      tmpl.New(k).Parse(a)
   }
   err = tmpl.Execute(bods, nil)
   if err != nil {
      panic(err)
   }
   content_type := "Content-Type:text/html;charset=utf-8"
   msg := []byte("To:" + receiveAddr  + "\r\nFrom:"+ username + "\r\nSubject:"+ subject + "\r\n" + content_type +  "\r\n\r\n"+ bods.String())
   err  = smtp.SendMail(serverAddr, auth, username, emails, msg)
   if err != nil{
      log.Errorf("发送邮件错误!err (%s)",err)
      return err
   }else{
      log.Infof("邮件发送成功")
      return
   }
   return
}

 

 

 

 

 

 

你可能感兴趣的:(golang笔记)