Go发送邮件遇wsarecv错误:远程主机强制关闭连接求助
Go发送SMTP邮件连接被重置问题排查
问题背景
我编写了Go语言程序用于发送邮件,确认凭证信息正确,但运行程序和curl测试均出现连接被重置的错误。
Go程序代码
package main import ( "fmt" "log" "net/smtp" ) const ( USERNAME = "ryuken@email.com" PASSWD = "password1111" HOST = "mail.privateemail.com" PORT = "465" ) func main() { from := "ryuken@email.com" to := []string{ "info@email.com", } msg := []byte("From: ryuken@email.com\r\n" + "To: info@email.com" + "Subject: Golang testing mail\r\n" + "Email Body: Welcome to Go!\r\n") auth := smtp.PlainAuth("", USERNAME, PASSWD, HOST) url := fmt.Sprintf(HOST + ":" + PORT) fmt.Printf("url=[%s]\n", url) err := smtp.SendMail(url, auth, from, to, msg) if err != nil { log.Fatal(err) } fmt.Println("Mail sent successfully!") }
程序运行错误
read tcp 192.168.0.2:61740->198.54.122.135:465: wsarecv: An existing connection was forcibly closed by the remote host.
exit status 1
curl测试情况
执行的curl命令及输出:
c:\GoProjects\goemail λ curl -v --url "smtp://mail.privateemail.com:465" --user "ryuken@email.com:password1111" --mail-from "ryuken@email.com" --mail-rcpt "info@email.com-" --upload-file sample.txt % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 198.54.122.135:465... * Connected to mail.privateemail.com (198.54.122.135) port 465 (#0) 0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0* Recv failure: Connection was reset 0 0 0 0 0 0 0 0 --:--:-- 0:00:10 --:--:-- 0 * Closing connection 0 curl: (56) Recv failure: Connection was reset
问题原因及解决方案
核心原因
端口465是**SMTP over SSL/TLS(SMTPS)**的标准端口,要求连接建立时直接使用TLS加密。你的Go程序和curl命令都用了普通明文SMTP协议连接该端口,服务器会直接重置不兼容的连接。
具体问题点
- Go的
smtp.SendMail默认使用明文SMTP,不支持直接连接465端口的SMTPS,必须手动建立TLS连接。 - curl命令里使用了
smtp://明文协议,需改用smtps://指定SMTPS协议;同时--mail-rcpt参数后多了一个无效的-符号。 - 原Go程序的邮件格式存在问题:
To字段后缺少\r\n,邮件头和正文之间没有空行分隔,会导致邮件解析失败。
修正后的Go代码示例
package main import ( "crypto/tls" "fmt" "log" "net/smtp" ) const ( USERNAME = "ryuken@email.com" PASSWD = "password1111" HOST = "mail.privateemail.com" PORT = "465" ) func main() { from := "ryuken@email.com" to := []string{"info@email.com"} // 修复邮件格式:补全换行符,添加邮件头与正文的分隔空行 msg := []byte("From: ryuken@email.com\r\n" + "To: info@email.com\r\n" + "Subject: Golang testing mail\r\n" + "\r\n" + // 邮件头和正文必须用空行分隔 "Welcome to Go!\r\n") auth := smtp.PlainAuth("", USERNAME, PASSWD, HOST) // 建立TLS加密连接 conn, err := tls.Dial("tcp", HOST+":"+PORT, &tls.Config{ServerName: HOST}) if err != nil { log.Fatal(err) } defer conn.Close() client, err := smtp.NewClient(conn, HOST) if err != nil { log.Fatal(err) } defer client.Quit() // 验证身份 if err = client.Auth(auth); err != nil { log.Fatal(err) } // 设置发件人 if err = client.Mail(from); err != nil { log.Fatal(err) } // 设置收件人 for _, addr := range to { if err = client.Rcpt(addr); err != nil { log.Fatal(err) } } // 发送邮件内容 w, err := client.Data() if err != nil { log.Fatal(err) } _, err = w.Write(msg) if err != nil { log.Fatal(err) } err = w.Close() if err != nil { log.Fatal(err) } fmt.Println("Mail sent successfully!") }
修正后的curl命令
curl -v --url "smtps://mail.privateemail.com:465" --user "ryuken@email.com:password1111" --mail-from "ryuken@email.com" --mail-rcpt "info@email.com" --upload-file sample.txt
内容的提问来源于stack exchange,提问作者ryuken
相关产品推荐
相关产品推荐

