package main import ( "crypto/tls" "fmt" "log" "net/smtp" "os" "time" ) const ( smtpServer = "smtp.exmail.qq.com" smtpPort = 465 maxRetries = 3 ) func main() { log.Println("Service Cli Mode Start ...") log.Println("Done!") err := sendEmail( os.Getenv("BSM_SMTP_TO"), "Go邮件测试", "这是一封通过Go语言发送的测试邮件", ) if err != nil { fmt.Printf("发送失败: %v\n", err) } else { fmt.Println("邮件发送成功") } } func sendEmail(to, subject, body string) error { smtpUser := os.Getenv("BSM_SMTP_USER") smtpPassword := os.Getenv("BSM_SMTP_PASSWORD") if smtpUser == "" || smtpPassword == "" || to == "" { return fmt.Errorf("BSM_SMTP_USER, BSM_SMTP_PASSWORD and BSM_SMTP_TO are required") } // 配置SMTP认证信息(需使用授权码) auth := smtp.PlainAuth( "", smtpUser, smtpPassword, smtpServer, ) // 邮件内容构建(符合RFC822标准) msg := fmt.Sprintf("To: %s\r\n"+ "From: %s\r\n"+ "Subject: %s\r\n"+ "Content-Type: text/plain; charset=UTF-8\r\n\r\n"+ "%s", to, smtpUser, subject, body, ) // 建立TLS连接 tlsConfig := &tls.Config{ ServerName: smtpServer, InsecureSkipVerify: false, MinVersion: tls.VersionTLS12, } var lastErr error for i := 0; i < maxRetries; i++ { conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", smtpServer, smtpPort), tlsConfig) if err != nil { lastErr = fmt.Errorf("TLS连接失败: %v", err) time.Sleep(2 * time.Second) continue } client, err := smtp.NewClient(conn, smtpServer) if err != nil { conn.Close() lastErr = fmt.Errorf("SMTP客户端创建失败: %v", err) continue } if err := client.Auth(auth); err != nil { client.Close() lastErr = fmt.Errorf("认证失败: %v", err) continue } if err := client.Mail("yanweidong@senlinai.com"); err != nil { client.Close() lastErr = fmt.Errorf("MAIL命令失败: %v", err) continue } if err := client.Rcpt(to); err != nil { client.Close() lastErr = fmt.Errorf("RCPT命令失败: %v", err) continue } w, err := client.Data() if err != nil { client.Close() lastErr = fmt.Errorf("DATA命令失败: %v", err) continue } if _, err := w.Write([]byte(msg)); err != nil { client.Close() lastErr = fmt.Errorf("写入邮件内容失败: %v", err) continue } if err := w.Close(); err != nil { client.Close() lastErr = fmt.Errorf("关闭数据流失败: %v", err) continue } client.Quit() return nil } return lastErr }