From ec61a8ae4f287b8d212c9ed78685f9930eaabe2f Mon Sep 17 00:00:00 2001 From: Rienzi Date: Wed, 30 Aug 2017 18:50:03 -0400 Subject: [PATCH 01/34] Added Check For Existing Files And Attachments --- send.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/send.go b/send.go index 9115ebe..b0cd0a4 100644 --- a/send.go +++ b/send.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/mail" + "os" ) // Sender is the interface that wraps the Send method. @@ -54,6 +55,10 @@ func send(s Sender, m *Message) error { return err } + if err := m.checkEmbedsAndAttachments(); err != nil { + return err + } + if err := s.Send(from, to, m); err != nil { return err } @@ -97,6 +102,20 @@ func (m *Message) getRecipients() ([]string, error) { return list, nil } +func (m *Message) checkEmbedsAndAttachments() error { + for _, file := range m.embedded { + if _, err := os.Stat(file.Name); err != nil { + return err + } + } + for _, file := range m.attachments { + if _, err := os.Stat(file.Name); err != nil { + return err + } + } + return nil +} + func addAddress(list []string, addr string) []string { for _, a := range list { if addr == a { From c331832adaea1ed9543417b573ed99c83211fde0 Mon Sep 17 00:00:00 2001 From: Rienzi Date: Wed, 30 Aug 2017 19:29:17 -0400 Subject: [PATCH 02/34] Updated Tests To Actually Create File --- message_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/message_test.go b/message_test.go index acceff2..210b2d4 100644 --- a/message_test.go +++ b/message_test.go @@ -1,6 +1,7 @@ package gomail import ( + "os" "bytes" "encoding/base64" "io" @@ -297,6 +298,9 @@ func TestRename(t *testing.T) { m.SetBody("text/plain", "Test") name, copy := mockCopyFile("/tmp/test.pdf") rename := Rename("another.pdf") + os.Create("another.pdf") + + m.Attach(name, copy, rename) want := &message{ @@ -705,6 +709,7 @@ func getBoundaries(t *testing.T, count int, m string) []string { var boundaryRegExp = regexp.MustCompile("boundary=(\\w+)") func mockCopyFile(name string) (string, FileSetting) { + os.Create(filepath.Base(name)) return name, SetCopyFunc(func(w io.Writer) error { _, err := w.Write([]byte("Content of " + filepath.Base(name))) return err From 92faf9500adb68b6a67269dc6fe74ce47e3056ac Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 18:20:49 +0000 Subject: [PATCH 03/34] Unfortunate fork ;-( Original maintainer missing/uncontactable --- .gitignore | 17 +++++++++++++++++ .travis.yml | 14 +++++++++----- CHANGELOG.md | 3 +++ README.md | 11 ++++++----- doc.go | 2 +- 5 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc4721c --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ + + +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + + +# IDE's +.idea/ diff --git a/.travis.yml b/.travis.yml index 48915e7..64e9339 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,13 @@ language: go go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 - - 1.6 + - 1.2x + - 1.3x + - 1.4x + - 1.5x + - 1.6x + - 1.7x + - 1.8x + - 1.9x - tip + diff --git a/CHANGELOG.md b/CHANGELOG.md index a797ab4..be37fba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 2017-12-06 Original project forked +https://github.com/go-gomail/gomail/issues/104 + ## [2.0.0] - 2015-09-02 - Mailer has been removed. It has been replaced by Dialer and Sender. diff --git a/README.md b/README.md index b3be9e1..4380c2e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Gomail -[![Build Status](https://travis-ci.org/go-gomail/gomail.svg?branch=v2)](https://travis-ci.org/go-gomail/gomail) [![Code Coverage](http://gocover.io/_badge/gopkg.in/gomail.v2)](http://gocover.io/gopkg.in/gomail.v2) [![Documentation](https://godoc.org/gopkg.in/gomail.v2?status.svg)](https://godoc.org/gopkg.in/gomail.v2) +[![Build Status](https://travis-ci.org/go-mail/gomail.svg?branch=v2)](https://travis-ci.org/go-mail/gomail) [![Code Coverage](http://gocover.io/_badge/gopkg.in/gomail.v2)](http://gocover.io/gopkg.in/gomail.v2) [![Documentation](https://godoc.org/github.com/go-mail/gomail?status.svg)](https://godoc.org/github.com/go-mail/gomail) + +**IMPORTANT** - This is a fork of [go-gomail/gomail](https://github.com/go-gomail/gomail). See this [issue#104](https://github.com/go-gomail/gomail/issues/104) + ## Introduction @@ -10,8 +13,6 @@ Gomail can only send emails using an SMTP server. But the API is flexible and it is easy to implement other methods for sending emails using a local Postfix, an API, etc. -It is versioned using [gopkg.in](https://gopkg.in) so I promise -there will never be backward incompatible changes within each version. It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used. @@ -29,7 +30,7 @@ Gomail supports: ## Documentation -https://godoc.org/gopkg.in/gomail.v2 +https://godoc.org/github.com/go-mail/gomail ## Download @@ -39,7 +40,7 @@ https://godoc.org/gopkg.in/gomail.v2 ## Examples -See the [examples in the documentation](https://godoc.org/gopkg.in/gomail.v2#example-package). +See the [examples in the documentation](https://godoc.org/github.com/go-mail/gomail#example-package). ## FAQ diff --git a/doc.go b/doc.go index a8f5091..1c7d183 100644 --- a/doc.go +++ b/doc.go @@ -1,5 +1,5 @@ // Package gomail provides a simple interface to compose emails and to mail them // efficiently. // -// More info on Github: https://github.com/go-gomail/gomail +// More info on Github: https://github.com/go-mail/gomail package gomail From 3e555824b70b4338031d426e76c4d73fa719f5ee Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 18:34:03 +0000 Subject: [PATCH 04/34] Fix imports --- README.md | 4 ++-- example_test.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4380c2e..373a9e5 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ https://godoc.org/github.com/go-mail/gomail ## Download - go get gopkg.in/gomail.v2 + go get github.com/go-mail/gomail ## Examples @@ -57,7 +57,7 @@ bypass the verification of the server's certificate chain and host name by using import ( "crypto/tls" - "gopkg.in/gomail.v2" + "github.com/go-mail/gomail" ) func main() { diff --git a/example_test.go b/example_test.go index 90008ab..1f5a0b8 100644 --- a/example_test.go +++ b/example_test.go @@ -7,7 +7,8 @@ import ( "log" "time" - "gopkg.in/gomail.v2" + //"gopkg.in/gomail.v2" - we forked + "github.com/go-mail/gomail" ) func Example() { From 594fad0bf173430584364e5e441168abfd016c25 Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 18:44:28 +0000 Subject: [PATCH 05/34] fix coverage link --- README.md | 2 +- doc.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 373a9e5..6b549af 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Gomail -[![Build Status](https://travis-ci.org/go-mail/gomail.svg?branch=v2)](https://travis-ci.org/go-mail/gomail) [![Code Coverage](http://gocover.io/_badge/gopkg.in/gomail.v2)](http://gocover.io/gopkg.in/gomail.v2) [![Documentation](https://godoc.org/github.com/go-mail/gomail?status.svg)](https://godoc.org/github.com/go-mail/gomail) +[![Build Status](https://travis-ci.org/go-mail/gomail.svg?branch=v2)](https://travis-ci.org/go-mail/gomail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/gomail)](http://gocover.io/github.com/go-mail/gomail) [![Documentation](https://godoc.org/github.com/go-mail/gomail?status.svg)](https://godoc.org/github.com/go-mail/gomail) **IMPORTANT** - This is a fork of [go-gomail/gomail](https://github.com/go-gomail/gomail). See this [issue#104](https://github.com/go-gomail/gomail/issues/104) diff --git a/doc.go b/doc.go index 1c7d183..ff3883d 100644 --- a/doc.go +++ b/doc.go @@ -2,4 +2,5 @@ // efficiently. // // More info on Github: https://github.com/go-mail/gomail +// package gomail From f10eb0a0f403519243d2b9cdce13eb60d8a8aa43 Mon Sep 17 00:00:00 2001 From: Andras Elso Date: Sun, 8 Oct 2017 14:04:37 +0200 Subject: [PATCH 06/34] Export NetDialTimeout to public [Ivy: move NetDialTimeout outside of var stubs to prevent confusion] --- smtp.go | 9 +++++---- smtp_test.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/smtp.go b/smtp.go index 2aa49c8..12d0606 100644 --- a/smtp.go +++ b/smtp.go @@ -55,10 +55,12 @@ func NewPlainDialer(host string, port int, username, password string) *Dialer { return NewDialer(host, port, username, password) } +var NetDialTimeout = net.DialTimeout + // Dial dials and authenticates to an SMTP server. The returned SendCloser // should be closed when done using it. func (d *Dialer) Dial() (SendCloser, error) { - conn, err := netDialTimeout("tcp", addr(d.Host, d.Port), 10*time.Second) + conn, err := NetDialTimeout("tcp", addr(d.Host, d.Port), 10*time.Second) if err != nil { return nil, err } @@ -182,9 +184,8 @@ func (c *smtpSender) Close() error { // Stubbed out for tests. var ( - netDialTimeout = net.DialTimeout - tlsClient = tls.Client - smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { + tlsClient = tls.Client + smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { return smtp.NewClient(conn, host) } ) diff --git a/smtp_test.go b/smtp_test.go index b6f9155..3323029 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -248,7 +248,7 @@ func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { timeout: timeout, } - netDialTimeout = func(network, address string, d time.Duration) (net.Conn, error) { + NetDialTimeout = func(network, address string, d time.Duration) (net.Conn, error) { if network != "tcp" { t.Errorf("Invalid network, got %q, want tcp", network) } From 834091045ffc7628973edbd31a3f49afb9a5d5ca Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 12:39:09 -0800 Subject: [PATCH 07/34] Document NetDialTimeout --- smtp.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/smtp.go b/smtp.go index 12d0606..b523f15 100644 --- a/smtp.go +++ b/smtp.go @@ -55,6 +55,9 @@ func NewPlainDialer(host string, port int, username, password string) *Dialer { return NewDialer(host, port, username, password) } +// NetDialTimeout specifies the DialTimeout function to establish a connection +// to the SMTP server. This can be used to override dialing in the case that a +// proxy or other special behavior is needed. var NetDialTimeout = net.DialTimeout // Dial dials and authenticates to an SMTP server. The returned SendCloser From 8dc4458ab91e0f12a063ee609516985bd4aa1d14 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 12:47:28 -0800 Subject: [PATCH 08/34] Add syntax highlighting to Go example --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6b549af..6c43b82 100644 --- a/README.md +++ b/README.md @@ -52,20 +52,22 @@ considered valid by the client running Gomail. As a quick workaround you can bypass the verification of the server's certificate chain and host name by using `SetTLSConfig`: - package main +```go +package main - import ( - "crypto/tls" +import ( + "crypto/tls" - "github.com/go-mail/gomail" - ) + "github.com/go-mail/gomail" +) - func main() { - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") - d.TLSConfig = &tls.Config{InsecureSkipVerify: true} +func main() { + d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d.TLSConfig = &tls.Config{InsecureSkipVerify: true} - // Send emails using d. - } + // Send emails using d. +} +``` Note, however, that this is insecure and should not be used in production. From c0dd68766e0e5c80c1c4382b2f6ba9f0da9518f9 Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 21:30:53 +0000 Subject: [PATCH 09/34] Ditch go < 1.5 (and no external dependancies) --- .travis.yml | 3 --- README.md | 2 +- mime.go | 1 - mime_go14.go | 25 ------------------------- 4 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 mime_go14.go diff --git a/.travis.yml b/.travis.yml index 64e9339..20b1123 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: go go: - - 1.2x - - 1.3x - - 1.4x - 1.5x - 1.6x - 1.7x diff --git a/README.md b/README.md index 6b549af..f4b4ad7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ is easy to implement other methods for sending emails using a local Postfix, an API, etc. -It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used. +It requires Go 1.5 or newer. ## Features diff --git a/mime.go b/mime.go index 194d4a7..3aab82d 100644 --- a/mime.go +++ b/mime.go @@ -1,4 +1,3 @@ -// +build go1.5 package gomail diff --git a/mime_go14.go b/mime_go14.go deleted file mode 100644 index 3dc26aa..0000000 --- a/mime_go14.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build !go1.5 - -package gomail - -import "gopkg.in/alexcesaro/quotedprintable.v3" - -var newQPWriter = quotedprintable.NewWriter - -type mimeEncoder struct { - quotedprintable.WordEncoder -} - -var ( - bEncoding = mimeEncoder{quotedprintable.BEncoding} - qEncoding = mimeEncoder{quotedprintable.QEncoding} - lastIndexByte = func(s string, c byte) int { - for i := len(s) - 1; i >= 0; i-- { - - if s[i] == c { - return i - } - } - return -1 - } -) From 4e2ebb06c6739fbcfe076b6d5de6e0d09c5d2aa4 Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 21:37:54 +0000 Subject: [PATCH 10/34] make travis check master+v2 for now --- .travis.yml | 5 +++++ README.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 20b1123..94002b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,8 @@ go: - 1.9x - tip +# safelist +branches: + only: + - master + - v2 \ No newline at end of file diff --git a/README.md b/README.md index f4b4ad7..bcea8ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Gomail -[![Build Status](https://travis-ci.org/go-mail/gomail.svg?branch=v2)](https://travis-ci.org/go-mail/gomail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/gomail)](http://gocover.io/github.com/go-mail/gomail) [![Documentation](https://godoc.org/github.com/go-mail/gomail?status.svg)](https://godoc.org/github.com/go-mail/gomail) +[![Build Status](https://travis-ci.org/go-mail/gomail.svg?branch=master)](https://travis-ci.org/go-mail/gomail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/gomail)](http://gocover.io/github.com/go-mail/gomail) [![Documentation](https://godoc.org/github.com/go-mail/gomail?status.svg)](https://godoc.org/github.com/go-mail/gomail) **IMPORTANT** - This is a fork of [go-gomail/gomail](https://github.com/go-gomail/gomail). See this [issue#104](https://github.com/go-gomail/gomail/issues/104) From 00ccffbd4f849b93cd9f69cd6b1422af7819a771 Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 21:47:27 +0000 Subject: [PATCH 11/34] gitter --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a849d6a..d3434a6 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,9 @@ See [CHANGELOG.md](CHANGELOG.md). [MIT](LICENSE) -## Contact +## Support & Contact + +[![Join the chat at https://gitter.im/gomail-community/Lobby](https://badges.gitter.im/gomail-community/Lobby.svg)](https://gitter.im/gomail-community/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) You can ask questions on the [Gomail thread](https://groups.google.com/d/topic/golang-nuts/jMxZHzvvEVg/discussion) From 875d2d5c7ae9996c18e0d49ed3d6893d031221cd Mon Sep 17 00:00:00 2001 From: pedromorgan Date: Wed, 6 Dec 2017 22:13:49 +0000 Subject: [PATCH 12/34] revert removal < 1.5 and small fixes --- .travis.yml | 8 +++++++- README.md | 2 +- mime.go | 1 + mime_go14.go | 25 +++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 mime_go14.go diff --git a/.travis.yml b/.travis.yml index 94002b3..0a1e5ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ language: go go: + - 1.2x + - 1.3x + - 1.4x - 1.5x - 1.6x - 1.7x @@ -12,4 +15,7 @@ go: branches: only: - master - - v2 \ No newline at end of file + - v2 + +notifications: + email: false \ No newline at end of file diff --git a/README.md b/README.md index d3434a6..b416b76 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ is easy to implement other methods for sending emails using a local Postfix, an API, etc. -It requires Go 1.5 or newer. +It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used. ## Features diff --git a/mime.go b/mime.go index 3aab82d..194d4a7 100644 --- a/mime.go +++ b/mime.go @@ -1,3 +1,4 @@ +// +build go1.5 package gomail diff --git a/mime_go14.go b/mime_go14.go new file mode 100644 index 0000000..3dc26aa --- /dev/null +++ b/mime_go14.go @@ -0,0 +1,25 @@ +// +build !go1.5 + +package gomail + +import "gopkg.in/alexcesaro/quotedprintable.v3" + +var newQPWriter = quotedprintable.NewWriter + +type mimeEncoder struct { + quotedprintable.WordEncoder +} + +var ( + bEncoding = mimeEncoder{quotedprintable.BEncoding} + qEncoding = mimeEncoder{quotedprintable.QEncoding} + lastIndexByte = func(s string, c byte) int { + for i := len(s) - 1; i >= 0; i-- { + + if s[i] == c { + return i + } + } + return -1 + } +) From 45ab546e07939a7cdd144f97a05ddcec2179dc41 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 9 Dec 2016 10:23:40 -0800 Subject: [PATCH 13/34] Allow timeout in connections, retries to be configurable [Ivy: update to use NetDialTimeout] --- smtp.go | 47 ++++++++++++++++++++++++++++++++++++++--------- smtp_test.go | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/smtp.go b/smtp.go index b523f15..6137e14 100644 --- a/smtp.go +++ b/smtp.go @@ -33,17 +33,24 @@ type Dialer struct { // LocalName is the hostname sent to the SMTP server with the HELO command. // By default, "localhost" is sent. LocalName string + // Timeout to use for read/write operations. Defaults to 10 seconds, can + // be set to 0 to disable timeouts. + Timeout time.Duration + // Whether we should retry mailing if the connection returned an error. + RetryFailure bool } // NewDialer returns a new SMTP Dialer. The given parameters are used to connect // to the SMTP server. func NewDialer(host string, port int, username, password string) *Dialer { return &Dialer{ - Host: host, - Port: port, - Username: username, - Password: password, - SSL: port == 465, + Host: host, + Port: port, + Username: username, + Password: password, + SSL: port == 465, + Timeout: 10 * time.Second, + RetryFailure: true, } } @@ -63,7 +70,7 @@ var NetDialTimeout = net.DialTimeout // Dial dials and authenticates to an SMTP server. The returned SendCloser // should be closed when done using it. func (d *Dialer) Dial() (SendCloser, error) { - conn, err := NetDialTimeout("tcp", addr(d.Host, d.Port), 10*time.Second) + conn, err := NetDialTimeout("tcp", addr(d.Host, d.Port), d.Timeout) if err != nil { return nil, err } @@ -77,6 +84,10 @@ func (d *Dialer) Dial() (SendCloser, error) { return nil, err } + if d.Timeout > 0 { + conn.SetDeadline(time.Now().Add(d.Timeout)) + } + if d.LocalName != "" { if err := c.Hello(d.LocalName); err != nil { return nil, err @@ -116,7 +127,7 @@ func (d *Dialer) Dial() (SendCloser, error) { } } - return &smtpSender{c, d}, nil + return &smtpSender{c, conn, d}, nil } func (d *Dialer) tlsConfig() *tls.Config { @@ -144,12 +155,29 @@ func (d *Dialer) DialAndSend(m ...*Message) error { type smtpSender struct { smtpClient - d *Dialer + conn net.Conn + d *Dialer +} + +func (c *smtpSender) retryError(err error) bool { + if !c.d.RetryFailure { + return false + } + + if nerr, ok := err.(net.Error); ok && nerr.Timeout() { + return true + } + + return err == io.EOF } func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { + if c.d.Timeout > 0 { + c.conn.SetDeadline(time.Now().Add(c.d.Timeout)) + } + if err := c.Mail(from); err != nil { - if err == io.EOF { + if c.retryError(err) { // This is probably due to a timeout, so reconnect and try again. sc, derr := c.d.Dial() if derr == nil { @@ -159,6 +187,7 @@ func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { } } } + return err } diff --git a/smtp_test.go b/smtp_test.go index 3323029..3f62a87 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -18,7 +18,7 @@ const ( var ( testConn = &net.TCPConn{} - testTLSConn = &tls.Conn{} + testTLSConn = tls.Client(testConn, &tls.Config{InsecureSkipVerify: true}) testConfig = &tls.Config{InsecureSkipVerify: true} testAuth = smtp.PlainAuth("", testUser, testPwd, testHost) ) @@ -118,8 +118,9 @@ func TestDialerNoAuth(t *testing.T) { func TestDialerTimeout(t *testing.T) { d := &Dialer{ - Host: testHost, - Port: testPort, + Host: testHost, + Port: testPort, + RetryFailure: true, } testSendMailTimeout(t, d, []string{ "Extension STARTTLS", @@ -138,6 +139,25 @@ func TestDialerTimeout(t *testing.T) { }) } +func TestDialerTimeoutNoRetry(t *testing.T) { + d := &Dialer{ + Host: testHost, + Port: testPort, + RetryFailure: false, + } + + err := doTestSendMail(t, d, []string{ + "Extension STARTTLS", + "StartTLS", + "Mail " + testFrom, + "Quit", + }, true) + + if err.Error() != "gomail: could not send email 1: EOF" { + t.Error("expected to have got EOF, but got:", err) + } +} + type mockClient struct { t *testing.T i int @@ -232,14 +252,18 @@ func (w *mockWriter) Close() error { } func testSendMail(t *testing.T, d *Dialer, want []string) { - doTestSendMail(t, d, want, false) + if err := doTestSendMail(t, d, want, false); err != nil { + t.Error(err) + } } func testSendMailTimeout(t *testing.T, d *Dialer, want []string) { - doTestSendMail(t, d, want, true) + if err := doTestSendMail(t, d, want, true); err != nil { + t.Error(err) + } } -func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { +func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) error { testClient := &mockClient{ t: t, want: want, @@ -274,9 +298,7 @@ func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { return testClient, nil } - if err := d.DialAndSend(getTestMessage()); err != nil { - t.Error(err) - } + return d.DialAndSend(getTestMessage()) } func assertConfig(t *testing.T, got, want *tls.Config) { From 0fb88094b41f07124affe1ed6953ec3565b0237c Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 16:47:46 -0800 Subject: [PATCH 14/34] Document default Dialer.RetryFailure --- smtp.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/smtp.go b/smtp.go index 6137e14..1214f08 100644 --- a/smtp.go +++ b/smtp.go @@ -36,7 +36,8 @@ type Dialer struct { // Timeout to use for read/write operations. Defaults to 10 seconds, can // be set to 0 to disable timeouts. Timeout time.Duration - // Whether we should retry mailing if the connection returned an error. + // Whether we should retry mailing if the connection returned an error, + // defaults to true. RetryFailure bool } From 8367efd91c1b3d1990f9d6f2d8b939808c60a887 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 19:10:00 -0800 Subject: [PATCH 15/34] Remove gitter badge --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index b416b76..7c93120 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,6 @@ See [CHANGELOG.md](CHANGELOG.md). ## Support & Contact -[![Join the chat at https://gitter.im/gomail-community/Lobby](https://badges.gitter.im/gomail-community/Lobby.svg)](https://gitter.im/gomail-community/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - You can ask questions on the [Gomail thread](https://groups.google.com/d/topic/golang-nuts/jMxZHzvvEVg/discussion) in the Go mailing-list. From 1e5036aa1b916b6fe5f942b569f101afa195d86d Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 19:29:48 -0800 Subject: [PATCH 16/34] Rename package to mail This change allows importing as: import "gopkg.in/mail.v2" --- auth.go | 2 +- auth_test.go | 2 +- doc.go | 4 ++-- example_test.go | 47 +++++++++++++++++++++++------------------------ message.go | 2 +- message_test.go | 2 +- mime.go | 2 +- mime_go14.go | 4 +--- send.go | 6 +++--- send_test.go | 2 +- smtp.go | 2 +- smtp_test.go | 2 +- writeto.go | 2 +- 13 files changed, 38 insertions(+), 41 deletions(-) diff --git a/auth.go b/auth.go index d28b83a..b8c0dde 100644 --- a/auth.go +++ b/auth.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "bytes" diff --git a/auth_test.go b/auth_test.go index 428ef34..604795e 100644 --- a/auth_test.go +++ b/auth_test.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "net/smtp" diff --git a/doc.go b/doc.go index ff3883d..d65bf35 100644 --- a/doc.go +++ b/doc.go @@ -1,6 +1,6 @@ // Package gomail provides a simple interface to compose emails and to mail them // efficiently. // -// More info on Github: https://github.com/go-mail/gomail +// More info on Github: https://github.com/go-mail/mail // -package gomail +package mail diff --git a/example_test.go b/example_test.go index 1f5a0b8..c9fd3fe 100644 --- a/example_test.go +++ b/example_test.go @@ -1,4 +1,4 @@ -package gomail_test +package mail_test import ( "fmt" @@ -7,12 +7,11 @@ import ( "log" "time" - //"gopkg.in/gomail.v2" - we forked - "github.com/go-mail/gomail" + "gopkg.in/mail.v2" ) func Example() { - m := gomail.NewMessage() + m := mail.NewMessage() m.SetHeader("From", "alex@example.com") m.SetHeader("To", "bob@example.com", "cora@example.com") m.SetAddressHeader("Cc", "dan@example.com", "Dan") @@ -20,7 +19,7 @@ func Example() { m.SetBody("text/html", "Hello Bob and Cora!") m.Attach("/home/Alex/lolcat.jpg") - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := mail.NewDialer("smtp.example.com", 587, "user", "123456") // Send the email to Bob, Cora and Dan. if err := d.DialAndSend(m); err != nil { @@ -30,12 +29,12 @@ func Example() { // A daemon that listens to a channel and sends all incoming messages. func Example_daemon() { - ch := make(chan *gomail.Message) + ch := make(chan *mail.Message) go func() { - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := mail.NewDialer("smtp.example.com", 587, "user", "123456") - var s gomail.SendCloser + var s mail.SendCloser var err error open := false for { @@ -50,7 +49,7 @@ func Example_daemon() { } open = true } - if err := gomail.Send(s, m); err != nil { + if err := mail.Send(s, m); err != nil { log.Print(err) } // Close the connection to the SMTP server if no email was sent in @@ -80,20 +79,20 @@ func Example_newsletter() { Address string } - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := mail.NewDialer("smtp.example.com", 587, "user", "123456") s, err := d.Dial() if err != nil { panic(err) } - m := gomail.NewMessage() + m := mail.NewMessage() for _, r := range list { m.SetHeader("From", "no-reply@example.com") m.SetAddressHeader("To", r.Address, r.Name) m.SetHeader("Subject", "Newsletter #1") m.SetBody("text/html", fmt.Sprintf("Hello %s!", r.Name)) - if err := gomail.Send(s, m); err != nil { + if err := mail.Send(s, m); err != nil { log.Printf("Could not send email to %q: %v", r.Address, err) } m.Reset() @@ -102,13 +101,13 @@ func Example_newsletter() { // Send an email using a local SMTP server. func Example_noAuth() { - m := gomail.NewMessage() + m := mail.NewMessage() m.SetHeader("From", "from@example.com") m.SetHeader("To", "to@example.com") m.SetHeader("Subject", "Hello!") m.SetBody("text/plain", "Hello!") - d := gomail.Dialer{Host: "localhost", Port: 587} + d := mail.Dialer{Host: "localhost", Port: 587} if err := d.DialAndSend(m); err != nil { panic(err) } @@ -116,13 +115,13 @@ func Example_noAuth() { // Send an email using an API or postfix. func Example_noSMTP() { - m := gomail.NewMessage() + m := mail.NewMessage() m.SetHeader("From", "from@example.com") m.SetHeader("To", "to@example.com") m.SetHeader("Subject", "Hello!") m.SetBody("text/plain", "Hello!") - s := gomail.SendFunc(func(from string, to []string, msg io.WriterTo) error { + s := mail.SendFunc(func(from string, to []string, msg io.WriterTo) error { // Implements you email-sending function, for example by calling // an API, or running postfix, etc. fmt.Println("From:", from) @@ -130,7 +129,7 @@ func Example_noSMTP() { return nil }) - if err := gomail.Send(s, m); err != nil { + if err := mail.Send(s, m); err != nil { panic(err) } // Output: @@ -138,10 +137,10 @@ func Example_noSMTP() { // To: [to@example.com] } -var m *gomail.Message +var m *mail.Message func ExampleSetCopyFunc() { - m.Attach("foo.txt", gomail.SetCopyFunc(func(w io.Writer) error { + m.Attach("foo.txt", mail.SetCopyFunc(func(w io.Writer) error { _, err := w.Write([]byte("Content of foo.txt")) return err })) @@ -149,11 +148,11 @@ func ExampleSetCopyFunc() { func ExampleSetHeader() { h := map[string][]string{"Content-ID": {""}} - m.Attach("foo.jpg", gomail.SetHeader(h)) + m.Attach("foo.jpg", mail.SetHeader(h)) } func ExampleRename() { - m.Attach("/tmp/0000146.jpg", gomail.Rename("picture.jpg")) + m.Attach("/tmp/0000146.jpg", mail.Rename("picture.jpg")) } func ExampleMessage_AddAlternative() { @@ -212,13 +211,13 @@ func ExampleMessage_SetHeaders() { } func ExampleSetCharset() { - m = gomail.NewMessage(gomail.SetCharset("ISO-8859-1")) + m = mail.NewMessage(mail.SetCharset("ISO-8859-1")) } func ExampleSetEncoding() { - m = gomail.NewMessage(gomail.SetEncoding(gomail.Base64)) + m = mail.NewMessage(mail.SetEncoding(mail.Base64)) } func ExampleSetPartEncoding() { - m.SetBody("text/plain", "Hello!", gomail.SetPartEncoding(gomail.Unencoded)) + m.SetBody("text/plain", "Hello!", mail.SetPartEncoding(mail.Unencoded)) } diff --git a/message.go b/message.go index 4bffb1e..eb81efd 100644 --- a/message.go +++ b/message.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "bytes" diff --git a/message_test.go b/message_test.go index acceff2..1a12ec3 100644 --- a/message_test.go +++ b/message_test.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "bytes" diff --git a/mime.go b/mime.go index 194d4a7..d95ea2e 100644 --- a/mime.go +++ b/mime.go @@ -1,6 +1,6 @@ // +build go1.5 -package gomail +package mail import ( "mime" diff --git a/mime_go14.go b/mime_go14.go index 3dc26aa..e12ab2e 100644 --- a/mime_go14.go +++ b/mime_go14.go @@ -1,8 +1,6 @@ // +build !go1.5 -package gomail - -import "gopkg.in/alexcesaro/quotedprintable.v3" +package mail var newQPWriter = quotedprintable.NewWriter diff --git a/send.go b/send.go index 9115ebe..57c063c 100644 --- a/send.go +++ b/send.go @@ -1,10 +1,10 @@ -package gomail +package mail import ( "errors" "fmt" "io" - "net/mail" + stdmail "net/mail" ) // Sender is the interface that wraps the Send method. @@ -108,7 +108,7 @@ func addAddress(list []string, addr string) []string { } func parseAddress(field string) (string, error) { - addr, err := mail.ParseAddress(field) + addr, err := stdmail.ParseAddress(field) if err != nil { return "", fmt.Errorf("gomail: invalid address %q: %v", field, err) } diff --git a/send_test.go b/send_test.go index ba59cd3..9bf05b9 100644 --- a/send_test.go +++ b/send_test.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "bytes" diff --git a/smtp.go b/smtp.go index 1214f08..5f3566d 100644 --- a/smtp.go +++ b/smtp.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "crypto/tls" diff --git a/smtp_test.go b/smtp_test.go index 3f62a87..7ed47c0 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "bytes" diff --git a/writeto.go b/writeto.go index 9fb6b86..22581ab 100644 --- a/writeto.go +++ b/writeto.go @@ -1,4 +1,4 @@ -package gomail +package mail import ( "encoding/base64" From a691f0477ceb93aca723b39da6cfcc6e9eb74a2b Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 19:30:53 -0800 Subject: [PATCH 17/34] Update readme with gopkg.in import path --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7c93120..611b2fa 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ # Gomail -[![Build Status](https://travis-ci.org/go-mail/gomail.svg?branch=master)](https://travis-ci.org/go-mail/gomail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/gomail)](http://gocover.io/github.com/go-mail/gomail) [![Documentation](https://godoc.org/github.com/go-mail/gomail?status.svg)](https://godoc.org/github.com/go-mail/gomail) - -**IMPORTANT** - This is a fork of [go-gomail/gomail](https://github.com/go-gomail/gomail). See this [issue#104](https://github.com/go-gomail/gomail/issues/104) - +[![Build Status](https://travis-ci.org/go-mail/mail.svg?branch=master)](https://travis-ci.org/go-mail/mail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/mail)](http://gocover.io/github.com/go-mail/mail) [![Documentation](https://godoc.org/github.com/go-mail/mail?status.svg)](https://godoc.org/github.com/go-mail/mail) ## Introduction @@ -13,7 +10,6 @@ Gomail can only send emails using an SMTP server. But the API is flexible and it is easy to implement other methods for sending emails using a local Postfix, an API, etc. - It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used. @@ -30,12 +26,12 @@ Gomail supports: ## Documentation -https://godoc.org/github.com/go-mail/gomail +https://godoc.org/github.com/go-mail/mail ## Download - go get github.com/go-mail/gomail + go get gopkg.in/mail.v2 ## Examples From c6c7e1d2cbf7ffdac4e0d918b9719af4f45c4577 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 19:36:12 -0800 Subject: [PATCH 18/34] Fix import path in readme example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 611b2fa..8ccd1b6 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ package main import ( "crypto/tls" - "github.com/go-mail/gomail" + "gopkg.in/mail.v2" ) func main() { From 6a770e935baf5699723bdeae9683bb0ad07383af Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 19:37:41 -0800 Subject: [PATCH 19/34] Fix references to old repo name --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8ccd1b6..7a06dbb 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ https://godoc.org/github.com/go-mail/mail ## Examples -See the [examples in the documentation](https://godoc.org/github.com/go-mail/gomail#example-package). +See the [examples in the documentation](https://godoc.org/github.com/go-mail/mail#example-package). ## FAQ @@ -58,7 +58,7 @@ import ( ) func main() { - d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d := mail.NewDialer("smtp.example.com", 587, "user", "123456") d.TLSConfig = &tls.Config{InsecureSkipVerify: true} // Send emails using d. From 7c2224c6189e45bd92aa2a103ec19b7deea34a76 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 20:46:37 -0800 Subject: [PATCH 20/34] travis: Fix incorrectly specified Go versions Changes introduced in 92faf950 were causing all builds to execute using Go 1.7.4. This fixes the config to once again build against each supported Go runtime. --- .travis.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a1e5ca..cba5708 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ language: go go: - - 1.2x - - 1.3x - - 1.4x - - 1.5x - - 1.6x - - 1.7x - - 1.8x - - 1.9x + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 - tip # safelist @@ -18,4 +18,4 @@ branches: - v2 notifications: - email: false \ No newline at end of file + email: false From 1f3725f4f60ed3fb92e7c3ef576aeb7ebc283d52 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 6 Dec 2017 20:52:04 -0800 Subject: [PATCH 21/34] Fix missing import in mime_go14.go The import statement for quotedprintable was accidentally removed during the package rename in 1e5036a. --- mime_go14.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mime_go14.go b/mime_go14.go index e12ab2e..bdb605d 100644 --- a/mime_go14.go +++ b/mime_go14.go @@ -2,6 +2,8 @@ package mail +import "gopkg.in/alexcesaro/quotedprintable.v3" + var newQPWriter = quotedprintable.NewWriter type mimeEncoder struct { From ef373989c852ddaa6c5f586c8d988f248ecb7892 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Thu, 7 Dec 2017 15:20:54 -0800 Subject: [PATCH 22/34] Document progress and steps for transitioning --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 7a06dbb..11eb6a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,23 @@ # Gomail [![Build Status](https://travis-ci.org/go-mail/mail.svg?branch=master)](https://travis-ci.org/go-mail/mail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/mail)](http://gocover.io/github.com/go-mail/mail) [![Documentation](https://godoc.org/github.com/go-mail/mail?status.svg)](https://godoc.org/github.com/go-mail/mail) +This is an actively maintained fork of [Gomail][1] and includes fixes and +improvements for a number of outstanding issues. The current progress is +as follows: + + - [x] Timeouts and retries can be specified outside of the 10 second default. + - [x] Proxying is supported through specifying a custom [NetDialTimeout][2]. + - [ ] Filenames are properly encoded for non-ASCII characters. + - [ ] Email addresses are properly encoded for non-ASCII characters. + - [ ] Embedded files and attachments are tested for their existence. + - [ ] An `io.Reader` can be supplied when embedding and attaching files. + +See [Transitioning Existing Codebases][3] for more information on switching. + +[1]: https://github.com/go-gomail/gomail +[2]: https://godoc.org/gopkg.in/mail.v2#NetDialTimeout +[3]: #transitioning-existing-codebases + ## Introduction Gomail is a simple and efficient package to send emails. It is well tested and @@ -67,6 +84,14 @@ func main() { Note, however, that this is insecure and should not be used in production. +### Transitioning Existing Codebases + +If you're already using the original Gomail, switching is as easy as updating +the import line to: + +``` +import gomail "gopkg.in/mail.v2" +``` ## Contribute From 71893bb665124aedd7282464cea0f6ad7554b0ca Mon Sep 17 00:00:00 2001 From: Rienzi Date: Fri, 8 Dec 2017 23:47:29 -0500 Subject: [PATCH 23/34] Added teardown method for files --- message_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/message_test.go b/message_test.go index 210b2d4..de0aeed 100644 --- a/message_test.go +++ b/message_test.go @@ -257,6 +257,9 @@ func TestAttachmentOnly(t *testing.T) { } testMessage(t, m, 0, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } } func TestAttachment(t *testing.T) { @@ -289,6 +292,9 @@ func TestAttachment(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } } func TestRename(t *testing.T) { @@ -326,6 +332,9 @@ func TestRename(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } } func TestAttachmentsOnly(t *testing.T) { @@ -359,6 +368,12 @@ func TestAttachmentsOnly(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } + if err := teardownFile("/tmp/test.zip"); err != nil { + panic(err) + } } func TestAttachments(t *testing.T) { @@ -398,6 +413,12 @@ func TestAttachments(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } + if err := teardownFile("/tmp/test.zip"); err != nil { + panic(err) + } } func TestEmbedded(t *testing.T) { @@ -439,6 +460,12 @@ func TestEmbedded(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("image1.jpg"); err != nil { + panic(err) + } + if err := teardownFile("image2.jpg"); err != nil { + panic(err) + } } func TestFullMessage(t *testing.T) { @@ -498,6 +525,14 @@ func TestFullMessage(t *testing.T) { testMessage(t, m, 3, want) + if err := teardownFile("test.pdf"); err != nil { + panic(err) + } + if err := teardownFile("image.jpg"); err != nil { + panic(err) + } + + want = &message{ from: "from@example.com", to: []string{"to@example.com"}, @@ -721,6 +756,10 @@ func mockCopyFileWithHeader(m *Message, name string, h map[string][]string) (str return name, f, SetHeader(h) } +func teardownFile(name string) err { + return os.Remove(filepath.Base(name)) +} + func BenchmarkFull(b *testing.B) { discardFunc := SendFunc(func(from string, to []string, m io.WriterTo) error { _, err := m.WriteTo(ioutil.Discard) @@ -746,5 +785,11 @@ func BenchmarkFull(b *testing.B) { panic(err) } m.Reset() + if err := teardownFile("benchmark.txt"); err != nil { + panic(err) + } + if err := teardownFile("benchmark.jpg"); err != nil { + panic(err) + } } } From cd0ee1215429d1c4444797de8a2607b2b29a581b Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 20:48:19 -0500 Subject: [PATCH 24/34] Removed Rename File Creation --- message_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/message_test.go b/message_test.go index de0aeed..467a136 100644 --- a/message_test.go +++ b/message_test.go @@ -304,7 +304,6 @@ func TestRename(t *testing.T) { m.SetBody("text/plain", "Test") name, copy := mockCopyFile("/tmp/test.pdf") rename := Rename("another.pdf") - os.Create("another.pdf") m.Attach(name, copy, rename) From 8a0aa6287002b48da8fdfb53ee4a8f1bb48a021b Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 20:52:30 -0500 Subject: [PATCH 25/34] Fixed Build Typo --- message_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message_test.go b/message_test.go index 467a136..ea3d7f5 100644 --- a/message_test.go +++ b/message_test.go @@ -755,7 +755,7 @@ func mockCopyFileWithHeader(m *Message, name string, h map[string][]string) (str return name, f, SetHeader(h) } -func teardownFile(name string) err { +func teardownFile(name string) error { return os.Remove(filepath.Base(name)) } From 8ca38acf0e469692f140cbae73fea07341ae1139 Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:11:41 -0500 Subject: [PATCH 26/34] Added originalName property for file --- message.go | 2 ++ send.go | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/message.go b/message.go index 4bffb1e..725125a 100644 --- a/message.go +++ b/message.go @@ -240,6 +240,7 @@ func SetPartEncoding(e Encoding) PartSetting { type file struct { Name string + originalName string Header map[string][]string CopyFunc func(w io.Writer) error } @@ -285,6 +286,7 @@ func SetCopyFunc(f func(io.Writer) error) FileSetting { func (m *Message) appendFile(list []*file, name string, settings []FileSetting) []*file { f := &file{ + originalName: name, Name: filepath.Base(name), Header: make(map[string][]string), CopyFunc: func(w io.Writer) error { diff --git a/send.go b/send.go index b0cd0a4..99a6dd8 100644 --- a/send.go +++ b/send.go @@ -104,12 +104,12 @@ func (m *Message) getRecipients() ([]string, error) { func (m *Message) checkEmbedsAndAttachments() error { for _, file := range m.embedded { - if _, err := os.Stat(file.Name); err != nil { + if _, err := os.Stat(file.originalName); err != nil { return err } } for _, file := range m.attachments { - if _, err := os.Stat(file.Name); err != nil { + if _, err := os.Stat(file.originalName); err != nil { return err } } From c491950f38546874b49e4bf139ad1538672e355f Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:14:52 -0500 Subject: [PATCH 27/34] Fixed Typo with originalName --- message.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message.go b/message.go index 725125a..7733e5e 100644 --- a/message.go +++ b/message.go @@ -286,7 +286,7 @@ func SetCopyFunc(f func(io.Writer) error) FileSetting { func (m *Message) appendFile(list []*file, name string, settings []FileSetting) []*file { f := &file{ - originalName: name, + originalName: filepath.Base(name), Name: filepath.Base(name), Header: make(map[string][]string), CopyFunc: func(w io.Writer) error { From 09b474da1c02d79df78a354b884acaef1662d89f Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:21:04 -0500 Subject: [PATCH 28/34] Added Tests for Embed/Attachment Validation --- send_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/send_test.go b/send_test.go index ba59cd3..f8d12aa 100644 --- a/send_test.go +++ b/send_test.go @@ -50,6 +50,47 @@ func TestSend(t *testing.T) { } } +func TestSendValidatesEmbeds(t *testing.T) { + s := &mockSendCloser{ + mockSender: stubSend(t, testFrom, []string{testTo1, testTo2}, testMsg), + close: func() error { + t.Error("Close() should not be called in Send()") + return nil + }, + } + + m := getTestMessage() + m.Embed("this-file-does-not-exist") + + err := Send(s, m) + if err == nil || !strings.HasSuffix(err.Error(), + "no such file or directory") { + t.Errorf("Send(): expected stat error but got %v", err) + } +} + + +func TestSendValidatesAttachments(t *testing.T) { + s := &mockSendCloser{ + mockSender: stubSend(t, testFrom, []string{testTo1, testTo2}, testMsg), + close: func() error { + t.Error("Close() should not be called in Send()") + return nil + }, + } + + m := getTestMessage() + m.Attach("this-file-does-not-exist") + + err := Send(s, m) + if err == nil || !strings.HasSuffix(err.Error(), + "no such file or directory") { + t.Errorf("Send(): expected stat error but got %v", err) + } +} + + + func getTestMessage() *Message { m := NewMessage() m.SetHeader("From", testFrom) From c117660e17a3bf344286d2806111ba0f80bc237e Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:23:24 -0500 Subject: [PATCH 29/34] Fogot to add strings import --- send_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/send_test.go b/send_test.go index f8d12aa..a5b426f 100644 --- a/send_test.go +++ b/send_test.go @@ -5,6 +5,7 @@ import ( "io" "reflect" "testing" + "strings" ) const ( From f5e292ee7b7f1c063995d3ca23f2e5b7d2d921bc Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:48:13 -0500 Subject: [PATCH 30/34] Removed first net/mail import --- send.go | 1 - 1 file changed, 1 deletion(-) diff --git a/send.go b/send.go index e14295d..241982c 100644 --- a/send.go +++ b/send.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "io" - "net/mail" "os" stdmail "net/mail" ) From 4a60beb645762fe11b64d54ef245eb4417c4d9fb Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:52:27 -0500 Subject: [PATCH 31/34] Revert "Fogot to add strings import" This reverts commit c117660e17a3bf344286d2806111ba0f80bc237e. --- send_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/send_test.go b/send_test.go index 0e8496c..53ca7ec 100644 --- a/send_test.go +++ b/send_test.go @@ -5,7 +5,6 @@ import ( "io" "reflect" "testing" - "strings" ) const ( From aaa67cd09604263226cdfd244dac64fd11768134 Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:57:29 -0500 Subject: [PATCH 32/34] Revert A bunch of things This reverts commit 4a60beb645762fe11b64d54ef245eb4417c4d9fb. --- send_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/send_test.go b/send_test.go index 53ca7ec..0e8496c 100644 --- a/send_test.go +++ b/send_test.go @@ -5,6 +5,7 @@ import ( "io" "reflect" "testing" + "strings" ) const ( From bafcd8493c9587bca5871c2935699032a88d1e16 Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:57:59 -0500 Subject: [PATCH 33/34] Revert "Removed first net/mail import" This reverts commit f5e292ee7b7f1c063995d3ca23f2e5b7d2d921bc. --- send.go | 1 + 1 file changed, 1 insertion(+) diff --git a/send.go b/send.go index 241982c..e14295d 100644 --- a/send.go +++ b/send.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io" + "net/mail" "os" stdmail "net/mail" ) From 3e277d0e96f13b2a24cd564aa62412f069f3457e Mon Sep 17 00:00:00 2001 From: Rienzi Date: Sat, 9 Dec 2017 21:59:34 -0500 Subject: [PATCH 34/34] Revert "Merge branch 'v2' into Fixing-Attachment-Error" This reverts commit c273b3f2ebc55da7c8048695697d6501d081ca25, reversing changes made to c117660e17a3bf344286d2806111ba0f80bc237e. --- .gitignore | 17 -------------- .travis.yml | 12 ---------- CHANGELOG.md | 3 --- README.md | 60 +++++++++++++++---------------------------------- auth.go | 2 +- auth_test.go | 2 +- doc.go | 5 ++--- example_test.go | 46 ++++++++++++++++++------------------- message.go | 2 +- message_test.go | 2 +- mime.go | 2 +- mime_go14.go | 2 +- send.go | 5 ++--- send_test.go | 2 +- smtp.go | 60 +++++++++++-------------------------------------- smtp_test.go | 44 +++++++++--------------------------- writeto.go | 2 +- 17 files changed, 77 insertions(+), 191 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index cc4721c..0000000 --- a/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ - - -# Binaries for programs and plugins -*.exe -*.dll -*.so -*.dylib - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - - -# IDE's -.idea/ diff --git a/.travis.yml b/.travis.yml index cba5708..48915e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,16 +6,4 @@ go: - 1.4 - 1.5 - 1.6 - - 1.7 - - 1.8 - - 1.9 - tip - -# safelist -branches: - only: - - master - - v2 - -notifications: - email: false diff --git a/CHANGELOG.md b/CHANGELOG.md index be37fba..a797ab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,6 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## 2017-12-06 Original project forked -https://github.com/go-gomail/gomail/issues/104 - ## [2.0.0] - 2015-09-02 - Mailer has been removed. It has been replaced by Dialer and Sender. diff --git a/README.md b/README.md index 11eb6a8..b3be9e1 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,5 @@ # Gomail -[![Build Status](https://travis-ci.org/go-mail/mail.svg?branch=master)](https://travis-ci.org/go-mail/mail) [![Code Coverage](http://gocover.io/_badge/github.com/go-mail/mail)](http://gocover.io/github.com/go-mail/mail) [![Documentation](https://godoc.org/github.com/go-mail/mail?status.svg)](https://godoc.org/github.com/go-mail/mail) - -This is an actively maintained fork of [Gomail][1] and includes fixes and -improvements for a number of outstanding issues. The current progress is -as follows: - - - [x] Timeouts and retries can be specified outside of the 10 second default. - - [x] Proxying is supported through specifying a custom [NetDialTimeout][2]. - - [ ] Filenames are properly encoded for non-ASCII characters. - - [ ] Email addresses are properly encoded for non-ASCII characters. - - [ ] Embedded files and attachments are tested for their existence. - - [ ] An `io.Reader` can be supplied when embedding and attaching files. - -See [Transitioning Existing Codebases][3] for more information on switching. - -[1]: https://github.com/go-gomail/gomail -[2]: https://godoc.org/gopkg.in/mail.v2#NetDialTimeout -[3]: #transitioning-existing-codebases +[![Build Status](https://travis-ci.org/go-gomail/gomail.svg?branch=v2)](https://travis-ci.org/go-gomail/gomail) [![Code Coverage](http://gocover.io/_badge/gopkg.in/gomail.v2)](http://gocover.io/gopkg.in/gomail.v2) [![Documentation](https://godoc.org/gopkg.in/gomail.v2?status.svg)](https://godoc.org/gopkg.in/gomail.v2) ## Introduction @@ -27,6 +10,9 @@ Gomail can only send emails using an SMTP server. But the API is flexible and it is easy to implement other methods for sending emails using a local Postfix, an API, etc. +It is versioned using [gopkg.in](https://gopkg.in) so I promise +there will never be backward incompatible changes within each version. + It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used. @@ -43,17 +29,17 @@ Gomail supports: ## Documentation -https://godoc.org/github.com/go-mail/mail +https://godoc.org/gopkg.in/gomail.v2 ## Download - go get gopkg.in/mail.v2 + go get gopkg.in/gomail.v2 ## Examples -See the [examples in the documentation](https://godoc.org/github.com/go-mail/mail#example-package). +See the [examples in the documentation](https://godoc.org/gopkg.in/gomail.v2#example-package). ## FAQ @@ -65,33 +51,23 @@ considered valid by the client running Gomail. As a quick workaround you can bypass the verification of the server's certificate chain and host name by using `SetTLSConfig`: -```go -package main + package main -import ( - "crypto/tls" + import ( + "crypto/tls" - "gopkg.in/mail.v2" -) + "gopkg.in/gomail.v2" + ) -func main() { - d := mail.NewDialer("smtp.example.com", 587, "user", "123456") - d.TLSConfig = &tls.Config{InsecureSkipVerify: true} + func main() { + d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") + d.TLSConfig = &tls.Config{InsecureSkipVerify: true} - // Send emails using d. -} -``` + // Send emails using d. + } Note, however, that this is insecure and should not be used in production. -### Transitioning Existing Codebases - -If you're already using the original Gomail, switching is as easy as updating -the import line to: - -``` -import gomail "gopkg.in/mail.v2" -``` ## Contribute @@ -109,7 +85,7 @@ See [CHANGELOG.md](CHANGELOG.md). [MIT](LICENSE) -## Support & Contact +## Contact You can ask questions on the [Gomail thread](https://groups.google.com/d/topic/golang-nuts/jMxZHzvvEVg/discussion) diff --git a/auth.go b/auth.go index b8c0dde..d28b83a 100644 --- a/auth.go +++ b/auth.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "bytes" diff --git a/auth_test.go b/auth_test.go index 604795e..428ef34 100644 --- a/auth_test.go +++ b/auth_test.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "net/smtp" diff --git a/doc.go b/doc.go index d65bf35..a8f5091 100644 --- a/doc.go +++ b/doc.go @@ -1,6 +1,5 @@ // Package gomail provides a simple interface to compose emails and to mail them // efficiently. // -// More info on Github: https://github.com/go-mail/mail -// -package mail +// More info on Github: https://github.com/go-gomail/gomail +package gomail diff --git a/example_test.go b/example_test.go index c9fd3fe..90008ab 100644 --- a/example_test.go +++ b/example_test.go @@ -1,4 +1,4 @@ -package mail_test +package gomail_test import ( "fmt" @@ -7,11 +7,11 @@ import ( "log" "time" - "gopkg.in/mail.v2" + "gopkg.in/gomail.v2" ) func Example() { - m := mail.NewMessage() + m := gomail.NewMessage() m.SetHeader("From", "alex@example.com") m.SetHeader("To", "bob@example.com", "cora@example.com") m.SetAddressHeader("Cc", "dan@example.com", "Dan") @@ -19,7 +19,7 @@ func Example() { m.SetBody("text/html", "Hello Bob and Cora!") m.Attach("/home/Alex/lolcat.jpg") - d := mail.NewDialer("smtp.example.com", 587, "user", "123456") + d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") // Send the email to Bob, Cora and Dan. if err := d.DialAndSend(m); err != nil { @@ -29,12 +29,12 @@ func Example() { // A daemon that listens to a channel and sends all incoming messages. func Example_daemon() { - ch := make(chan *mail.Message) + ch := make(chan *gomail.Message) go func() { - d := mail.NewDialer("smtp.example.com", 587, "user", "123456") + d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") - var s mail.SendCloser + var s gomail.SendCloser var err error open := false for { @@ -49,7 +49,7 @@ func Example_daemon() { } open = true } - if err := mail.Send(s, m); err != nil { + if err := gomail.Send(s, m); err != nil { log.Print(err) } // Close the connection to the SMTP server if no email was sent in @@ -79,20 +79,20 @@ func Example_newsletter() { Address string } - d := mail.NewDialer("smtp.example.com", 587, "user", "123456") + d := gomail.NewDialer("smtp.example.com", 587, "user", "123456") s, err := d.Dial() if err != nil { panic(err) } - m := mail.NewMessage() + m := gomail.NewMessage() for _, r := range list { m.SetHeader("From", "no-reply@example.com") m.SetAddressHeader("To", r.Address, r.Name) m.SetHeader("Subject", "Newsletter #1") m.SetBody("text/html", fmt.Sprintf("Hello %s!", r.Name)) - if err := mail.Send(s, m); err != nil { + if err := gomail.Send(s, m); err != nil { log.Printf("Could not send email to %q: %v", r.Address, err) } m.Reset() @@ -101,13 +101,13 @@ func Example_newsletter() { // Send an email using a local SMTP server. func Example_noAuth() { - m := mail.NewMessage() + m := gomail.NewMessage() m.SetHeader("From", "from@example.com") m.SetHeader("To", "to@example.com") m.SetHeader("Subject", "Hello!") m.SetBody("text/plain", "Hello!") - d := mail.Dialer{Host: "localhost", Port: 587} + d := gomail.Dialer{Host: "localhost", Port: 587} if err := d.DialAndSend(m); err != nil { panic(err) } @@ -115,13 +115,13 @@ func Example_noAuth() { // Send an email using an API or postfix. func Example_noSMTP() { - m := mail.NewMessage() + m := gomail.NewMessage() m.SetHeader("From", "from@example.com") m.SetHeader("To", "to@example.com") m.SetHeader("Subject", "Hello!") m.SetBody("text/plain", "Hello!") - s := mail.SendFunc(func(from string, to []string, msg io.WriterTo) error { + s := gomail.SendFunc(func(from string, to []string, msg io.WriterTo) error { // Implements you email-sending function, for example by calling // an API, or running postfix, etc. fmt.Println("From:", from) @@ -129,7 +129,7 @@ func Example_noSMTP() { return nil }) - if err := mail.Send(s, m); err != nil { + if err := gomail.Send(s, m); err != nil { panic(err) } // Output: @@ -137,10 +137,10 @@ func Example_noSMTP() { // To: [to@example.com] } -var m *mail.Message +var m *gomail.Message func ExampleSetCopyFunc() { - m.Attach("foo.txt", mail.SetCopyFunc(func(w io.Writer) error { + m.Attach("foo.txt", gomail.SetCopyFunc(func(w io.Writer) error { _, err := w.Write([]byte("Content of foo.txt")) return err })) @@ -148,11 +148,11 @@ func ExampleSetCopyFunc() { func ExampleSetHeader() { h := map[string][]string{"Content-ID": {""}} - m.Attach("foo.jpg", mail.SetHeader(h)) + m.Attach("foo.jpg", gomail.SetHeader(h)) } func ExampleRename() { - m.Attach("/tmp/0000146.jpg", mail.Rename("picture.jpg")) + m.Attach("/tmp/0000146.jpg", gomail.Rename("picture.jpg")) } func ExampleMessage_AddAlternative() { @@ -211,13 +211,13 @@ func ExampleMessage_SetHeaders() { } func ExampleSetCharset() { - m = mail.NewMessage(mail.SetCharset("ISO-8859-1")) + m = gomail.NewMessage(gomail.SetCharset("ISO-8859-1")) } func ExampleSetEncoding() { - m = mail.NewMessage(mail.SetEncoding(mail.Base64)) + m = gomail.NewMessage(gomail.SetEncoding(gomail.Base64)) } func ExampleSetPartEncoding() { - m.SetBody("text/plain", "Hello!", mail.SetPartEncoding(mail.Unencoded)) + m.SetBody("text/plain", "Hello!", gomail.SetPartEncoding(gomail.Unencoded)) } diff --git a/message.go b/message.go index da3a308..7733e5e 100644 --- a/message.go +++ b/message.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "bytes" diff --git a/message_test.go b/message_test.go index 720c873..ea3d7f5 100644 --- a/message_test.go +++ b/message_test.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "os" diff --git a/mime.go b/mime.go index d95ea2e..194d4a7 100644 --- a/mime.go +++ b/mime.go @@ -1,6 +1,6 @@ // +build go1.5 -package mail +package gomail import ( "mime" diff --git a/mime_go14.go b/mime_go14.go index bdb605d..3dc26aa 100644 --- a/mime_go14.go +++ b/mime_go14.go @@ -1,6 +1,6 @@ // +build !go1.5 -package mail +package gomail import "gopkg.in/alexcesaro/quotedprintable.v3" diff --git a/send.go b/send.go index e14295d..99a6dd8 100644 --- a/send.go +++ b/send.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "errors" @@ -6,7 +6,6 @@ import ( "io" "net/mail" "os" - stdmail "net/mail" ) // Sender is the interface that wraps the Send method. @@ -128,7 +127,7 @@ func addAddress(list []string, addr string) []string { } func parseAddress(field string) (string, error) { - addr, err := stdmail.ParseAddress(field) + addr, err := mail.ParseAddress(field) if err != nil { return "", fmt.Errorf("gomail: invalid address %q: %v", field, err) } diff --git a/send_test.go b/send_test.go index 0e8496c..a5b426f 100644 --- a/send_test.go +++ b/send_test.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "bytes" diff --git a/smtp.go b/smtp.go index 5f3566d..2aa49c8 100644 --- a/smtp.go +++ b/smtp.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "crypto/tls" @@ -33,25 +33,17 @@ type Dialer struct { // LocalName is the hostname sent to the SMTP server with the HELO command. // By default, "localhost" is sent. LocalName string - // Timeout to use for read/write operations. Defaults to 10 seconds, can - // be set to 0 to disable timeouts. - Timeout time.Duration - // Whether we should retry mailing if the connection returned an error, - // defaults to true. - RetryFailure bool } // NewDialer returns a new SMTP Dialer. The given parameters are used to connect // to the SMTP server. func NewDialer(host string, port int, username, password string) *Dialer { return &Dialer{ - Host: host, - Port: port, - Username: username, - Password: password, - SSL: port == 465, - Timeout: 10 * time.Second, - RetryFailure: true, + Host: host, + Port: port, + Username: username, + Password: password, + SSL: port == 465, } } @@ -63,15 +55,10 @@ func NewPlainDialer(host string, port int, username, password string) *Dialer { return NewDialer(host, port, username, password) } -// NetDialTimeout specifies the DialTimeout function to establish a connection -// to the SMTP server. This can be used to override dialing in the case that a -// proxy or other special behavior is needed. -var NetDialTimeout = net.DialTimeout - // Dial dials and authenticates to an SMTP server. The returned SendCloser // should be closed when done using it. func (d *Dialer) Dial() (SendCloser, error) { - conn, err := NetDialTimeout("tcp", addr(d.Host, d.Port), d.Timeout) + conn, err := netDialTimeout("tcp", addr(d.Host, d.Port), 10*time.Second) if err != nil { return nil, err } @@ -85,10 +72,6 @@ func (d *Dialer) Dial() (SendCloser, error) { return nil, err } - if d.Timeout > 0 { - conn.SetDeadline(time.Now().Add(d.Timeout)) - } - if d.LocalName != "" { if err := c.Hello(d.LocalName); err != nil { return nil, err @@ -128,7 +111,7 @@ func (d *Dialer) Dial() (SendCloser, error) { } } - return &smtpSender{c, conn, d}, nil + return &smtpSender{c, d}, nil } func (d *Dialer) tlsConfig() *tls.Config { @@ -156,29 +139,12 @@ func (d *Dialer) DialAndSend(m ...*Message) error { type smtpSender struct { smtpClient - conn net.Conn - d *Dialer -} - -func (c *smtpSender) retryError(err error) bool { - if !c.d.RetryFailure { - return false - } - - if nerr, ok := err.(net.Error); ok && nerr.Timeout() { - return true - } - - return err == io.EOF + d *Dialer } func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { - if c.d.Timeout > 0 { - c.conn.SetDeadline(time.Now().Add(c.d.Timeout)) - } - if err := c.Mail(from); err != nil { - if c.retryError(err) { + if err == io.EOF { // This is probably due to a timeout, so reconnect and try again. sc, derr := c.d.Dial() if derr == nil { @@ -188,7 +154,6 @@ func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { } } } - return err } @@ -217,8 +182,9 @@ func (c *smtpSender) Close() error { // Stubbed out for tests. var ( - tlsClient = tls.Client - smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { + netDialTimeout = net.DialTimeout + tlsClient = tls.Client + smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) { return smtp.NewClient(conn, host) } ) diff --git a/smtp_test.go b/smtp_test.go index 7ed47c0..b6f9155 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "bytes" @@ -18,7 +18,7 @@ const ( var ( testConn = &net.TCPConn{} - testTLSConn = tls.Client(testConn, &tls.Config{InsecureSkipVerify: true}) + testTLSConn = &tls.Conn{} testConfig = &tls.Config{InsecureSkipVerify: true} testAuth = smtp.PlainAuth("", testUser, testPwd, testHost) ) @@ -118,9 +118,8 @@ func TestDialerNoAuth(t *testing.T) { func TestDialerTimeout(t *testing.T) { d := &Dialer{ - Host: testHost, - Port: testPort, - RetryFailure: true, + Host: testHost, + Port: testPort, } testSendMailTimeout(t, d, []string{ "Extension STARTTLS", @@ -139,25 +138,6 @@ func TestDialerTimeout(t *testing.T) { }) } -func TestDialerTimeoutNoRetry(t *testing.T) { - d := &Dialer{ - Host: testHost, - Port: testPort, - RetryFailure: false, - } - - err := doTestSendMail(t, d, []string{ - "Extension STARTTLS", - "StartTLS", - "Mail " + testFrom, - "Quit", - }, true) - - if err.Error() != "gomail: could not send email 1: EOF" { - t.Error("expected to have got EOF, but got:", err) - } -} - type mockClient struct { t *testing.T i int @@ -252,18 +232,14 @@ func (w *mockWriter) Close() error { } func testSendMail(t *testing.T, d *Dialer, want []string) { - if err := doTestSendMail(t, d, want, false); err != nil { - t.Error(err) - } + doTestSendMail(t, d, want, false) } func testSendMailTimeout(t *testing.T, d *Dialer, want []string) { - if err := doTestSendMail(t, d, want, true); err != nil { - t.Error(err) - } + doTestSendMail(t, d, want, true) } -func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) error { +func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) { testClient := &mockClient{ t: t, want: want, @@ -272,7 +248,7 @@ func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) error timeout: timeout, } - NetDialTimeout = func(network, address string, d time.Duration) (net.Conn, error) { + netDialTimeout = func(network, address string, d time.Duration) (net.Conn, error) { if network != "tcp" { t.Errorf("Invalid network, got %q, want tcp", network) } @@ -298,7 +274,9 @@ func doTestSendMail(t *testing.T, d *Dialer, want []string, timeout bool) error return testClient, nil } - return d.DialAndSend(getTestMessage()) + if err := d.DialAndSend(getTestMessage()); err != nil { + t.Error(err) + } } func assertConfig(t *testing.T, got, want *tls.Config) { diff --git a/writeto.go b/writeto.go index 22581ab..9fb6b86 100644 --- a/writeto.go +++ b/writeto.go @@ -1,4 +1,4 @@ -package mail +package gomail import ( "encoding/base64"