github.com/gogf/gf@v1.16.9/net/gsmtp/gsmtp.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  // Package gsmtp provides a simple SMTP client to access remote mail server.
     8  //
     9  // Eg:
    10  // s := smtp.New("smtp.exmail.qq.com:25", "notify@a.com", "password")
    11  // glog.Println(s.SendMail("notify@a.com", "ulric@b.com;rain@c.com", "subject", "body, <font color=red>red</font>"))
    12  package gsmtp
    13  
    14  import (
    15  	"encoding/base64"
    16  	"fmt"
    17  	"net/smtp"
    18  	"strings"
    19  )
    20  
    21  // SMTP is the structure for smtp connection
    22  type SMTP struct {
    23  	Address  string
    24  	Username string
    25  	Password string
    26  }
    27  
    28  // New creates and returns a new SMTP object.
    29  func New(address, username, password string) *SMTP {
    30  	return &SMTP{
    31  		Address:  address,
    32  		Username: username,
    33  		Password: password,
    34  	}
    35  }
    36  
    37  var (
    38  	// contentEncoding is the BASE64 encoding object for mail content.
    39  	contentEncoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
    40  )
    41  
    42  // SendMail connects to the server at addr, switches to TLS if
    43  // possible, authenticates with the optional mechanism a if possible,
    44  // and then sends an email from address <from>, to addresses <to>, with
    45  // message msg.
    46  //
    47  // The parameter <contentType> specifies the content type of the mail, eg: html.
    48  func (s *SMTP) SendMail(from, tos, subject, body string, contentType ...string) error {
    49  	var (
    50  		server  = ""
    51  		address = ""
    52  		hp      = strings.Split(s.Address, ":")
    53  	)
    54  	if s.Address == "" || len(hp) > 2 {
    55  		return fmt.Errorf("server address is either empty or incorrect: %s", s.Address)
    56  	} else if len(hp) == 1 {
    57  		server = s.Address
    58  		address = server + ":25"
    59  	} else if len(hp) == 2 {
    60  		if (hp[0] == "") || (hp[1] == "") {
    61  			return fmt.Errorf("server address is either empty or incorrect: %s", s.Address)
    62  		}
    63  		server = hp[0]
    64  		address = s.Address
    65  	}
    66  	var (
    67  		tosArr []string
    68  		arr    = strings.Split(tos, ";")
    69  	)
    70  	for _, to := range arr {
    71  		// TODO: replace with regex
    72  		if strings.Contains(to, "@") {
    73  			tosArr = append(tosArr, to)
    74  		}
    75  	}
    76  	if len(tosArr) == 0 {
    77  		return fmt.Errorf("tos if invalid: %s", tos)
    78  	}
    79  
    80  	if !strings.Contains(from, "@") {
    81  		return fmt.Errorf("from is invalid: %s", from)
    82  	}
    83  
    84  	header := map[string]string{
    85  		"From":                      from,
    86  		"To":                        strings.Join(tosArr, ";"),
    87  		"Subject":                   fmt.Sprintf("=?UTF-8?B?%s?=", contentEncoding.EncodeToString([]byte(subject))),
    88  		"MIME-Version":              "1.0",
    89  		"Content-Type":              "text/plain; charset=UTF-8",
    90  		"Content-Transfer-Encoding": "base64",
    91  	}
    92  	if len(contentType) > 0 && contentType[0] == "html" {
    93  		header["Content-Type"] = "text/html; charset=UTF-8"
    94  	}
    95  	message := ""
    96  	for k, v := range header {
    97  		message += fmt.Sprintf("%s: %s\r\n", k, v)
    98  	}
    99  	message += "\r\n" + contentEncoding.EncodeToString([]byte(body))
   100  	return smtp.SendMail(
   101  		address,
   102  		smtp.PlainAuth("", s.Username, s.Password, server),
   103  		from,
   104  		tosArr,
   105  		[]byte(message),
   106  	)
   107  }