Golang發送郵件

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
package mainimport (   "bytes"   "crypto/tls"   "encoding/base64"   "errors"   "fmt"   "io"   "mime"   "mime/multipart"   "mime/quotedprintable"   "net/smtp"   "net/textproto"   "os"   "path/filepath"   "strings")const MemMaxSize = (1 << 20) * 10func SendMail(from, to, pw, subject, content, contentType, attach, host string) error {   var x = &Email{      From: from,      To: to,      Subject: subject,      Content: content,      Attachments: attach,      Type: contentType,   }   size, err := x.Len()   if err != nil {      return err   }   var file io.ReadWriter   if size >= MemMaxSize {      temp := fmt.Sprintf(".%d.tmp", os.Getpid())      file, err = os.Create(temp)      if err != nil {         return err      }      defer os.Remove(temp)   } else {      file = bytes.NewBuffer(make([]byte, 0, size))   }   x.Writer(file)   addr := strings.Split(host, ":")   if len(addr) != 2 {      return errors.New("host must be host:port")   }   auth := smtp.PlainAuth("", from, pw, addr[0])   err = Send(*x, host, auth, file)   if err != nil {      return err   }   if c, ok := file.(io.Closer); ok {      c.Close()   }   return nil}//發送訊息func Send(msg Email, addr string, auth smtp.Auth, body io.Reader) error {   to := strings.Split(msg.To, ",")   if msg.From == "" || len(to) == 0 {      return errors.New("Must specify at least one From address and one To address")   }   client, err := smtp.Dial(addr)   if err != nil {      return err   }   defer client.Close()   host := strings.Split(addr, ":")[0]   if err = client.Hello(host); err != nil {      return err   }   if ok, _ := client.Extension("STARTTLS"); ok {      config := &tls.Config{ServerName: host}      if err = client.StartTLS(config); err != nil {         return err      }   }   if err = client.Auth(auth); err != nil {      return err   }   if err = client.Mail(msg.From); err != nil {      return err   }   for _, addr := range to {      if err = client.Rcpt(addr); err != nil {         return err      }   }   w, err := client.Data()   if err != nil {      return err   }   if value, ok := body.(io.Seeker); ok {      value.Seek(0, 0)   }   _, err = io.Copy(w, body)   if err != nil {      return err   }   err = w.Close()   if err != nil {      return err   }   return client.Quit()}//添加附件func Attach(w *multipart.Writer, filename string) (err error) {   typ := mime.TypeByExtension(filepath.Ext(filename))   var Header = make(textproto.MIMEHeader)   if typ != "" {      Header.Set("Content-Type", typ)   } else {      Header.Set("Content-Type", "application/octet-stream")   }   basename := filepath.Base(filename)   Header.Set("Content-Disposition", fmt.Sprintf("attachment;\r\n filename=\"%s\"", basename))   Header.Set("Content-ID", fmt.Sprintf("<%s>", basename))   Header.Set("Content-Transfer-Encoding", "base64")   File, err := os.Open(filename)   if err != nil {      return err   }   defer File.Close()   mw, err := w.CreatePart(Header)   if err != nil {      return err   }   return base64Wrap(mw, File)}type Email struct {   From        string   To          string   Subject     string   Content     string   ContentPath string   Type        string   Attachments string}//返回基礎的頭資訊func (e *Email) Headers() (textproto.MIMEHeader, error) {   res := make(textproto.MIMEHeader)   if _, ok := res["To"]; !ok && len(e.To) > 0 {      res.Set("To", e.To)   }   if _, ok := res["Subject"]; !ok && e.Subject != "" {      res.Set("Subject", e.Subject)   }   if _, ok := res["From"]; !ok {      res.Set("From", e.From)   }   return res, nil}//編碼郵件內容func (e *Email) Writer(datawriter io.Writer) error {   headers, err := e.Headers()   if err != nil {      return err   }   w := multipart.NewWriter(datawriter)   headers.Set("Content-Type", "multipart/mixed;\r\n boundary="+w.Boundary())   headerToBytes(datawriter, headers)   io.WriteString(datawriter, "\r\n")   fmt.Fprintf(datawriter, "--%s\r\n", w.Boundary())   header := textproto.MIMEHeader{}   if e.Content != "" || e.ContentPath != "" {      subWriter := multipart.NewWriter(datawriter)      header.Set("Content-Type", fmt.Sprintf("multipart/alternative;\r\n boundary=%s\r\n", subWriter.Boundary()))      headerToBytes(datawriter, header)      if e.Content != "" {         header.Set("Content-Type", fmt.Sprintf("text/%s; charset=UTF-8", e.Type))         header.Set("Content-Transfer-Encoding", "quoted-printable")         if _, err := subWriter.CreatePart(header); err != nil {            return err         }         qp := quotedprintable.NewWriter(datawriter)         if _, err := qp.Write([]byte(e.Content)); err != nil {            return err         }         if err := qp.Close(); err != nil {            return err         }      } else {         header.Set("Content-Type", fmt.Sprintf("text/%s; charset=UTF-8", e.Type))         header.Set("Content-Transfer-Encoding", "quoted-printable")         if _, err := subWriter.CreatePart(header); err != nil {            return err         }         qp := quotedprintable.NewWriter(datawriter)         File, err := os.Open(e.ContentPath)         if err != nil {            return err         }         defer File.Close()         _, err = io.Copy(qp, File)         if err != nil {            return err         }         if err := qp.Close(); err != nil {            return err         }      }      if err := subWriter.Close(); err != nil {         return err      }   }   if e.Attachments != "" {      list := strings.Split(e.Attachments, ",")      for _, path := range list {         err = Attach(w, path)         if err != nil {            w.Close()            return err         }      }   }   return nil}//查看一下發送的內容大小,如果過超過一定大小則,使用磁碟檔案做臨時func (e *Email) Len() (int64, error) {   var l int64   if e.Content != "" {      l += int64(len(e.Content))   } else {      stat, err := os.Lstat(e.ContentPath)      if err != nil {         return 0, err      }      l += stat.Size()   }   if e.Attachments != "" {      for _, path := range strings.Split(e.Attachments, ",") {         stat, err := os.Lstat(path)         if err != nil {            return 0, err         }         l += stat.Size()      }   }   return l, nil}//根據頭資訊建立附件func headerToBytes(w io.Writer, header textproto.MIMEHeader) {   for field, vals := range header {      for _, subval := range vals {         io.WriteString(w, field)         io.WriteString(w, ": ")         switch {         case field == "Content-Type" || field == "Content-Disposition":            w.Write([]byte(subval))         default:            w.Write([]byte(mime.QEncoding.Encode("UTF-8", subval)))         }         io.WriteString(w, "\r\n")      }   }}//編碼成每行固定長度的base64訊息func base64Wrap(w io.Writer, r io.Reader) error {   const maxRaw = 57   const MaxLineLength = 76   buffer := make([]byte, MaxLineLength+len("\r\n"))   copy(buffer[MaxLineLength:], "\r\n")   var b = make([]byte, maxRaw)   for {      n, err := r.Read(b)      if err != nil {         if err == io.EOF {            return nil         }         return err      }      if n == maxRaw {         base64.StdEncoding.Encode(buffer, b[:n])         w.Write(buffer)      } else {         out := buffer[:base64.StdEncoding.EncodedLen(len(b))]         base64.StdEncoding.Encode(out, b)         out = append(out, "\r\n"...)         w.Write(out)      }   }}
func main() {   var from string = "XXXXXXXX@qq.com"   var to string = "XXXXXXXXX@qq.com"   var pw string = "XXXXXXXXXXXXXX"   var subject string = "Test"   var content string = "郵件內文"   var cType string = "plain"   var attach string = "/path/test.xlsx"   var host string = "smtp.qq.com:25"   err := SendMail(from, to, pw, subject, content, cType, attach, host)   if err != nil {      fmt.Println(err)   } else {      fmt.Println("發送成功!!!")   }}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.