【问题标题】:Go: Connect to SMTP server and send multiple emails in one connection?Go:连接到 SMTP 服务器并在一个连接中发送多封电子邮件?
【发布时间】:2015-08-07 15:15:35
【问题描述】:

我正在编写一个包,我打算与本地 SMTP 服务器建立一个初始连接,然后它在一个通道上等待,该通道将填充电子邮件以在需要发送时发送。

查看 net/http 似乎期望每次发送电子邮件时都应拨入 SMTP 服务器并进行身份验证。当然,我可以拨号和验证一次,保持连接打开,然后添加新的电子邮件?

查看smtp.SendMail 的来源,我不明白这是怎么做到的,因为似乎没有办法回收*Clienthttp://golang.org/src/net/smtp/smtp.go?s=7610:7688#L263

*Client 有一个Reset 函数,但它的描述是:

 Reset sends the RSET command to the server, aborting the current mail transaction.

我不想中止当前的邮件交易,我想进行多个邮件交易。

如何保持与 SMTP 服务器的连接打开并在一个连接上发送多封电子邮件?

【问题讨论】:

    标签: email go smtp smtp-auth


    【解决方案1】:

    smtp.SendMail 没有提供重用连接的方法是正确的。

    如果您想要那种细粒度的控制,您应该使用持久的客户端连接。这需要对 smtp 命令和协议有更多了解。

    1. 使用smtp.Dial 打开连接并创建客户端对象。
    2. 酌情使用client.Helloclient.Authclient.StartTLS
    3. 使用RcptMailData 发送消息。
    4. client.Quit() 完成后关闭连接。

    【讨论】:

    • 谢谢...何时重置连接以发送另一封电子邮件?我是在每条消息的末尾还是在发送所有消息的末尾使用client.Quit()
    • quit 表示“我已经完成并准备断开连接”。仅在所有消息结束时发送。
    • 不需要第一步(自己开一个net.Conn)。你可以使用smtp.Dial。基本上,只需做几乎与smtp.SendMail 完全相同的操作,除了在调用Quit 之前循环并执行更多MailRcptData 调用。
    • 在这种情况下,我将永远不会运行 Quit() 或 Close(),因为 Go webapp 始终保持拨入 SMTP 服务器。 Go 应用退出时连接会自动终止吗?
    • 成功了!非常感谢。我将 Quit and Close 作为延迟放在等待通道的 goroutine 中。因此,当 goroutine 终止时,它将关闭连接。
    【解决方案2】:

    Gomail v2 现在支持在一个连接中发送多封电子邮件。文档中的Daemon example 似乎与您的用例相匹配:

    ch := make(chan *gomail.Message)
    
    go func() {
        d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456")
    
        var s gomail.SendCloser
        var err error
        open := false
        for {
            select {
            case m, ok := <-ch:
                if !ok {
                    return
                }
                if !open {
                    if s, err = d.Dial(); err != nil {
                        panic(err)
                    }
                    open = true
                }
                if err := gomail.Send(s, m); err != nil {
                    log.Print(err)
                }
            // Close the connection to the SMTP server if no email was sent in
            // the last 30 seconds.
            case <-time.After(30 * time.Second):
                if open {
                    if err := s.Close(); err != nil {
                        panic(err)
                    }
                    open = false
                }
            }
        }
    }()
    
    // Use the channel in your program to send emails.
    
    // Close the channel to stop the mail daemon.
    close(ch)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      • 2019-06-19
      • 1970-01-01
      相关资源
      最近更新 更多