smtpSender.Send() now automatically redials in case of a timeout
This commit is contained in:
parent
5ceb8e6541
commit
afff51fd8c
13
smtp.go
13
smtp.go
|
@ -110,7 +110,7 @@ func (d *Dialer) Dial() (SendCloser, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &smtpSender{c}, nil
|
return &smtpSender{c, d}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) tlsConfig() *tls.Config {
|
func (d *Dialer) tlsConfig() *tls.Config {
|
||||||
|
@ -138,10 +138,21 @@ func (d *Dialer) DialAndSend(m ...*Message) error {
|
||||||
|
|
||||||
type smtpSender struct {
|
type smtpSender struct {
|
||||||
smtpClient
|
smtpClient
|
||||||
|
d *Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
|
func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
|
||||||
if err := c.Mail(from); err != nil {
|
if err := c.Mail(from); err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
// This is probably due to a timeout, so reconnect and try again.
|
||||||
|
sc, derr := c.d.Dial()
|
||||||
|
if derr == nil {
|
||||||
|
if s, ok := sc.(*smtpSender); ok {
|
||||||
|
*c = *s
|
||||||
|
return c.Send(from, to, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
36
smtp_test.go
36
smtp_test.go
|
@ -115,12 +115,35 @@ func TestDialerNoAuth(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDialerTimeout(t *testing.T) {
|
||||||
|
d := &Dialer{
|
||||||
|
Host: testHost,
|
||||||
|
Port: testPort,
|
||||||
|
}
|
||||||
|
testSendMailTimeout(t, d, []string{
|
||||||
|
"Extension STARTTLS",
|
||||||
|
"StartTLS",
|
||||||
|
"Mail " + testFrom,
|
||||||
|
"Extension STARTTLS",
|
||||||
|
"StartTLS",
|
||||||
|
"Mail " + testFrom,
|
||||||
|
"Rcpt " + testTo1,
|
||||||
|
"Rcpt " + testTo2,
|
||||||
|
"Data",
|
||||||
|
"Write message",
|
||||||
|
"Close writer",
|
||||||
|
"Quit",
|
||||||
|
"Close",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type mockClient struct {
|
type mockClient struct {
|
||||||
t *testing.T
|
t *testing.T
|
||||||
i int
|
i int
|
||||||
want []string
|
want []string
|
||||||
addr string
|
addr string
|
||||||
config *tls.Config
|
config *tls.Config
|
||||||
|
timeout bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockClient) Hello(localName string) error {
|
func (c *mockClient) Hello(localName string) error {
|
||||||
|
@ -149,6 +172,10 @@ func (c *mockClient) Auth(a smtp.Auth) error {
|
||||||
|
|
||||||
func (c *mockClient) Mail(from string) error {
|
func (c *mockClient) Mail(from string) error {
|
||||||
c.do("Mail " + from)
|
c.do("Mail " + from)
|
||||||
|
if c.timeout {
|
||||||
|
c.timeout = false
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,11 +231,20 @@ func (w *mockWriter) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSendMail(t *testing.T, d *Dialer, want []string) {
|
func testSendMail(t *testing.T, d *Dialer, want []string) {
|
||||||
|
doTestSendMail(t, d, want, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSendMailTimeout(t *testing.T, d *Dialer, want []string) {
|
||||||
|
doTestSendMail(t, d, want, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) {
|
||||||
testClient := &mockClient{
|
testClient := &mockClient{
|
||||||
t: t,
|
t: t,
|
||||||
want: want,
|
want: want,
|
||||||
addr: addr(d.Host, d.Port),
|
addr: addr(d.Host, d.Port),
|
||||||
config: d.TLSConfig,
|
config: d.TLSConfig,
|
||||||
|
timeout: timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
netDial = func(network, address string) (net.Conn, error) {
|
netDial = func(network, address string) (net.Conn, error) {
|
||||||
|
|
Loading…
Reference in New Issue