From f5437632f486b7d0a0a181c58f113c86d032b02c Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 24 Apr 2017 20:11:36 -0400 Subject: Upgrading server dependancies (#6215) --- vendor/gopkg.in/gomail.v2/.travis.yml | 8 - vendor/gopkg.in/gomail.v2/CHANGELOG.md | 20 - vendor/gopkg.in/gomail.v2/CONTRIBUTING.md | 20 - vendor/gopkg.in/gomail.v2/LICENSE | 20 - vendor/gopkg.in/gomail.v2/README.md | 97 ----- vendor/gopkg.in/gomail.v2/auth.go | 67 ---- vendor/gopkg.in/gomail.v2/auth_test.go | 156 -------- vendor/gopkg.in/gomail.v2/doc.go | 5 - vendor/gopkg.in/gomail.v2/example_test.go | 215 ---------- vendor/gopkg.in/gomail.v2/message.go | 302 -------------- vendor/gopkg.in/gomail.v2/message_test.go | 630 ------------------------------ vendor/gopkg.in/gomail.v2/mime.go | 19 - vendor/gopkg.in/gomail.v2/mime_go14.go | 16 - vendor/gopkg.in/gomail.v2/send.go | 117 ------ vendor/gopkg.in/gomail.v2/send_test.go | 80 ---- vendor/gopkg.in/gomail.v2/smtp.go | 175 --------- vendor/gopkg.in/gomail.v2/smtp_test.go | 254 ------------ vendor/gopkg.in/gomail.v2/writeto.go | 242 ------------ 18 files changed, 2443 deletions(-) delete mode 100644 vendor/gopkg.in/gomail.v2/.travis.yml delete mode 100644 vendor/gopkg.in/gomail.v2/CHANGELOG.md delete mode 100644 vendor/gopkg.in/gomail.v2/CONTRIBUTING.md delete mode 100644 vendor/gopkg.in/gomail.v2/LICENSE delete mode 100644 vendor/gopkg.in/gomail.v2/README.md delete mode 100644 vendor/gopkg.in/gomail.v2/auth.go delete mode 100644 vendor/gopkg.in/gomail.v2/auth_test.go delete mode 100644 vendor/gopkg.in/gomail.v2/doc.go delete mode 100644 vendor/gopkg.in/gomail.v2/example_test.go delete mode 100644 vendor/gopkg.in/gomail.v2/message.go delete mode 100644 vendor/gopkg.in/gomail.v2/message_test.go delete mode 100644 vendor/gopkg.in/gomail.v2/mime.go delete mode 100644 vendor/gopkg.in/gomail.v2/mime_go14.go delete mode 100644 vendor/gopkg.in/gomail.v2/send.go delete mode 100644 vendor/gopkg.in/gomail.v2/send_test.go delete mode 100644 vendor/gopkg.in/gomail.v2/smtp.go delete mode 100644 vendor/gopkg.in/gomail.v2/smtp_test.go delete mode 100644 vendor/gopkg.in/gomail.v2/writeto.go (limited to 'vendor/gopkg.in/gomail.v2') diff --git a/vendor/gopkg.in/gomail.v2/.travis.yml b/vendor/gopkg.in/gomail.v2/.travis.yml deleted file mode 100644 index 24edf22cc..000000000 --- a/vendor/gopkg.in/gomail.v2/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go - -go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 - - tip diff --git a/vendor/gopkg.in/gomail.v2/CHANGELOG.md b/vendor/gopkg.in/gomail.v2/CHANGELOG.md deleted file mode 100644 index a797ab4c0..000000000 --- a/vendor/gopkg.in/gomail.v2/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -## [2.0.0] - 2015-09-02 - -- Mailer has been removed. It has been replaced by Dialer and Sender. -- `File` type and the `CreateFile` and `OpenFile` functions have been removed. -- `Message.Attach` and `Message.Embed` have a new signature. -- `Message.GetBodyWriter` has been removed. Use `Message.AddAlternativeWriter` -instead. -- `Message.Export` has been removed. `Message.WriteTo` can be used instead. -- `Message.DelHeader` has been removed. -- The `Bcc` header field is no longer sent. It is far more simpler and -efficient: the same message is sent to all recipients instead of sending a -different email to each Bcc address. -- LoginAuth has been removed. `NewPlainDialer` now implements the LOGIN -authentication mechanism when needed. -- Go 1.2 is now required instead of Go 1.3. No external dependency are used when -using Go 1.5. diff --git a/vendor/gopkg.in/gomail.v2/CONTRIBUTING.md b/vendor/gopkg.in/gomail.v2/CONTRIBUTING.md deleted file mode 100644 index d5601c257..000000000 --- a/vendor/gopkg.in/gomail.v2/CONTRIBUTING.md +++ /dev/null @@ -1,20 +0,0 @@ -Thank you for contributing to Gomail! Here are a few guidelines: - -## Bugs - -If you think you found a bug, create an issue and supply the minimum amount -of code triggering the bug so it can be reproduced. - - -## Fixing a bug - -If you want to fix a bug, you can send a pull request. It should contains a -new test or update an existing one to cover that bug. - - -## New feature proposal - -If you think Gomail lacks a feature, you can open an issue or send a pull -request. I want to keep Gomail code and API as simple as possible so please -describe your needs so we can discuss whether this feature should be added to -Gomail or not. diff --git a/vendor/gopkg.in/gomail.v2/LICENSE b/vendor/gopkg.in/gomail.v2/LICENSE deleted file mode 100644 index 5f5c12af7..000000000 --- a/vendor/gopkg.in/gomail.v2/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Alexandre Cesaro - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gopkg.in/gomail.v2/README.md b/vendor/gopkg.in/gomail.v2/README.md deleted file mode 100644 index 18cb88130..000000000 --- a/vendor/gopkg.in/gomail.v2/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# 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) - -## Introduction - -Gomail is a simple and efficient package to send emails. It is well tested and -documented. - -It is versioned using [gopkg.in](https://gopkg.in) so I promise -they 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. - - -## Features - -Gomail supports: -- Attachments -- Embedded images -- HTML and text templates -- Automatic encoding of special characters -- SSL and TLS -- Sending multiple emails with the same SMTP connection -- Any method to send emails: SMTP, postfix (not included but easily doable), etc - - -## Documentation - -https://godoc.org/gopkg.in/gomail.v2 - - -## Download - - go get gopkg.in/gomail.v2 - - -## Examples - -See the [examples in the documentation](https://godoc.org/gopkg.in/gomail.v2#example-package). - - -## FAQ - -### x509: certificate signed by unknown authority - -If you get this error it means the certificate used by the SMTP server is not -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`: - - d := gomail.NewPlainDialer("smtp.example.com", "user", "123456", 587) - d.TLSConfig = &tls.Config{InsecureSkipVerify: true} - -Note, however, that this is insecure and should not be used in production. - - -## Contribute - -Contributions are more than welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for -more info. - - -## Change log - -See [CHANGELOG.md](CHANGELOG.md). - - -## License - -[MIT](LICENSE) - - -## Contact - -You can ask questions on the [Gomail -thread](https://groups.google.com/d/topic/golang-nuts/jMxZHzvvEVg/discussion) -in the Go mailing-list. - - -## Support - -If you want to support the development of Gomail, I gladly accept donations. - -I will give 100% of the money I receive to -[Enfants, Espoir Du Monde](http://www.eedm.fr/). -EEDM is a French NGO which helps children in Bangladesh, Cameroun, Haiti, India -and Madagascar. - -All its members are volunteers so its operating costs are only -1.9%. So your money will directly helps children of these countries. - -As an added bonus, your donations will also tip me by lowering my taxes :smile: - -I will send an email with the receipt of the donation to EEDM annually to all -donors. - -[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PYQKC7VFVXCFG) diff --git a/vendor/gopkg.in/gomail.v2/auth.go b/vendor/gopkg.in/gomail.v2/auth.go deleted file mode 100644 index 4bcdd0620..000000000 --- a/vendor/gopkg.in/gomail.v2/auth.go +++ /dev/null @@ -1,67 +0,0 @@ -package gomail - -import ( - "bytes" - "errors" - "fmt" - "net/smtp" -) - -// plainAuth is an smtp.Auth that implements the PLAIN authentication mechanism. -// It fallbacks to the LOGIN mechanism if it is the only mechanism advertised -// by the server. -type plainAuth struct { - username string - password string - host string - login bool -} - -func (a *plainAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { - if server.Name != a.host { - return "", nil, errors.New("gomail: wrong host name") - } - - var plain, login bool - for _, a := range server.Auth { - switch a { - case "PLAIN": - plain = true - case "LOGIN": - login = true - } - } - - if !server.TLS && !plain && !login { - return "", nil, errors.New("gomail: unencrypted connection") - } - - if !plain && login { - a.login = true - return "LOGIN", nil, nil - } - - return "PLAIN", []byte("\x00" + a.username + "\x00" + a.password), nil -} - -func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) { - if !a.login { - if more { - return nil, errors.New("gomail: unexpected server challenge") - } - return nil, nil - } - - if !more { - return nil, nil - } - - switch { - case bytes.Equal(fromServer, []byte("Username:")): - return []byte(a.username), nil - case bytes.Equal(fromServer, []byte("Password:")): - return []byte(a.password), nil - default: - return nil, fmt.Errorf("gomail: unexpected server challenge: %s", fromServer) - } -} diff --git a/vendor/gopkg.in/gomail.v2/auth_test.go b/vendor/gopkg.in/gomail.v2/auth_test.go deleted file mode 100644 index 20b477214..000000000 --- a/vendor/gopkg.in/gomail.v2/auth_test.go +++ /dev/null @@ -1,156 +0,0 @@ -package gomail - -import ( - "net/smtp" - "testing" -) - -const ( - testUser = "user" - testPwd = "pwd" - testHost = "smtp.example.com" -) - -var testAuth = &plainAuth{ - username: testUser, - password: testPwd, - host: testHost, -} - -type plainAuthTest struct { - auths []string - challenges []string - tls bool - wantProto string - wantData []string - wantError bool -} - -func TestNoAdvertisement(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{}, - challenges: []string{"Username:", "Password:"}, - tls: false, - wantProto: "PLAIN", - wantError: true, - }) -} - -func TestNoAdvertisementTLS(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{}, - challenges: []string{"Username:", "Password:"}, - tls: true, - wantProto: "PLAIN", - wantData: []string{"\x00" + testUser + "\x00" + testPwd}, - }) -} - -func TestPlain(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{"PLAIN"}, - challenges: []string{"Username:", "Password:"}, - tls: false, - wantProto: "PLAIN", - wantData: []string{"\x00" + testUser + "\x00" + testPwd}, - }) -} - -func TestPlainTLS(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{"PLAIN"}, - challenges: []string{"Username:", "Password:"}, - tls: true, - wantProto: "PLAIN", - wantData: []string{"\x00" + testUser + "\x00" + testPwd}, - }) -} - -func TestPlainAndLogin(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{"PLAIN", "LOGIN"}, - challenges: []string{"Username:", "Password:"}, - tls: false, - wantProto: "PLAIN", - wantData: []string{"\x00" + testUser + "\x00" + testPwd}, - }) -} - -func TestPlainAndLoginTLS(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{"PLAIN", "LOGIN"}, - challenges: []string{"Username:", "Password:"}, - tls: true, - wantProto: "PLAIN", - wantData: []string{"\x00" + testUser + "\x00" + testPwd}, - }) -} - -func TestLogin(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{"LOGIN"}, - challenges: []string{"Username:", "Password:"}, - tls: false, - wantProto: "LOGIN", - wantData: []string{"", testUser, testPwd}, - }) -} - -func TestLoginTLS(t *testing.T) { - testPlainAuth(t, &plainAuthTest{ - auths: []string{"LOGIN"}, - challenges: []string{"Username:", "Password:"}, - tls: true, - wantProto: "LOGIN", - wantData: []string{"", testUser, testPwd}, - }) -} - -func testPlainAuth(t *testing.T, test *plainAuthTest) { - auth := &plainAuth{ - username: testUser, - password: testPwd, - host: testHost, - } - server := &smtp.ServerInfo{ - Name: testHost, - TLS: test.tls, - Auth: test.auths, - } - proto, toServer, err := auth.Start(server) - if err != nil && !test.wantError { - t.Fatalf("plainAuth.Start(): %v", err) - } - if err != nil && test.wantError { - return - } - if proto != test.wantProto { - t.Errorf("invalid protocol, got %q, want %q", proto, test.wantProto) - } - - i := 0 - got := string(toServer) - if got != test.wantData[i] { - t.Errorf("Invalid response, got %q, want %q", got, test.wantData[i]) - } - - if proto == "PLAIN" { - return - } - - for _, challenge := range test.challenges { - i++ - if i >= len(test.wantData) { - t.Fatalf("unexpected challenge: %q", challenge) - } - - toServer, err = auth.Next([]byte(challenge), true) - if err != nil { - t.Fatalf("plainAuth.Auth(): %v", err) - } - got = string(toServer) - if got != test.wantData[i] { - t.Errorf("Invalid response, got %q, want %q", got, test.wantData[i]) - } - } -} diff --git a/vendor/gopkg.in/gomail.v2/doc.go b/vendor/gopkg.in/gomail.v2/doc.go deleted file mode 100644 index a8f5091f5..000000000 --- a/vendor/gopkg.in/gomail.v2/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Package gomail provides a simple interface to compose emails and to mail them -// efficiently. -// -// More info on Github: https://github.com/go-gomail/gomail -package gomail diff --git a/vendor/gopkg.in/gomail.v2/example_test.go b/vendor/gopkg.in/gomail.v2/example_test.go deleted file mode 100644 index 8d9c6c293..000000000 --- a/vendor/gopkg.in/gomail.v2/example_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package gomail_test - -import ( - "fmt" - "html/template" - "io" - "log" - "time" - - "gopkg.in/gomail.v2" -) - -func Example() { - 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") - m.SetHeader("Subject", "Hello!") - m.SetBody("text/html", "Hello Bob and Cora!") - m.Attach("/home/Alex/lolcat.jpg") - - d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456") - - // Send the email to Bob, Cora and Dan. - if err := d.DialAndSend(m); err != nil { - panic(err) - } -} - -// A daemon that listens to a channel and sends all incoming messages. -func Example_daemon() { - 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) -} - -// Efficiently send a customized newsletter to a list of recipients. -func Example_newsletter() { - // The list of recipients. - var list []struct { - Name string - Address string - } - - d := gomail.NewPlainDialer("smtp.example.com", 587, "user", "123456") - s, err := d.Dial() - if err != nil { - panic(err) - } - - 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 := gomail.Send(s, m); err != nil { - log.Printf("Could not send email to %q: %v", r.Address, err) - } - m.Reset() - } -} - -// Send an email using a local SMTP server. -func Example_noAuth() { - 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 := gomail.Dialer{Host: "localhost", Port: 587} - if err := d.DialAndSend(m); err != nil { - panic(err) - } -} - -// Send an email using an API or postfix. -func Example_noSMTP() { - 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 := 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) - fmt.Println("To:", to) - return nil - }) - - if err := gomail.Send(s, m); err != nil { - panic(err) - } - // Output: - // From: from@example.com - // To: [to@example.com] -} - -var m *gomail.Message - -func ExampleSetCopyFunc() { - m.Attach("foo.txt", gomail.SetCopyFunc(func(w io.Writer) error { - _, err := w.Write([]byte("Content of foo.txt")) - return err - })) -} - -func ExampleSetHeader() { - h := map[string][]string{"Content-ID": {""}} - m.Attach("foo.jpg", gomail.SetHeader(h)) -} - -func ExampleMessage_AddAlternative() { - m.SetBody("text/plain", "Hello!") - m.AddAlternative("text/html", "

Hello!

") -} - -func ExampleMessage_AddAlternativeWriter() { - t := template.Must(template.New("example").Parse("Hello {{.}}!")) - m.AddAlternativeWriter("text/plain", func(w io.Writer) error { - return t.Execute(w, "Bob") - }) -} - -func ExampleMessage_Attach() { - m.Attach("/tmp/image.jpg") -} - -func ExampleMessage_Embed() { - m.Embed("/tmp/image.jpg") - m.SetBody("text/html", `My image`) -} - -func ExampleMessage_FormatAddress() { - m.SetHeader("To", m.FormatAddress("bob@example.com", "Bob"), m.FormatAddress("cora@example.com", "Cora")) -} - -func ExampleMessage_FormatDate() { - m.SetHeaders(map[string][]string{ - "X-Date": {m.FormatDate(time.Now())}, - }) -} - -func ExampleMessage_SetAddressHeader() { - m.SetAddressHeader("To", "bob@example.com", "Bob") -} - -func ExampleMessage_SetBody() { - m.SetBody("text/plain", "Hello!") -} - -func ExampleMessage_SetDateHeader() { - m.SetDateHeader("X-Date", time.Now()) -} - -func ExampleMessage_SetHeader() { - m.SetHeader("Subject", "Hello!") -} - -func ExampleMessage_SetHeaders() { - m.SetHeaders(map[string][]string{ - "From": {m.FormatAddress("alex@example.com", "Alex")}, - "To": {"bob@example.com", "cora@example.com"}, - "Subject": {"Hello"}, - }) -} - -func ExampleSetCharset() { - m = gomail.NewMessage(gomail.SetCharset("ISO-8859-1")) -} - -func ExampleSetEncoding() { - m = gomail.NewMessage(gomail.SetEncoding(gomail.Base64)) -} diff --git a/vendor/gopkg.in/gomail.v2/message.go b/vendor/gopkg.in/gomail.v2/message.go deleted file mode 100644 index 2f75368bd..000000000 --- a/vendor/gopkg.in/gomail.v2/message.go +++ /dev/null @@ -1,302 +0,0 @@ -package gomail - -import ( - "bytes" - "io" - "os" - "path/filepath" - "time" -) - -// Message represents an email. -type Message struct { - header header - parts []part - attachments []*file - embedded []*file - charset string - encoding Encoding - hEncoder mimeEncoder - buf bytes.Buffer -} - -type header map[string][]string - -type part struct { - header header - copier func(io.Writer) error -} - -// NewMessage creates a new message. It uses UTF-8 and quoted-printable encoding -// by default. -func NewMessage(settings ...MessageSetting) *Message { - m := &Message{ - header: make(header), - charset: "UTF-8", - encoding: QuotedPrintable, - } - - m.applySettings(settings) - - if m.encoding == Base64 { - m.hEncoder = bEncoding - } else { - m.hEncoder = qEncoding - } - - return m -} - -// Reset resets the message so it can be reused. The message keeps its previous -// settings so it is in the same state that after a call to NewMessage. -func (m *Message) Reset() { - for k := range m.header { - delete(m.header, k) - } - m.parts = nil - m.attachments = nil - m.embedded = nil -} - -func (m *Message) applySettings(settings []MessageSetting) { - for _, s := range settings { - s(m) - } -} - -// A MessageSetting can be used as an argument in NewMessage to configure an -// email. -type MessageSetting func(m *Message) - -// SetCharset is a message setting to set the charset of the email. -func SetCharset(charset string) MessageSetting { - return func(m *Message) { - m.charset = charset - } -} - -// SetEncoding is a message setting to set the encoding of the email. -func SetEncoding(enc Encoding) MessageSetting { - return func(m *Message) { - m.encoding = enc - } -} - -// Encoding represents a MIME encoding scheme like quoted-printable or base64. -type Encoding string - -const ( - // QuotedPrintable represents the quoted-printable encoding as defined in - // RFC 2045. - QuotedPrintable Encoding = "quoted-printable" - // Base64 represents the base64 encoding as defined in RFC 2045. - Base64 Encoding = "base64" - // Unencoded can be used to avoid encoding the body of an email. The headers - // will still be encoded using quoted-printable encoding. - Unencoded Encoding = "8bit" -) - -// SetHeader sets a value to the given header field. -func (m *Message) SetHeader(field string, value ...string) { - m.encodeHeader(value) - m.header[field] = value -} - -func (m *Message) encodeHeader(values []string) { - for i := range values { - values[i] = m.encodeString(values[i]) - } -} - -func (m *Message) encodeString(value string) string { - return m.hEncoder.Encode(m.charset, value) -} - -// SetHeaders sets the message headers. -func (m *Message) SetHeaders(h map[string][]string) { - for k, v := range h { - m.SetHeader(k, v...) - } -} - -// SetAddressHeader sets an address to the given header field. -func (m *Message) SetAddressHeader(field, address, name string) { - m.header[field] = []string{m.FormatAddress(address, name)} -} - -// FormatAddress formats an address and a name as a valid RFC 5322 address. -func (m *Message) FormatAddress(address, name string) string { - enc := m.encodeString(name) - if enc == name { - m.buf.WriteByte('"') - for i := 0; i < len(name); i++ { - b := name[i] - if b == '\\' || b == '"' { - m.buf.WriteByte('\\') - } - m.buf.WriteByte(b) - } - m.buf.WriteByte('"') - } else if hasSpecials(name) { - m.buf.WriteString(bEncoding.Encode(m.charset, name)) - } else { - m.buf.WriteString(enc) - } - m.buf.WriteString(" <") - m.buf.WriteString(address) - m.buf.WriteByte('>') - - addr := m.buf.String() - m.buf.Reset() - return addr -} - -func hasSpecials(text string) bool { - for i := 0; i < len(text); i++ { - switch c := text[i]; c { - case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '.', '"': - return true - } - } - - return false -} - -// SetDateHeader sets a date to the given header field. -func (m *Message) SetDateHeader(field string, date time.Time) { - m.header[field] = []string{m.FormatDate(date)} -} - -// FormatDate formats a date as a valid RFC 5322 date. -func (m *Message) FormatDate(date time.Time) string { - return date.Format(time.RFC1123Z) -} - -// GetHeader gets a header field. -func (m *Message) GetHeader(field string) []string { - return m.header[field] -} - -// SetBody sets the body of the message. -func (m *Message) SetBody(contentType, body string) { - m.parts = []part{ - { - header: m.getPartHeader(contentType), - copier: func(w io.Writer) error { - _, err := io.WriteString(w, body) - return err - }, - }, - } -} - -// AddAlternative adds an alternative part to the message. -// -// It is commonly used to send HTML emails that default to the plain text -// version for backward compatibility. -// -// More info: http://en.wikipedia.org/wiki/MIME#Alternative -func (m *Message) AddAlternative(contentType, body string) { - m.parts = append(m.parts, - part{ - header: m.getPartHeader(contentType), - copier: func(w io.Writer) error { - _, err := io.WriteString(w, body) - return err - }, - }, - ) -} - -// AddAlternativeWriter adds an alternative part to the message. It can be -// useful with the text/template or html/template packages. -func (m *Message) AddAlternativeWriter(contentType string, f func(io.Writer) error) { - m.parts = []part{ - { - header: m.getPartHeader(contentType), - copier: f, - }, - } -} - -func (m *Message) getPartHeader(contentType string) header { - return map[string][]string{ - "Content-Type": {contentType + "; charset=" + m.charset}, - "Content-Transfer-Encoding": {string(m.encoding)}, - } -} - -type file struct { - Name string - Header map[string][]string - CopyFunc func(w io.Writer) error -} - -func (f *file) setHeader(field, value string) { - f.Header[field] = []string{value} -} - -// A FileSetting can be used as an argument in Message.Attach or Message.Embed. -type FileSetting func(*file) - -// SetHeader is a file setting to set the MIME header of the message part that -// contains the file content. -// -// Mandatory headers are automatically added if they are not set when sending -// the email. -func SetHeader(h map[string][]string) FileSetting { - return func(f *file) { - for k, v := range h { - f.Header[k] = v - } - } -} - -// SetCopyFunc is a file setting to replace the function that runs when the -// message is sent. It should copy the content of the file to the io.Writer. -// -// The default copy function opens the file with the given filename, and copy -// its content to the io.Writer. -func SetCopyFunc(f func(io.Writer) error) FileSetting { - return func(fi *file) { - fi.CopyFunc = f - } -} - -func (m *Message) appendFile(list []*file, name string, settings []FileSetting) []*file { - f := &file{ - Name: filepath.Base(name), - Header: make(map[string][]string), - CopyFunc: func(w io.Writer) error { - h, err := os.Open(name) - if err != nil { - return err - } - if _, err := io.Copy(w, h); err != nil { - h.Close() - return err - } - return h.Close() - }, - } - - for _, s := range settings { - s(f) - } - - if list == nil { - return []*file{f} - } - - return append(list, f) -} - -// Attach attaches the files to the email. -func (m *Message) Attach(filename string, settings ...FileSetting) { - m.attachments = m.appendFile(m.attachments, filename, settings) -} - -// Embed embeds the images to the email. -func (m *Message) Embed(filename string, settings ...FileSetting) { - m.embedded = m.appendFile(m.embedded, filename, settings) -} diff --git a/vendor/gopkg.in/gomail.v2/message_test.go b/vendor/gopkg.in/gomail.v2/message_test.go deleted file mode 100644 index fdd9ff9bd..000000000 --- a/vendor/gopkg.in/gomail.v2/message_test.go +++ /dev/null @@ -1,630 +0,0 @@ -package gomail - -import ( - "bytes" - "encoding/base64" - "io" - "io/ioutil" - "path/filepath" - "regexp" - "strconv" - "strings" - "testing" - "time" -) - -func init() { - now = func() time.Time { - return time.Date(2014, 06, 25, 17, 46, 0, 0, time.UTC) - } -} - -type message struct { - from string - to []string - content string -} - -func TestMessage(t *testing.T) { - m := NewMessage() - m.SetAddressHeader("From", "from@example.com", "Señor From") - m.SetHeader("To", m.FormatAddress("to@example.com", "Señor To"), "tobis@example.com") - m.SetAddressHeader("Cc", "cc@example.com", "A, B") - m.SetAddressHeader("X-To", "ccbis@example.com", "à, b") - m.SetDateHeader("X-Date", now()) - m.SetHeader("X-Date-2", m.FormatDate(now())) - m.SetHeader("Subject", "¡Hola, señor!") - m.SetHeaders(map[string][]string{ - "X-Headers": {"Test", "Café"}, - }) - m.SetBody("text/plain", "¡Hola, señor!") - - want := &message{ - from: "from@example.com", - to: []string{ - "to@example.com", - "tobis@example.com", - "cc@example.com", - }, - content: "From: =?UTF-8?q?Se=C3=B1or_From?= \r\n" + - "To: =?UTF-8?q?Se=C3=B1or_To?= , tobis@example.com\r\n" + - "Cc: \"A, B\" \r\n" + - "X-To: =?UTF-8?b?w6AsIGI=?= \r\n" + - "X-Date: Wed, 25 Jun 2014 17:46:00 +0000\r\n" + - "X-Date-2: Wed, 25 Jun 2014 17:46:00 +0000\r\n" + - "X-Headers: Test, =?UTF-8?q?Caf=C3=A9?=\r\n" + - "Subject: =?UTF-8?q?=C2=A1Hola,_se=C3=B1or!?=\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "=C2=A1Hola, se=C3=B1or!", - } - - testMessage(t, m, 0, want) -} - -func TestBodyWriter(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.AddAlternativeWriter("text/plain", func(w io.Writer) error { - _, err := w.Write([]byte("Test message")) - return err - }) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test message", - } - - testMessage(t, m, 0, want) -} - -func TestCustomMessage(t *testing.T) { - m := NewMessage(SetCharset("ISO-8859-1"), SetEncoding(Base64)) - m.SetHeaders(map[string][]string{ - "From": {"from@example.com"}, - "To": {"to@example.com"}, - "Subject": {"Café"}, - }) - m.SetBody("text/html", "¡Hola, señor!") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Subject: =?ISO-8859-1?b?Q2Fmw6k=?=\r\n" + - "Content-Type: text/html; charset=ISO-8859-1\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - "wqFIb2xhLCBzZcOxb3Ih", - } - - testMessage(t, m, 0, want) -} - -func TestUnencodedMessage(t *testing.T) { - m := NewMessage(SetEncoding(Unencoded)) - m.SetHeaders(map[string][]string{ - "From": {"from@example.com"}, - "To": {"to@example.com"}, - "Subject": {"Café"}, - }) - m.SetBody("text/html", "¡Hola, señor!") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Subject: =?UTF-8?q?Caf=C3=A9?=\r\n" + - "Content-Type: text/html; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: 8bit\r\n" + - "\r\n" + - "¡Hola, señor!", - } - - testMessage(t, m, 0, want) -} - -func TestRecipients(t *testing.T) { - m := NewMessage() - m.SetHeaders(map[string][]string{ - "From": {"from@example.com"}, - "To": {"to@example.com"}, - "Cc": {"cc@example.com"}, - "Bcc": {"bcc1@example.com", "bcc2@example.com"}, - "Subject": {"Hello!"}, - }) - m.SetBody("text/plain", "Test message") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com", "cc@example.com", "bcc1@example.com", "bcc2@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Cc: cc@example.com\r\n" + - "Subject: Hello!\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test message", - } - - testMessage(t, m, 0, want) -} - -func TestAlternative(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", "¡Hola, señor!") - m.AddAlternative("text/html", "¡Hola, señor!") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/alternative; boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "=C2=A1Hola, se=C3=B1or!\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/html; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "=C2=A1Hola, se=C3=B1or!\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - -func TestAttachmentOnly(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.Attach(mockCopyFile("/tmp/test.pdf")) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: application/pdf; name=\"test.pdf\"\r\n" + - "Content-Disposition: attachment; filename=\"test.pdf\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")), - } - - testMessage(t, m, 0, want) -} - -func TestAttachment(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", "Test") - m.Attach(mockCopyFile("/tmp/test.pdf")) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/pdf; name=\"test.pdf\"\r\n" + - "Content-Disposition: attachment; filename=\"test.pdf\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")) + "\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - -func TestAttachmentsOnly(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.Attach(mockCopyFile("/tmp/test.pdf")) - m.Attach(mockCopyFile("/tmp/test.zip")) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/pdf; name=\"test.pdf\"\r\n" + - "Content-Disposition: attachment; filename=\"test.pdf\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")) + "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/zip; name=\"test.zip\"\r\n" + - "Content-Disposition: attachment; filename=\"test.zip\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.zip")) + "\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - -func TestAttachments(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", "Test") - m.Attach(mockCopyFile("/tmp/test.pdf")) - m.Attach(mockCopyFile("/tmp/test.zip")) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/pdf; name=\"test.pdf\"\r\n" + - "Content-Disposition: attachment; filename=\"test.pdf\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")) + "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/zip; name=\"test.zip\"\r\n" + - "Content-Disposition: attachment; filename=\"test.zip\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.zip")) + "\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - -func TestEmbedded(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.Embed(mockCopyFileWithHeader(m, "image1.jpg", map[string][]string{"Content-ID": {""}})) - m.Embed(mockCopyFile("image2.jpg")) - m.SetBody("text/plain", "Test") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/related; boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: image/jpeg; name=\"image1.jpg\"\r\n" + - "Content-Disposition: inline; filename=\"image1.jpg\"\r\n" + - "Content-ID: \r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of image1.jpg")) + "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: image/jpeg; name=\"image2.jpg\"\r\n" + - "Content-Disposition: inline; filename=\"image2.jpg\"\r\n" + - "Content-ID: \r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of image2.jpg")) + "\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 1, want) -} - -func TestFullMessage(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", "¡Hola, señor!") - m.AddAlternative("text/html", "¡Hola, señor!") - m.Attach(mockCopyFile("test.pdf")) - m.Embed(mockCopyFile("image.jpg")) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: multipart/mixed; boundary=_BOUNDARY_1_\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: multipart/related; boundary=_BOUNDARY_2_\r\n" + - "\r\n" + - "--_BOUNDARY_2_\r\n" + - "Content-Type: multipart/alternative; boundary=_BOUNDARY_3_\r\n" + - "\r\n" + - "--_BOUNDARY_3_\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "=C2=A1Hola, se=C3=B1or!\r\n" + - "--_BOUNDARY_3_\r\n" + - "Content-Type: text/html; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "=C2=A1Hola, se=C3=B1or!\r\n" + - "--_BOUNDARY_3_--\r\n" + - "\r\n" + - "--_BOUNDARY_2_\r\n" + - "Content-Type: image/jpeg; name=\"image.jpg\"\r\n" + - "Content-Disposition: inline; filename=\"image.jpg\"\r\n" + - "Content-ID: \r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of image.jpg")) + "\r\n" + - "--_BOUNDARY_2_--\r\n" + - "\r\n" + - "--_BOUNDARY_1_\r\n" + - "Content-Type: application/pdf; name=\"test.pdf\"\r\n" + - "Content-Disposition: attachment; filename=\"test.pdf\"\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")) + "\r\n" + - "--_BOUNDARY_1_--\r\n", - } - - testMessage(t, m, 3, want) - - want = &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - "Test reset", - } - m.Reset() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", "Test reset") - testMessage(t, m, 0, want) -} - -func TestQpLineLength(t *testing.T) { - m := NewMessage() - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", - strings.Repeat("0", 76)+"\r\n"+ - strings.Repeat("0", 75)+"à\r\n"+ - strings.Repeat("0", 74)+"à\r\n"+ - strings.Repeat("0", 73)+"à\r\n"+ - strings.Repeat("0", 72)+"à\r\n"+ - strings.Repeat("0", 75)+"\r\n"+ - strings.Repeat("0", 76)+"\n") - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - strings.Repeat("0", 75) + "=\r\n0\r\n" + - strings.Repeat("0", 75) + "=\r\n=C3=A0\r\n" + - strings.Repeat("0", 74) + "=\r\n=C3=A0\r\n" + - strings.Repeat("0", 73) + "=\r\n=C3=A0\r\n" + - strings.Repeat("0", 72) + "=C3=\r\n=A0\r\n" + - strings.Repeat("0", 75) + "\r\n" + - strings.Repeat("0", 75) + "=\r\n0\r\n", - } - - testMessage(t, m, 0, want) -} - -func TestBase64LineLength(t *testing.T) { - m := NewMessage(SetCharset("UTF-8"), SetEncoding(Base64)) - m.SetHeader("From", "from@example.com") - m.SetHeader("To", "to@example.com") - m.SetBody("text/plain", strings.Repeat("0", 58)) - - want := &message{ - from: "from@example.com", - to: []string{"to@example.com"}, - content: "From: from@example.com\r\n" + - "To: to@example.com\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: base64\r\n" + - "\r\n" + - strings.Repeat("MDAw", 19) + "\r\nMA==", - } - - testMessage(t, m, 0, want) -} - -func testMessage(t *testing.T, m *Message, bCount int, want *message) { - err := Send(stubSendMail(t, bCount, want), m) - if err != nil { - t.Error(err) - } -} - -func stubSendMail(t *testing.T, bCount int, want *message) SendFunc { - return func(from string, to []string, m io.WriterTo) error { - if from != want.from { - t.Fatalf("Invalid from, got %q, want %q", from, want.from) - } - - if len(to) != len(want.to) { - t.Fatalf("Invalid recipient count, \ngot %d: %q\nwant %d: %q", - len(to), to, - len(want.to), want.to, - ) - } - for i := range want.to { - if to[i] != want.to[i] { - t.Fatalf("Invalid recipient, got %q, want %q", - to[i], want.to[i], - ) - } - } - - buf := new(bytes.Buffer) - _, err := m.WriteTo(buf) - if err != nil { - t.Error(err) - } - got := buf.String() - wantMsg := string("Mime-Version: 1.0\r\n" + - "Date: Wed, 25 Jun 2014 17:46:00 +0000\r\n" + - want.content) - if bCount > 0 { - boundaries := getBoundaries(t, bCount, got) - for i, b := range boundaries { - wantMsg = strings.Replace(wantMsg, "_BOUNDARY_"+strconv.Itoa(i+1)+"_", b, -1) - } - } - - compareBodies(t, got, wantMsg) - - return nil - } -} - -func compareBodies(t *testing.T, got, want string) { - // We cannot do a simple comparison since the ordering of headers' fields - // is random. - gotLines := strings.Split(got, "\r\n") - wantLines := strings.Split(want, "\r\n") - - // We only test for too many lines, missing lines are tested after - if len(gotLines) > len(wantLines) { - t.Fatalf("Message has too many lines, \ngot %d:\n%s\nwant %d:\n%s", len(gotLines), got, len(wantLines), want) - } - - isInHeader := true - headerStart := 0 - for i, line := range wantLines { - if line == gotLines[i] { - if line == "" { - isInHeader = false - } else if !isInHeader && len(line) > 2 && line[:2] == "--" { - isInHeader = true - headerStart = i + 1 - } - continue - } - - if !isInHeader { - missingLine(t, line, got, want) - } - - isMissing := true - for j := headerStart; j < len(gotLines); j++ { - if gotLines[j] == "" { - break - } - if gotLines[j] == line { - isMissing = false - break - } - } - if isMissing { - missingLine(t, line, got, want) - } - } -} - -func missingLine(t *testing.T, line, got, want string) { - t.Fatalf("Missing line %q\ngot:\n%s\nwant:\n%s", line, got, want) -} - -func getBoundaries(t *testing.T, count int, m string) []string { - if matches := boundaryRegExp.FindAllStringSubmatch(m, count); matches != nil { - boundaries := make([]string, count) - for i, match := range matches { - boundaries[i] = match[1] - } - return boundaries - } - - t.Fatal("Boundary not found in body") - return []string{""} -} - -var boundaryRegExp = regexp.MustCompile("boundary=(\\w+)") - -func mockCopyFile(name string) (string, FileSetting) { - return name, SetCopyFunc(func(w io.Writer) error { - _, err := w.Write([]byte("Content of " + filepath.Base(name))) - return err - }) -} - -func mockCopyFileWithHeader(m *Message, name string, h map[string][]string) (string, FileSetting, FileSetting) { - name, f := mockCopyFile(name) - return name, f, SetHeader(h) -} - -func BenchmarkFull(b *testing.B) { - discardFunc := SendFunc(func(from string, to []string, m io.WriterTo) error { - _, err := m.WriteTo(ioutil.Discard) - return err - }) - - m := NewMessage() - b.ResetTimer() - for n := 0; n < b.N; n++ { - m.SetAddressHeader("From", "from@example.com", "Señor From") - m.SetHeaders(map[string][]string{ - "To": {"to@example.com"}, - "Cc": {"cc@example.com"}, - "Bcc": {"bcc1@example.com", "bcc2@example.com"}, - "Subject": {"¡Hola, señor!"}, - }) - m.SetBody("text/plain", "¡Hola, señor!") - m.AddAlternative("text/html", "

¡Hola, señor!

") - m.Attach(mockCopyFile("benchmark.txt")) - m.Embed(mockCopyFile("benchmark.jpg")) - - if err := Send(discardFunc, m); err != nil { - panic(err) - } - m.Reset() - } -} diff --git a/vendor/gopkg.in/gomail.v2/mime.go b/vendor/gopkg.in/gomail.v2/mime.go deleted file mode 100644 index 51cba724b..000000000 --- a/vendor/gopkg.in/gomail.v2/mime.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build go1.5 - -package gomail - -import ( - "mime" - "mime/quotedprintable" -) - -var newQPWriter = quotedprintable.NewWriter - -type mimeEncoder struct { - mime.WordEncoder -} - -var ( - bEncoding = mimeEncoder{mime.BEncoding} - qEncoding = mimeEncoder{mime.QEncoding} -) diff --git a/vendor/gopkg.in/gomail.v2/mime_go14.go b/vendor/gopkg.in/gomail.v2/mime_go14.go deleted file mode 100644 index 246e2e5e5..000000000 --- a/vendor/gopkg.in/gomail.v2/mime_go14.go +++ /dev/null @@ -1,16 +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} -) diff --git a/vendor/gopkg.in/gomail.v2/send.go b/vendor/gopkg.in/gomail.v2/send.go deleted file mode 100644 index 3e6726509..000000000 --- a/vendor/gopkg.in/gomail.v2/send.go +++ /dev/null @@ -1,117 +0,0 @@ -package gomail - -import ( - "errors" - "fmt" - "io" - "net/mail" -) - -// Sender is the interface that wraps the Send method. -// -// Send sends an email to the given addresses. -type Sender interface { - Send(from string, to []string, msg io.WriterTo) error -} - -// SendCloser is the interface that groups the Send and Close methods. -type SendCloser interface { - Sender - Close() error -} - -// A SendFunc is a function that sends emails to the given adresses. -// -// The SendFunc type is an adapter to allow the use of ordinary functions as -// email senders. If f is a function with the appropriate signature, SendFunc(f) -// is a Sender object that calls f. -type SendFunc func(from string, to []string, msg io.WriterTo) error - -// Send calls f(from, to, msg). -func (f SendFunc) Send(from string, to []string, msg io.WriterTo) error { - return f(from, to, msg) -} - -// Send sends emails using the given Sender. -func Send(s Sender, msg ...*Message) error { - for i, m := range msg { - if err := send(s, m); err != nil { - return fmt.Errorf("gomail: could not send email %d: %v", i+1, err) - } - } - - return nil -} - -func send(s Sender, m *Message) error { - from, err := m.getFrom() - if err != nil { - return err - } - - to, err := m.getRecipients() - if err != nil { - return err - } - - if err := s.Send(from, to, m); err != nil { - return err - } - - return nil -} - -func (m *Message) getFrom() (string, error) { - from := m.header["Sender"] - if len(from) == 0 { - from = m.header["From"] - if len(from) == 0 { - return "", errors.New(`gomail: invalid message, "From" field is absent`) - } - } - - return parseAddress(from[0]) -} - -func (m *Message) getRecipients() ([]string, error) { - n := 0 - for _, field := range []string{"To", "Cc", "Bcc"} { - if addresses, ok := m.header[field]; ok { - n += len(addresses) - } - } - list := make([]string, 0, n) - - for _, field := range []string{"To", "Cc", "Bcc"} { - if addresses, ok := m.header[field]; ok { - for _, a := range addresses { - addr, err := parseAddress(a) - if err != nil { - return nil, err - } - list = addAddress(list, addr) - } - } - } - - return list, nil -} - -func addAddress(list []string, addr string) []string { - for _, a := range list { - if addr == a { - return list - } - } - - return append(list, addr) -} - -func parseAddress(field string) (string, error) { - a, err := mail.ParseAddress(field) - if a == nil { - return "", err - } - - return a.Address, err -} diff --git a/vendor/gopkg.in/gomail.v2/send_test.go b/vendor/gopkg.in/gomail.v2/send_test.go deleted file mode 100644 index ba59cd3dc..000000000 --- a/vendor/gopkg.in/gomail.v2/send_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package gomail - -import ( - "bytes" - "io" - "reflect" - "testing" -) - -const ( - testTo1 = "to1@example.com" - testTo2 = "to2@example.com" - testFrom = "from@example.com" - testBody = "Test message" - testMsg = "To: " + testTo1 + ", " + testTo2 + "\r\n" + - "From: " + testFrom + "\r\n" + - "Mime-Version: 1.0\r\n" + - "Date: Wed, 25 Jun 2014 17:46:00 +0000\r\n" + - "Content-Type: text/plain; charset=UTF-8\r\n" + - "Content-Transfer-Encoding: quoted-printable\r\n" + - "\r\n" + - testBody -) - -type mockSender SendFunc - -func (s mockSender) Send(from string, to []string, msg io.WriterTo) error { - return s(from, to, msg) -} - -type mockSendCloser struct { - mockSender - close func() error -} - -func (s *mockSendCloser) Close() error { - return s.close() -} - -func TestSend(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 - }, - } - if err := Send(s, getTestMessage()); err != nil { - t.Errorf("Send(): %v", err) - } -} - -func getTestMessage() *Message { - m := NewMessage() - m.SetHeader("From", testFrom) - m.SetHeader("To", testTo1, testTo2) - m.SetBody("text/plain", testBody) - - return m -} - -func stubSend(t *testing.T, wantFrom string, wantTo []string, wantBody string) mockSender { - return func(from string, to []string, msg io.WriterTo) error { - if from != wantFrom { - t.Errorf("invalid from, got %q, want %q", from, wantFrom) - } - if !reflect.DeepEqual(to, wantTo) { - t.Errorf("invalid to, got %v, want %v", to, wantTo) - } - - buf := new(bytes.Buffer) - _, err := msg.WriteTo(buf) - if err != nil { - t.Fatal(err) - } - compareBodies(t, buf.String(), wantBody) - - return nil - } -} diff --git a/vendor/gopkg.in/gomail.v2/smtp.go b/vendor/gopkg.in/gomail.v2/smtp.go deleted file mode 100644 index cf773a102..000000000 --- a/vendor/gopkg.in/gomail.v2/smtp.go +++ /dev/null @@ -1,175 +0,0 @@ -package gomail - -import ( - "crypto/tls" - "fmt" - "io" - "net" - "net/smtp" -) - -// A Dialer is a dialer to an SMTP server. -type Dialer struct { - // Host represents the host of the SMTP server. - Host string - // Port represents the port of the SMTP server. - Port int - // Auth represents the authentication mechanism used to authenticate to the - // SMTP server. - Auth smtp.Auth - // SSL defines whether an SSL connection is used. It should be false in - // most cases since the authentication mechanism should use the STARTTLS - // extension instead. - SSL bool - // TSLConfig represents the TLS configuration used for the TLS (when the - // STARTTLS extension is used) or SSL connection. - TLSConfig *tls.Config -} - -// NewPlainDialer returns a Dialer. The given parameters are used to connect to -// the SMTP server via a PLAIN authentication mechanism. -// -// It fallbacks to the LOGIN mechanism if it is the only mechanism advertised by -// the server. -func NewPlainDialer(host string, port int, username, password string) *Dialer { - return &Dialer{ - Host: host, - Port: port, - Auth: &plainAuth{ - username: username, - password: password, - host: host, - }, - SSL: port == 465, - } -} - -// Dial dials and authenticates to an SMTP server. The returned SendCloser -// should be closed when done using it. -func (d *Dialer) Dial() (SendCloser, error) { - c, err := d.dial() - if err != nil { - return nil, err - } - - if d.Auth != nil { - if ok, _ := c.Extension("AUTH"); ok { - if err = c.Auth(d.Auth); err != nil { - c.Close() - return nil, err - } - } - } - - return &smtpSender{c}, nil -} - -func (d *Dialer) dial() (smtpClient, error) { - if d.SSL { - return d.sslDial() - } - return d.starttlsDial() -} - -func (d *Dialer) starttlsDial() (smtpClient, error) { - c, err := smtpDial(addr(d.Host, d.Port)) - if err != nil { - return nil, err - } - - if ok, _ := c.Extension("STARTTLS"); ok { - if err := c.StartTLS(d.tlsConfig()); err != nil { - c.Close() - return nil, err - } - } - - return c, nil -} - -func (d *Dialer) sslDial() (smtpClient, error) { - conn, err := tlsDial("tcp", addr(d.Host, d.Port), d.tlsConfig()) - if err != nil { - return nil, err - } - - return newClient(conn, d.Host) -} - -func (d *Dialer) tlsConfig() *tls.Config { - if d.TLSConfig == nil { - return &tls.Config{ServerName: d.Host} - } - - return d.TLSConfig -} - -func addr(host string, port int) string { - return fmt.Sprintf("%s:%d", host, port) -} - -// DialAndSend opens a connection to the SMTP server, sends the given emails and -// closes the connection. -func (d *Dialer) DialAndSend(m ...*Message) error { - s, err := d.Dial() - if err != nil { - return err - } - defer s.Close() - - return Send(s, m...) -} - -type smtpSender struct { - smtpClient -} - -func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error { - if err := c.Mail(from); err != nil { - return err - } - - for _, addr := range to { - if err := c.Rcpt(addr); err != nil { - return err - } - } - - w, err := c.Data() - if err != nil { - return err - } - - if _, err = msg.WriteTo(w); err != nil { - w.Close() - return err - } - - return w.Close() -} - -func (c *smtpSender) Close() error { - return c.Quit() -} - -// Stubbed out for tests. -var ( - smtpDial = func(addr string) (smtpClient, error) { - return smtp.Dial(addr) - } - tlsDial = tls.Dial - newClient = func(conn net.Conn, host string) (smtpClient, error) { - return smtp.NewClient(conn, host) - } -) - -type smtpClient interface { - Extension(string) (bool, string) - StartTLS(*tls.Config) error - Auth(smtp.Auth) error - Mail(string) error - Rcpt(string) error - Data() (io.WriteCloser, error) - Quit() error - Close() error -} diff --git a/vendor/gopkg.in/gomail.v2/smtp_test.go b/vendor/gopkg.in/gomail.v2/smtp_test.go deleted file mode 100644 index c8503489b..000000000 --- a/vendor/gopkg.in/gomail.v2/smtp_test.go +++ /dev/null @@ -1,254 +0,0 @@ -package gomail - -import ( - "bytes" - "crypto/tls" - "io" - "net" - "net/smtp" - "reflect" - "testing" -) - -const ( - testPort = 587 - testSSLPort = 465 -) - -var ( - testTLSConn = &tls.Conn{} - testConfig = &tls.Config{InsecureSkipVerify: true} -) - -func TestDialer(t *testing.T) { - d := NewPlainDialer(testHost, testPort, "user", "pwd") - testSendMail(t, d, []string{ - "Extension STARTTLS", - "StartTLS", - "Extension AUTH", - "Auth", - "Mail " + testFrom, - "Rcpt " + testTo1, - "Rcpt " + testTo2, - "Data", - "Write message", - "Close writer", - "Quit", - "Close", - }) -} - -func TestDialerSSL(t *testing.T) { - d := NewPlainDialer(testHost, testSSLPort, "user", "pwd") - testSendMail(t, d, []string{ - "Extension AUTH", - "Auth", - "Mail " + testFrom, - "Rcpt " + testTo1, - "Rcpt " + testTo2, - "Data", - "Write message", - "Close writer", - "Quit", - "Close", - }) -} - -func TestDialerConfig(t *testing.T) { - d := NewPlainDialer(testHost, testPort, "user", "pwd") - d.TLSConfig = testConfig - testSendMail(t, d, []string{ - "Extension STARTTLS", - "StartTLS", - "Extension AUTH", - "Auth", - "Mail " + testFrom, - "Rcpt " + testTo1, - "Rcpt " + testTo2, - "Data", - "Write message", - "Close writer", - "Quit", - "Close", - }) -} - -func TestDialerSSLConfig(t *testing.T) { - d := NewPlainDialer(testHost, testSSLPort, "user", "pwd") - d.TLSConfig = testConfig - testSendMail(t, d, []string{ - "Extension AUTH", - "Auth", - "Mail " + testFrom, - "Rcpt " + testTo1, - "Rcpt " + testTo2, - "Data", - "Write message", - "Close writer", - "Quit", - "Close", - }) -} - -func TestDialerNoAuth(t *testing.T) { - d := &Dialer{ - Host: testHost, - Port: testPort, - } - testSendMail(t, d, []string{ - "Extension STARTTLS", - "StartTLS", - "Mail " + testFrom, - "Rcpt " + testTo1, - "Rcpt " + testTo2, - "Data", - "Write message", - "Close writer", - "Quit", - "Close", - }) -} - -type mockClient struct { - t *testing.T - i int - want []string - addr string - auth smtp.Auth - config *tls.Config -} - -func (c *mockClient) Extension(ext string) (bool, string) { - c.do("Extension " + ext) - return true, "" -} - -func (c *mockClient) StartTLS(config *tls.Config) error { - assertConfig(c.t, config, c.config) - c.do("StartTLS") - return nil -} - -func (c *mockClient) Auth(a smtp.Auth) error { - assertAuth(c.t, a, c.auth) - c.do("Auth") - return nil -} - -func (c *mockClient) Mail(from string) error { - c.do("Mail " + from) - return nil -} - -func (c *mockClient) Rcpt(to string) error { - c.do("Rcpt " + to) - return nil -} - -func (c *mockClient) Data() (io.WriteCloser, error) { - c.do("Data") - return &mockWriter{c: c, want: testMsg}, nil -} - -func (c *mockClient) Quit() error { - c.do("Quit") - return nil -} - -func (c *mockClient) Close() error { - c.do("Close") - return nil -} - -func (c *mockClient) do(cmd string) { - if c.i >= len(c.want) { - c.t.Fatalf("Invalid command %q", cmd) - } - - if cmd != c.want[c.i] { - c.t.Fatalf("Invalid command, got %q, want %q", cmd, c.want[c.i]) - } - c.i++ -} - -type mockWriter struct { - want string - c *mockClient - buf bytes.Buffer -} - -func (w *mockWriter) Write(p []byte) (int, error) { - if w.buf.Len() == 0 { - w.c.do("Write message") - } - w.buf.Write(p) - return len(p), nil -} - -func (w *mockWriter) Close() error { - compareBodies(w.c.t, w.buf.String(), w.want) - w.c.do("Close writer") - return nil -} - -func testSendMail(t *testing.T, d *Dialer, want []string) { - testClient := &mockClient{ - t: t, - want: want, - addr: addr(d.Host, d.Port), - auth: testAuth, - config: d.TLSConfig, - } - - smtpDial = func(addr string) (smtpClient, error) { - assertAddr(t, addr, testClient.addr) - return testClient, nil - } - - tlsDial = func(network, addr string, config *tls.Config) (*tls.Conn, error) { - if network != "tcp" { - t.Errorf("Invalid network, got %q, want tcp", network) - } - assertAddr(t, addr, testClient.addr) - assertConfig(t, config, testClient.config) - return testTLSConn, nil - } - - newClient = func(conn net.Conn, host string) (smtpClient, error) { - if conn != testTLSConn { - t.Error("Invalid TLS connection used") - } - if host != testHost { - t.Errorf("Invalid host, got %q, want %q", host, testHost) - } - return testClient, nil - } - - if err := d.DialAndSend(getTestMessage()); err != nil { - t.Error(err) - } -} - -func assertAuth(t *testing.T, got, want smtp.Auth) { - if !reflect.DeepEqual(got, want) { - t.Errorf("Invalid auth, got %#v, want %#v", got, want) - } -} - -func assertAddr(t *testing.T, got, want string) { - if got != want { - t.Errorf("Invalid addr, got %q, want %q", got, want) - } -} - -func assertConfig(t *testing.T, got, want *tls.Config) { - if want == nil { - want = &tls.Config{ServerName: testHost} - } - if got.ServerName != want.ServerName { - t.Errorf("Invalid field ServerName in config, got %q, want %q", got.ServerName, want.ServerName) - } - if got.InsecureSkipVerify != want.InsecureSkipVerify { - t.Errorf("Invalid field InsecureSkipVerify in config, got %v, want %v", got.InsecureSkipVerify, want.InsecureSkipVerify) - } -} diff --git a/vendor/gopkg.in/gomail.v2/writeto.go b/vendor/gopkg.in/gomail.v2/writeto.go deleted file mode 100644 index 57a1dd7f1..000000000 --- a/vendor/gopkg.in/gomail.v2/writeto.go +++ /dev/null @@ -1,242 +0,0 @@ -package gomail - -import ( - "encoding/base64" - "errors" - "io" - "mime" - "mime/multipart" - "path/filepath" - "time" -) - -// WriteTo implements io.WriterTo. It dumps the whole message into w. -func (m *Message) WriteTo(w io.Writer) (int64, error) { - mw := &messageWriter{w: w} - mw.writeMessage(m) - return mw.n, mw.err -} - -func (w *messageWriter) writeMessage(m *Message) { - if _, ok := m.header["Mime-Version"]; !ok { - w.writeString("Mime-Version: 1.0\r\n") - } - if _, ok := m.header["Date"]; !ok { - w.writeHeader("Date", m.FormatDate(now())) - } - w.writeHeaders(m.header) - - if m.hasMixedPart() { - w.openMultipart("mixed") - } - - if m.hasRelatedPart() { - w.openMultipart("related") - } - - if m.hasAlternativePart() { - w.openMultipart("alternative") - } - for _, part := range m.parts { - w.writeHeaders(part.header) - w.writeBody(part.copier, m.encoding) - } - if m.hasAlternativePart() { - w.closeMultipart() - } - - w.addFiles(m.embedded, false) - if m.hasRelatedPart() { - w.closeMultipart() - } - - w.addFiles(m.attachments, true) - if m.hasMixedPart() { - w.closeMultipart() - } -} - -func (m *Message) hasMixedPart() bool { - return (len(m.parts) > 0 && len(m.attachments) > 0) || len(m.attachments) > 1 -} - -func (m *Message) hasRelatedPart() bool { - return (len(m.parts) > 0 && len(m.embedded) > 0) || len(m.embedded) > 1 -} - -func (m *Message) hasAlternativePart() bool { - return len(m.parts) > 1 -} - -type messageWriter struct { - w io.Writer - n int64 - writers [3]*multipart.Writer - partWriter io.Writer - depth uint8 - err error -} - -func (w *messageWriter) openMultipart(mimeType string) { - mw := multipart.NewWriter(w) - contentType := "multipart/" + mimeType + "; boundary=" + mw.Boundary() - w.writers[w.depth] = mw - - if w.depth == 0 { - w.writeHeader("Content-Type", contentType) - w.writeString("\r\n") - } else { - w.createPart(map[string][]string{ - "Content-Type": {contentType}, - }) - } - w.depth++ -} - -func (w *messageWriter) createPart(h map[string][]string) { - w.partWriter, w.err = w.writers[w.depth-1].CreatePart(h) -} - -func (w *messageWriter) closeMultipart() { - if w.depth > 0 { - w.writers[w.depth-1].Close() - w.depth-- - } -} - -func (w *messageWriter) addFiles(files []*file, isAttachment bool) { - for _, f := range files { - if _, ok := f.Header["Content-Type"]; !ok { - mediaType := mime.TypeByExtension(filepath.Ext(f.Name)) - if mediaType == "" { - mediaType = "application/octet-stream" - } - f.setHeader("Content-Type", mediaType+`; name="`+f.Name+`"`) - } - - if _, ok := f.Header["Content-Transfer-Encoding"]; !ok { - f.setHeader("Content-Transfer-Encoding", string(Base64)) - } - - if _, ok := f.Header["Content-Disposition"]; !ok { - var disp string - if isAttachment { - disp = "attachment" - } else { - disp = "inline" - } - f.setHeader("Content-Disposition", disp+`; filename="`+f.Name+`"`) - } - - if !isAttachment { - if _, ok := f.Header["Content-ID"]; !ok { - f.setHeader("Content-ID", "<"+f.Name+">") - } - } - w.writeHeaders(f.Header) - w.writeBody(f.CopyFunc, Base64) - } -} - -func (w *messageWriter) Write(p []byte) (int, error) { - if w.err != nil { - return 0, errors.New("gomail: cannot write as writer is in error") - } - - var n int - n, w.err = w.w.Write(p) - w.n += int64(n) - return n, w.err -} - -func (w *messageWriter) writeString(s string) { - n, _ := io.WriteString(w.w, s) - w.n += int64(n) -} - -func (w *messageWriter) writeStrings(a []string, sep string) { - if len(a) > 0 { - w.writeString(a[0]) - if len(a) == 1 { - return - } - } - for _, s := range a[1:] { - w.writeString(sep) - w.writeString(s) - } -} - -func (w *messageWriter) writeHeader(k string, v ...string) { - w.writeString(k) - w.writeString(": ") - w.writeStrings(v, ", ") - w.writeString("\r\n") -} - -func (w *messageWriter) writeHeaders(h map[string][]string) { - if w.depth == 0 { - for k, v := range h { - if k != "Bcc" { - w.writeHeader(k, v...) - } - } - } else { - w.createPart(h) - } -} - -func (w *messageWriter) writeBody(f func(io.Writer) error, enc Encoding) { - var subWriter io.Writer - if w.depth == 0 { - w.writeString("\r\n") - subWriter = w.w - } else { - subWriter = w.partWriter - } - - if enc == Base64 { - wc := base64.NewEncoder(base64.StdEncoding, newBase64LineWriter(subWriter)) - w.err = f(wc) - wc.Close() - } else if enc == Unencoded { - w.err = f(subWriter) - } else { - wc := newQPWriter(subWriter) - w.err = f(wc) - wc.Close() - } -} - -// As required by RFC 2045, 6.7. (page 21) for quoted-printable, and -// RFC 2045, 6.8. (page 25) for base64. -const maxLineLen = 76 - -// base64LineWriter limits text encoded in base64 to 76 characters per line -type base64LineWriter struct { - w io.Writer - lineLen int -} - -func newBase64LineWriter(w io.Writer) *base64LineWriter { - return &base64LineWriter{w: w} -} - -func (w *base64LineWriter) Write(p []byte) (int, error) { - n := 0 - for len(p)+w.lineLen > maxLineLen { - w.w.Write(p[:maxLineLen-w.lineLen]) - w.w.Write([]byte("\r\n")) - p = p[maxLineLen-w.lineLen:] - n += maxLineLen - w.lineLen - w.lineLen = 0 - } - - w.w.Write(p) - w.lineLen += len(p) - - return n + len(p), nil -} - -// Stubbed out for testing. -var now = time.Now -- cgit v1.2.3-1-g7c22