funcSendMail(addr string, a Auth, from string, to []string, msg []byte)error { //validateLine checks to see if a line has CR or LF //if it has, then return an error if err := validateLine(from); err != nil { return err } for _, recp := range to { if err := validateLine(recp); err != nil { return err } } //Dial returns a new Client connected to an SMTP server at addr. The addr must include a port, as in "mail.example.com:smtp" c, err := Dial(addr) if err != nil { return err } // close the connection. defer c.Close() //Hello sends a HELO or EHLO to the server as the given host name. if err = c.hello(); err != nil { return err } //Extension reports whether an extension is support by the server // the StartTLS extension if ok, _ := c.Extension("STARTTLS"); ok { config := &tls.Config{ServerName: c.serverName} if testHookStartTLS != nil { testHookStartTLS(config) } if err = c.StartTLS(config); err != nil { return err } } if a != nil && c.ext != nil { if _, ok := c.ext["AUTH"]; !ok { return errors.New("smtp: server doesn't support AUTH") } //Auth authenticates a client using the provided authentication mechanism. if err = c.Auth(a); err != nil { return err } } //Mail issues a MAIL command to the server using the provided email address. if err = c.Mail(from); err != nil { return err } for _, addr := range to { //Rcpt issues a RCPT command to the server using the provided email address. if err = c.Rcpt(addr); err != nil { return err } } //Data issues a DATA command to the server and returns a writer that can be used to write the mail headers and body. w, err := c.Data() if err != nil { return err } _, err = w.Write(msg) if err != nil { return err } err = w.Close() if err != nil { return err } //Quit sends the QUIT command and closes the connection to the server. return c.Quit() }
// Auth is implemented by an SMTP authentication mechanism. type Auth interface { // Start begins an authentication with a server. // It returns the name of the authentication protocol and optionally data to include in the initial AUTH message sent to the server. Start(server *ServerInfo) (proto string, toServer []byte, err error)
// Next continues the authentication. The server has just sent the fromServer data. If more is true, the server expects a response, which Next should return as toServer; Next(fromServer []byte, more bool) (toServer []byte, err error) }
type plainAuth struct { identity, username, password string host string } //PlainAuth will only send the credentials if the connection is using TLS or is connected to localhost. funcPlainAuth(identity, username, password, host string)Auth { return &plainAuth{identity, username, password, host} }
func(a *plainAuth)Start(server *ServerInfo)(string, []byte, error) { // Must have TLS, or else localhost server. // Note: If TLS is not true, then we can't trust ANYTHING in ServerInfo. if !server.TLS && !isLocalhost(server.Name) { return"", nil, errors.New("unencrypted connection") } if server.Name != a.host { return"", nil, errors.New("wrong host name") } resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password) return"PLAIN", resp, nil }
I made a simple application of smtp to send email :