You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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协议连接该端口,服务器会直接重置不兼容的连接。

具体问题点

  1. Go的smtp.SendMail默认使用明文SMTP,不支持直接连接465端口的SMTPS,必须手动建立TLS连接。
  2. curl命令里使用了smtp://明文协议,需改用smtps://指定SMTPS协议;同时--mail-rcpt参数后多了一个无效的-符号。
  3. 原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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 04:45:41