Skip to content

Instantly share code, notes, and snippets.

@jedy
Last active March 15, 2017 01:59
Show Gist options
  • Save jedy/4679c9f3ce5cbff4f775c0b8e7126ecd to your computer and use it in GitHub Desktop.
Save jedy/4679c9f3ce5cbff4f775c0b8e7126ecd to your computer and use it in GitHub Desktop.
sendmail with tls
package main
import (
"crypto/tls"
"errors"
"log"
"net"
"net/smtp"
)
func main() {
// Set up authentication information.
auth := smtp.PlainAuth("", "[email protected]", "password", "mail.example.com")
// Connect to the server, authenticate, set the sender and recipient,
// and send the email all in one step.
to := []string{"[email protected]"}
msg := []byte("To: [email protected]\r\n" +
"Subject: discount Gophers!\r\n" +
"\r\n" +
"This is the email body.\r\n")
// directly use tls port 465
err := smtp.SendMail("mail.example.com:465", auth, "[email protected]", to, msg)
if err != nil {
log.Fatal(err)
}
}
// SendMail 用于发送邮件。和标准库中不同的是默认使用TLS,而不是先用普通连接之后再升级
// 邮件提供商提供的smtp发送端口都要直接用TLS连接的,使用标准库会返回错误EOF
// 如果使用标准库需要用25端口,而不是帮助中说的465或995端口
func SendMail(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
hostname, _, err := net.SplitHostPort(addr)
if err != nil {
return err
}
conn, err := tls.Dial("tcp", addr, &tls.Config{ServerName: hostname})
if err != nil {
return err
}
c, err := smtp.NewClient(conn, hostname)
if err != nil {
return err
}
defer c.Close()
if err = c.Auth(a); err != nil {
return err
}
if err = c.Mail(from); err != nil {
return err
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}
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
}
return c.Quit()
}
type plainAuth struct {
identity, username, password string
host string
}
func (a *plainAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
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
}
func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
// We've already sent everything.
return nil, errors.New("unexpected server challenge")
}
return nil, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment