I'm writing a package which I intend to make one initial connection to the local SMTP server and then it waits on a channel which will be populated with emails to send when they are needed to be sent.
Looking at net/http it appears to be expecting that the SMTP server should be dialed into and authenticated each time an email is to be sent. Surely I can dial and authenticate once, keep the connection open and just add new emails as they come?
Looking at the source for smtp.SendMail
, I don't see how this can be done, as there does not appear to be a way to recycle the *Client
:
http://golang.org/src/net/smtp/smtp.go?s=7610:7688#L263
There is a Reset
function for *Client
, but the description for that is:
Reset sends the RSET command to the server, aborting the current mail transaction.
I don't want to abort the current mail transaction, I want to have multiple mail transactions.
How can I keep the connection to the SMTP server open and send multiple emails on that one connection?
You are correct that smtp.SendMail
does not provide a way to reuse the connection.
If you want that fine grained control, you should use a persistent client connection. This will require knowing a bit more about the smtp commands and protocol.
smtp.Dial
to open a connection and create a client object.client.Hello
, client.Auth
, and client.StartTLS
as appropriate.Rcpt
, Mail
, Data
as approprate to send messages.client.Quit()
and close connection when you are all done.Gomail v2 now supports sending multiple emails in one connection. The Daemon example from the documentation seems to match your use case:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With