代码拉取完成,页面将自动刷新
package email
import (
"context"
"crypto/tls"
"errors"
"log"
"net"
"net/smtp"
"strings"
"time"
)
type Conn struct {
*smtp.Client
conn *tls.Conn
}
func Dial(ctx context.Context, addr string, auth smtp.Auth) (*Conn, error) {
deadline, hasDeadline := ctx.Deadline()
conn, err := tls.DialWithDialer(&net.Dialer{Deadline: deadline}, "tcp", addr, nil)
if err != nil {
return nil, err
}
if hasDeadline {
if err := conn.SetDeadline(deadline); err != nil {
conn.Close()
return nil, err
}
}
host, _, _ := net.SplitHostPort(addr)
client, err := smtp.NewClient(conn, host)
if err != nil {
conn.Close()
return nil, err
}
if auth != nil {
if ok, _ := client.Extension("AUTH"); ok {
if err = client.Auth(auth); err != nil {
conn.Close()
return nil, err
}
}
}
if hasDeadline {
if err := conn.SetDeadline(time.Time{}); err != nil {
conn.Close()
return nil, err
}
}
return &Conn{Client: client, conn: conn}, nil
}
func (c *Conn) Send(ctx context.Context, from string, to []string, msg []byte) (err error) {
if err = validateLine(from); err != nil {
return
}
for _, recp := range to {
if err = validateLine(recp); err != nil {
return
}
}
if deadline, ok := ctx.Deadline(); ok {
if err = c.conn.SetDeadline(deadline); err != nil {
return
}
defer func() {
if err2 := c.conn.SetDeadline(time.Time{}); err2 != nil {
if err == nil {
err = err2
} else {
log.Println("email: conn.SetDeadline:", err2)
}
}
}()
}
if err = c.Mail(from); err != nil {
return
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return
}
}
w, err := c.Data()
if err != nil {
return
}
defer w.Close()
// "net/textproto".Writer will convert "\n" to "\r\n"
_, err = w.Write(msg)
return
}
// validateLine checks to see if a line has CR or LF as per RFC 5321
func validateLine(line string) error {
if strings.ContainsAny(line, "\n\r") {
return errors.New("mail: A line must not contain CR or LF")
}
return nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。