From a041682cc89046c4538827e66d34ded5042a0fef Mon Sep 17 00:00:00 2001 From: Jace Ferguson Date: Wed, 22 Mar 2017 14:27:46 -0500 Subject: [PATCH 1/3] Made the SMTP client Reset method accessible to the userspace. --- example_test.go | 7 ++++- send.go | 1 + send_test.go | 9 +++++++ smtp.go | 5 ++++ smtp_test.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/example_test.go b/example_test.go index 90008ab..5fe8cc6 100644 --- a/example_test.go +++ b/example_test.go @@ -7,7 +7,7 @@ import ( "log" "time" - "gopkg.in/gomail.v2" + "github.com/fjace05/gomail" ) func Example() { @@ -50,6 +50,11 @@ func Example_daemon() { open = true } if err := gomail.Send(s, m); err != nil { + /* + If a message fails to send, the SMTP channel can be reset so additional messages + can be attempted. + */ + s.Reset() log.Print(err) } // Close the connection to the SMTP server if no email was sent in diff --git a/send.go b/send.go index 9115ebe..4b32445 100644 --- a/send.go +++ b/send.go @@ -18,6 +18,7 @@ type Sender interface { type SendCloser interface { Sender Close() error + Reset() error } // A SendFunc is a function that sends emails to the given addresses. diff --git a/send_test.go b/send_test.go index ba59cd3..239b471 100644 --- a/send_test.go +++ b/send_test.go @@ -31,12 +31,17 @@ func (s mockSender) Send(from string, to []string, msg io.WriterTo) error { type mockSendCloser struct { mockSender close func() error + reset func() error } func (s *mockSendCloser) Close() error { return s.close() } +func (s *mockSendCloser) Reset() error { + return s.reset() +} + func TestSend(t *testing.T) { s := &mockSendCloser{ mockSender: stubSend(t, testFrom, []string{testTo1, testTo2}, testMsg), @@ -44,6 +49,10 @@ func TestSend(t *testing.T) { t.Error("Close() should not be called in Send()") return nil }, + reset: func() error { + t.Error("Reset() should not be called in Send()") + return nil + }, } if err := Send(s, getTestMessage()); err != nil { t.Errorf("Send(): %v", err) diff --git a/smtp.go b/smtp.go index 2aa49c8..ee9a393 100644 --- a/smtp.go +++ b/smtp.go @@ -180,6 +180,10 @@ func (c *smtpSender) Close() error { return c.Quit() } +func (c *smtpSender) Reset() error { + return c.smtpClient.Reset() +} + // Stubbed out for tests. var ( netDialTimeout = net.DialTimeout @@ -196,6 +200,7 @@ type smtpClient interface { Auth(smtp.Auth) error Mail(string) error Rcpt(string) error + Reset() error Data() (io.WriteCloser, error) Quit() error Close() error diff --git a/smtp_test.go b/smtp_test.go index b6f9155..dc50dd9 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -52,6 +52,7 @@ func TestDialerSSL(t *testing.T) { "Data", "Write message", "Close writer", + "Reset", "Quit", "Close", }) @@ -138,6 +139,19 @@ func TestDialerTimeout(t *testing.T) { }) } +func TestDialerReset(t *testing.T) { + d := NewDialer(testHost, testPort, "user", "pwd") + doTestSMTPReset(t, d, []string{ + "Extension STARTTLS", + "StartTLS", + "Extension AUTH", + "Auth", + "Reset", + "Quit", + "Close", + }) +} + type mockClient struct { t *testing.T i int @@ -195,6 +209,11 @@ func (c *mockClient) Quit() error { return nil } +func (c *mockClient) Reset() error { + c.do("Reset") + return nil +} + func (c *mockClient) Close() error { c.do("Close") return nil @@ -239,6 +258,55 @@ func testSendMailTimeout(t *testing.T, d *Dialer, want []string) { doTestSendMail(t, d, want, true) } +func doTestSMTPReset(t *testing.T, d *Dialer, want []string){ + testClient := &mockClient{ + t: t, + want: want, + addr: addr(d.Host, d.Port), + config: d.TLSConfig, + timeout: false, + } + + netDialTimeout = func(network, address string, d time.Duration) (net.Conn, error) { + if network != "tcp" { + t.Errorf("Invalid network, got %q, want tcp", network) + } + if address != testClient.addr { + t.Errorf("Invalid address, got %q, want %q", + address, testClient.addr) + } + return testConn, nil + } + + tlsClient = func(conn net.Conn, config *tls.Config) *tls.Conn { + if conn != testConn { + t.Errorf("Invalid conn, got %#v, want %#v", conn, testConn) + } + assertConfig(t, config, testClient.config) + return testTLSConn + } + + smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { + if host != testHost { + t.Errorf("Invalid host, got %q, want %q", host, testHost) + } + return testClient, nil + } + //Start "daemon" mode + s, err := d.Dial() + if err != nil { + t.Error(err) + } + + /* + Call the reset for testing purposes. In practice, this should be called after an error while attempting to send + a message. But per RFC 5321 RSET can be called at any time. + */ + s.Reset() + s.Close() + +} + func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { testClient := &mockClient{ t: t, From de645af65dfff40e326cc6ba9a23f33f36c04b00 Mon Sep 17 00:00:00 2001 From: Jace Ferguson Date: Wed, 22 Mar 2017 14:33:07 -0500 Subject: [PATCH 2/3] Reverted example_test because of the versioned gomail import. --- example_test.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/example_test.go b/example_test.go index 5fe8cc6..90008ab 100644 --- a/example_test.go +++ b/example_test.go @@ -7,7 +7,7 @@ import ( "log" "time" - "github.com/fjace05/gomail" + "gopkg.in/gomail.v2" ) func Example() { @@ -50,11 +50,6 @@ func Example_daemon() { open = true } if err := gomail.Send(s, m); err != nil { - /* - If a message fails to send, the SMTP channel can be reset so additional messages - can be attempted. - */ - s.Reset() log.Print(err) } // Close the connection to the SMTP server if no email was sent in From 6344c409c518738ec8646fdbae7f026e6da928cb Mon Sep 17 00:00:00 2001 From: Jace Ferguson Date: Wed, 22 Mar 2017 14:49:44 -0500 Subject: [PATCH 3/3] Reverted a change made to the original tests before pull specific test was written. --- smtp_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/smtp_test.go b/smtp_test.go index dc50dd9..3239f43 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -52,7 +52,6 @@ func TestDialerSSL(t *testing.T) { "Data", "Write message", "Close writer", - "Reset", "Quit", "Close", })