如何在没有任何 smtp 服务器的情况下在 golang 中发送电子邮件

How to send emails in golang without any smtp server

我想从用 golang 编写的服务器应用程序发送群发邮件。我只是不想使用任何第三方 smtp 服务器来避免使用配额限制。

没有 smtp 服务器如何发送电子邮件?标准库中的 smtp 包可以帮助我吗?我看到的所有使用 smtp 包的示例都需要第三方 smtp 服务器来发送电子邮件。

您的问题类似于 - 我可以在没有网络服务器的情况下向用户显示网页吗?是的,如果您能够编写自己的网络服务器,您就可以。

你会在 Go 上编写 SMTP 服务器吗?是的。 Google 显示了 "golang smtp server" 查询的几个解决方案。所以我很确定您可以将 SMTP 服务器功能集成到您的应用程序中。

但正如评论者所说 - 您的大部分邮件(如果不是全部)将直接进入大部分服务的垃圾邮件文件夹。

只有一种方法可以在不直接与 SMTP 服务器通信的情况下发送 e-mail 消息:将此操作委托给其他程序。

选择什么程序,本身就是一个开放而广泛的问题,因为有很多程序可以发送邮件。

另一方面,如果我们谈论 POSIX 系统,例如 GNU/Linux- 或 *BSD-based 操作系统,它们 通常 带有二进制 /usr/sbin/sendmail 或有时 /usr/bin/sendmail 由真正的 Sendmail package or by another MTA which exist in abundance—ranging from full-blown MTAs such as Postfix or Exim 提供给 narrow-scoped "null-clients" 例如 ssmtpnullmailer.

此程序通常使用 -t command-line 选项调用,这使得它从邮件本身的 To headers 中读取邮件收件人的地址.

基本上调用 /usr/sbin/sendmail -t 并将完整消息的文本通过管道传输到其标准输入是 PHP's mail() function 所做的,FWIW。

虽然您可以直接使用 os/execnet/mailnet/textproto 标准包进行此调用,但流行的 gomail 包提供了一种更简单的方法:它的 Message 类型提供了 WriteTo() 方法,可以写入 运行 Sendmail 实例,像这样(从我的一个真实程序中复制):

const sendmail = "/usr/sbin/sendmail"

func submitMail(m *gomail.Message) (err error) {
    cmd := exec.Command(sendmail, "-t")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    pw, err := cmd.StdinPipe()
    if err != nil {
        return
    }

    err = cmd.Start()
    if err != nil {
        return
    }

    var errs [3]error
    _, errs[0] = m.WriteTo(pw)
    errs[1] = pw.Close()
    errs[2] = cmd.Wait()
    for _, err = range errs {
        if err != nil {
            return
        }
    }
    return
}

实际上,依靠 MTA 来传递邮件的一个优势是 full-blown MTA 支持邮件排队:也就是说,如果 MTA 无法立即发送您的邮件(例如,由于网络原因)中断等)所以它会将消息保存在一个特殊的目录中,然后会定期尝试一次又一次地传递它直到成功或(通常很长,比如 4-5 天)超时到期。