From b9de1157289455b0ca26daff519d4a0ddcd1fa13 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Wed, 24 Feb 2016 13:48:45 -0800 Subject: Update 4.8.1 to 4.8.3. My previous drop was the wrong version. The platform mingw is currently using 4.8.3, not 4.8.1 (not sure how I got that wrong). From ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.3/gcc-4.8.3.tar.bz2. Bug: http://b/26523949 Change-Id: Id85f1bdcbbaf78c7d0b5a69e74c798a08f341c35 --- gcc-4.8.1/libgo/go/net/smtp/auth.go | 98 ------- gcc-4.8.1/libgo/go/net/smtp/smtp.go | 341 ---------------------- gcc-4.8.1/libgo/go/net/smtp/smtp_test.go | 468 ------------------------------- 3 files changed, 907 deletions(-) delete mode 100644 gcc-4.8.1/libgo/go/net/smtp/auth.go delete mode 100644 gcc-4.8.1/libgo/go/net/smtp/smtp.go delete mode 100644 gcc-4.8.1/libgo/go/net/smtp/smtp_test.go (limited to 'gcc-4.8.1/libgo/go/net/smtp') diff --git a/gcc-4.8.1/libgo/go/net/smtp/auth.go b/gcc-4.8.1/libgo/go/net/smtp/auth.go deleted file mode 100644 index d401e3c21..000000000 --- a/gcc-4.8.1/libgo/go/net/smtp/auth.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package smtp - -import ( - "crypto/hmac" - "crypto/md5" - "errors" - "fmt" -) - -// Auth is implemented by an SMTP authentication mechanism. -type Auth interface { - // Start begins an authentication with a server. - // It returns the name of the authentication protocol - // and optionally data to include in the initial AUTH message - // sent to the server. It can return proto == "" to indicate - // that the authentication should be skipped. - // If it returns a non-nil error, the SMTP client aborts - // the authentication attempt and closes the connection. - Start(server *ServerInfo) (proto string, toServer []byte, err error) - - // Next continues the authentication. The server has just sent - // the fromServer data. If more is true, the server expects a - // response, which Next should return as toServer; otherwise - // Next should return toServer == nil. - // If Next returns a non-nil error, the SMTP client aborts - // the authentication attempt and closes the connection. - Next(fromServer []byte, more bool) (toServer []byte, err error) -} - -// ServerInfo records information about an SMTP server. -type ServerInfo struct { - Name string // SMTP server name - TLS bool // using TLS, with valid certificate for Name - Auth []string // advertised authentication mechanisms -} - -type plainAuth struct { - identity, username, password string - host string -} - -// PlainAuth returns an Auth that implements the PLAIN authentication -// mechanism as defined in RFC 4616. -// The returned Auth uses the given username and password to authenticate -// on TLS connections to host and act as identity. Usually identity will be -// left blank to act as username. -func PlainAuth(identity, username, password, host string) Auth { - return &plainAuth{identity, username, password, host} -} - -func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) { - if !server.TLS { - return "", nil, errors.New("unencrypted connection") - } - if server.Name != a.host { - return "", nil, errors.New("wrong host name") - } - resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password) - return "PLAIN", resp, nil -} - -func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) { - if more { - // We've already sent everything. - return nil, errors.New("unexpected server challenge") - } - return nil, nil -} - -type cramMD5Auth struct { - username, secret string -} - -// CRAMMD5Auth returns an Auth that implements the CRAM-MD5 authentication -// mechanism as defined in RFC 2195. -// The returned Auth uses the given username and secret to authenticate -// to the server using the challenge-response mechanism. -func CRAMMD5Auth(username, secret string) Auth { - return &cramMD5Auth{username, secret} -} - -func (a *cramMD5Auth) Start(server *ServerInfo) (string, []byte, error) { - return "CRAM-MD5", nil, nil -} - -func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) { - if more { - d := hmac.New(md5.New, []byte(a.secret)) - d.Write(fromServer) - s := make([]byte, 0, d.Size()) - return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil - } - return nil, nil -} diff --git a/gcc-4.8.1/libgo/go/net/smtp/smtp.go b/gcc-4.8.1/libgo/go/net/smtp/smtp.go deleted file mode 100644 index 4b9177877..000000000 --- a/gcc-4.8.1/libgo/go/net/smtp/smtp.go +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package smtp implements the Simple Mail Transfer Protocol as defined in RFC 5321. -// It also implements the following extensions: -// 8BITMIME RFC 1652 -// AUTH RFC 2554 -// STARTTLS RFC 3207 -// Additional extensions may be handled by clients. -package smtp - -import ( - "crypto/tls" - "encoding/base64" - "errors" - "io" - "net" - "net/textproto" - "strings" -) - -// A Client represents a client connection to an SMTP server. -type Client struct { - // Text is the textproto.Conn used by the Client. It is exported to allow for - // clients to add extensions. - Text *textproto.Conn - // keep a reference to the connection so it can be used to create a TLS - // connection later - conn net.Conn - // whether the Client is using TLS - tls bool - serverName string - // map of supported extensions - ext map[string]string - // supported auth mechanisms - auth []string - localName string // the name to use in HELO/EHLO - didHello bool // whether we've said HELO/EHLO - helloError error // the error from the hello -} - -// Dial returns a new Client connected to an SMTP server at addr. -func Dial(addr string) (*Client, error) { - conn, err := net.Dial("tcp", addr) - if err != nil { - return nil, err - } - host := addr[:strings.Index(addr, ":")] - return NewClient(conn, host) -} - -// NewClient returns a new Client using an existing connection and host as a -// server name to be used when authenticating. -func NewClient(conn net.Conn, host string) (*Client, error) { - text := textproto.NewConn(conn) - _, _, err := text.ReadResponse(220) - if err != nil { - text.Close() - return nil, err - } - c := &Client{Text: text, conn: conn, serverName: host, localName: "localhost"} - return c, nil -} - -// hello runs a hello exchange if needed. -func (c *Client) hello() error { - if !c.didHello { - c.didHello = true - err := c.ehlo() - if err != nil { - c.helloError = c.helo() - } - } - return c.helloError -} - -// Hello sends a HELO or EHLO to the server as the given host name. -// Calling this method is only necessary if the client needs control -// over the host name used. The client will introduce itself as "localhost" -// automatically otherwise. If Hello is called, it must be called before -// any of the other methods. -func (c *Client) Hello(localName string) error { - if c.didHello { - return errors.New("smtp: Hello called after other methods") - } - c.localName = localName - return c.hello() -} - -// cmd is a convenience function that sends a command and returns the response -func (c *Client) cmd(expectCode int, format string, args ...interface{}) (int, string, error) { - id, err := c.Text.Cmd(format, args...) - if err != nil { - return 0, "", err - } - c.Text.StartResponse(id) - defer c.Text.EndResponse(id) - code, msg, err := c.Text.ReadResponse(expectCode) - return code, msg, err -} - -// helo sends the HELO greeting to the server. It should be used only when the -// server does not support ehlo. -func (c *Client) helo() error { - c.ext = nil - _, _, err := c.cmd(250, "HELO %s", c.localName) - return err -} - -// ehlo sends the EHLO (extended hello) greeting to the server. It -// should be the preferred greeting for servers that support it. -func (c *Client) ehlo() error { - _, msg, err := c.cmd(250, "EHLO %s", c.localName) - if err != nil { - return err - } - ext := make(map[string]string) - extList := strings.Split(msg, "\n") - if len(extList) > 1 { - extList = extList[1:] - for _, line := range extList { - args := strings.SplitN(line, " ", 2) - if len(args) > 1 { - ext[args[0]] = args[1] - } else { - ext[args[0]] = "" - } - } - } - if mechs, ok := ext["AUTH"]; ok { - c.auth = strings.Split(mechs, " ") - } - c.ext = ext - return err -} - -// StartTLS sends the STARTTLS command and encrypts all further communication. -// Only servers that advertise the STARTTLS extension support this function. -func (c *Client) StartTLS(config *tls.Config) error { - if err := c.hello(); err != nil { - return err - } - _, _, err := c.cmd(220, "STARTTLS") - if err != nil { - return err - } - c.conn = tls.Client(c.conn, config) - c.Text = textproto.NewConn(c.conn) - c.tls = true - return c.ehlo() -} - -// Verify checks the validity of an email address on the server. -// If Verify returns nil, the address is valid. A non-nil return -// does not necessarily indicate an invalid address. Many servers -// will not verify addresses for security reasons. -func (c *Client) Verify(addr string) error { - if err := c.hello(); err != nil { - return err - } - _, _, err := c.cmd(250, "VRFY %s", addr) - return err -} - -// Auth authenticates a client using the provided authentication mechanism. -// A failed authentication closes the connection. -// Only servers that advertise the AUTH extension support this function. -func (c *Client) Auth(a Auth) error { - if err := c.hello(); err != nil { - return err - } - encoding := base64.StdEncoding - mech, resp, err := a.Start(&ServerInfo{c.serverName, c.tls, c.auth}) - if err != nil { - c.Quit() - return err - } - resp64 := make([]byte, encoding.EncodedLen(len(resp))) - encoding.Encode(resp64, resp) - code, msg64, err := c.cmd(0, "AUTH %s %s", mech, resp64) - for err == nil { - var msg []byte - switch code { - case 334: - msg, err = encoding.DecodeString(msg64) - case 235: - // the last message isn't base64 because it isn't a challenge - msg = []byte(msg64) - default: - err = &textproto.Error{Code: code, Msg: msg64} - } - resp, err = a.Next(msg, code == 334) - if err != nil { - // abort the AUTH - c.cmd(501, "*") - c.Quit() - break - } - if resp == nil { - break - } - resp64 = make([]byte, encoding.EncodedLen(len(resp))) - encoding.Encode(resp64, resp) - code, msg64, err = c.cmd(0, string(resp64)) - } - return err -} - -// Mail issues a MAIL command to the server using the provided email address. -// If the server supports the 8BITMIME extension, Mail adds the BODY=8BITMIME -// parameter. -// This initiates a mail transaction and is followed by one or more Rcpt calls. -func (c *Client) Mail(from string) error { - if err := c.hello(); err != nil { - return err - } - cmdStr := "MAIL FROM:<%s>" - if c.ext != nil { - if _, ok := c.ext["8BITMIME"]; ok { - cmdStr += " BODY=8BITMIME" - } - } - _, _, err := c.cmd(250, cmdStr, from) - return err -} - -// Rcpt issues a RCPT command to the server using the provided email address. -// A call to Rcpt must be preceded by a call to Mail and may be followed by -// a Data call or another Rcpt call. -func (c *Client) Rcpt(to string) error { - _, _, err := c.cmd(25, "RCPT TO:<%s>", to) - return err -} - -type dataCloser struct { - c *Client - io.WriteCloser -} - -func (d *dataCloser) Close() error { - d.WriteCloser.Close() - _, _, err := d.c.Text.ReadResponse(250) - return err -} - -// Data issues a DATA command to the server and returns a writer that -// can be used to write the data. The caller should close the writer -// before calling any more methods on c. -// A call to Data must be preceded by one or more calls to Rcpt. -func (c *Client) Data() (io.WriteCloser, error) { - _, _, err := c.cmd(354, "DATA") - if err != nil { - return nil, err - } - return &dataCloser{c, c.Text.DotWriter()}, nil -} - -// SendMail connects to the server at addr, switches to TLS if possible, -// authenticates with mechanism a if possible, and then sends an email from -// address from, to addresses to, with message msg. -func SendMail(addr string, a Auth, from string, to []string, msg []byte) error { - c, err := Dial(addr) - if err != nil { - return err - } - if err := c.hello(); err != nil { - return err - } - if ok, _ := c.Extension("STARTTLS"); ok { - if err = c.StartTLS(nil); err != nil { - return err - } - } - if a != nil && c.ext != nil { - if _, ok := c.ext["AUTH"]; ok { - if err = c.Auth(a); err != nil { - return err - } - } - } - 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 - } - _, err = w.Write(msg) - if err != nil { - return err - } - err = w.Close() - if err != nil { - return err - } - return c.Quit() -} - -// Extension reports whether an extension is support by the server. -// The extension name is case-insensitive. If the extension is supported, -// Extension also returns a string that contains any parameters the -// server specifies for the extension. -func (c *Client) Extension(ext string) (bool, string) { - if err := c.hello(); err != nil { - return false, "" - } - if c.ext == nil { - return false, "" - } - ext = strings.ToUpper(ext) - param, ok := c.ext[ext] - return ok, param -} - -// Reset sends the RSET command to the server, aborting the current mail -// transaction. -func (c *Client) Reset() error { - if err := c.hello(); err != nil { - return err - } - _, _, err := c.cmd(250, "RSET") - return err -} - -// Quit sends the QUIT command and closes the connection to the server. -func (c *Client) Quit() error { - if err := c.hello(); err != nil { - return err - } - _, _, err := c.cmd(221, "QUIT") - if err != nil { - return err - } - return c.Text.Close() -} diff --git a/gcc-4.8.1/libgo/go/net/smtp/smtp_test.go b/gcc-4.8.1/libgo/go/net/smtp/smtp_test.go deleted file mode 100644 index 8317428cb..000000000 --- a/gcc-4.8.1/libgo/go/net/smtp/smtp_test.go +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package smtp - -import ( - "bufio" - "bytes" - "io" - "net" - "net/textproto" - "strings" - "testing" - "time" -) - -type authTest struct { - auth Auth - challenges []string - name string - responses []string -} - -var authTests = []authTest{ - {PlainAuth("", "user", "pass", "testserver"), []string{}, "PLAIN", []string{"\x00user\x00pass"}}, - {PlainAuth("foo", "bar", "baz", "testserver"), []string{}, "PLAIN", []string{"foo\x00bar\x00baz"}}, - {CRAMMD5Auth("user", "pass"), []string{"<123456.1322876914@testserver>"}, "CRAM-MD5", []string{"", "user 287eb355114cf5c471c26a875f1ca4ae"}}, -} - -func TestAuth(t *testing.T) { -testLoop: - for i, test := range authTests { - name, resp, err := test.auth.Start(&ServerInfo{"testserver", true, nil}) - if name != test.name { - t.Errorf("#%d got name %s, expected %s", i, name, test.name) - } - if !bytes.Equal(resp, []byte(test.responses[0])) { - t.Errorf("#%d got response %s, expected %s", i, resp, test.responses[0]) - } - if err != nil { - t.Errorf("#%d error: %s", i, err) - } - for j := range test.challenges { - challenge := []byte(test.challenges[j]) - expected := []byte(test.responses[j+1]) - resp, err := test.auth.Next(challenge, true) - if err != nil { - t.Errorf("#%d error: %s", i, err) - continue testLoop - } - if !bytes.Equal(resp, expected) { - t.Errorf("#%d got %s, expected %s", i, resp, expected) - continue testLoop - } - } - } -} - -type faker struct { - io.ReadWriter -} - -func (f faker) Close() error { return nil } -func (f faker) LocalAddr() net.Addr { return nil } -func (f faker) RemoteAddr() net.Addr { return nil } -func (f faker) SetDeadline(time.Time) error { return nil } -func (f faker) SetReadDeadline(time.Time) error { return nil } -func (f faker) SetWriteDeadline(time.Time) error { return nil } - -func TestBasic(t *testing.T) { - server := strings.Join(strings.Split(basicServer, "\n"), "\r\n") - client := strings.Join(strings.Split(basicClient, "\n"), "\r\n") - - var cmdbuf bytes.Buffer - bcmdbuf := bufio.NewWriter(&cmdbuf) - var fake faker - fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf) - c := &Client{Text: textproto.NewConn(fake), localName: "localhost"} - - if err := c.helo(); err != nil { - t.Fatalf("HELO failed: %s", err) - } - if err := c.ehlo(); err == nil { - t.Fatalf("Expected first EHLO to fail") - } - if err := c.ehlo(); err != nil { - t.Fatalf("Second EHLO failed: %s", err) - } - - c.didHello = true - if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" { - t.Fatalf("Expected AUTH supported") - } - if ok, _ := c.Extension("DSN"); ok { - t.Fatalf("Shouldn't support DSN") - } - - if err := c.Mail("user@gmail.com"); err == nil { - t.Fatalf("MAIL should require authentication") - } - - if err := c.Verify("user1@gmail.com"); err == nil { - t.Fatalf("First VRFY: expected no verification") - } - if err := c.Verify("user2@gmail.com"); err != nil { - t.Fatalf("Second VRFY: expected verification, got %s", err) - } - - // fake TLS so authentication won't complain - c.tls = true - c.serverName = "smtp.google.com" - if err := c.Auth(PlainAuth("", "user", "pass", "smtp.google.com")); err != nil { - t.Fatalf("AUTH failed: %s", err) - } - - if err := c.Mail("user@gmail.com"); err != nil { - t.Fatalf("MAIL failed: %s", err) - } - if err := c.Rcpt("golang-nuts@googlegroups.com"); err != nil { - t.Fatalf("RCPT failed: %s", err) - } - msg := `From: user@gmail.com -To: golang-nuts@googlegroups.com -Subject: Hooray for Go - -Line 1 -.Leading dot line . -Goodbye.` - w, err := c.Data() - if err != nil { - t.Fatalf("DATA failed: %s", err) - } - if _, err := w.Write([]byte(msg)); err != nil { - t.Fatalf("Data write failed: %s", err) - } - if err := w.Close(); err != nil { - t.Fatalf("Bad data response: %s", err) - } - - if err := c.Quit(); err != nil { - t.Fatalf("QUIT failed: %s", err) - } - - bcmdbuf.Flush() - actualcmds := cmdbuf.String() - if client != actualcmds { - t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client) - } -} - -var basicServer = `250 mx.google.com at your service -502 Unrecognized command. -250-mx.google.com at your service -250-SIZE 35651584 -250-AUTH LOGIN PLAIN -250 8BITMIME -530 Authentication required -252 Send some mail, I'll try my best -250 User is valid -235 Accepted -250 Sender OK -250 Receiver OK -354 Go ahead -250 Data OK -221 OK -` - -var basicClient = `HELO localhost -EHLO localhost -EHLO localhost -MAIL FROM: BODY=8BITMIME -VRFY user1@gmail.com -VRFY user2@gmail.com -AUTH PLAIN AHVzZXIAcGFzcw== -MAIL FROM: BODY=8BITMIME -RCPT TO: -DATA -From: user@gmail.com -To: golang-nuts@googlegroups.com -Subject: Hooray for Go - -Line 1 -..Leading dot line . -Goodbye. -. -QUIT -` - -func TestNewClient(t *testing.T) { - server := strings.Join(strings.Split(newClientServer, "\n"), "\r\n") - client := strings.Join(strings.Split(newClientClient, "\n"), "\r\n") - - var cmdbuf bytes.Buffer - bcmdbuf := bufio.NewWriter(&cmdbuf) - out := func() string { - bcmdbuf.Flush() - return cmdbuf.String() - } - var fake faker - fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf) - c, err := NewClient(fake, "fake.host") - if err != nil { - t.Fatalf("NewClient: %v\n(after %v)", err, out()) - } - if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" { - t.Fatalf("Expected AUTH supported") - } - if ok, _ := c.Extension("DSN"); ok { - t.Fatalf("Shouldn't support DSN") - } - if err := c.Quit(); err != nil { - t.Fatalf("QUIT failed: %s", err) - } - - actualcmds := out() - if client != actualcmds { - t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client) - } -} - -var newClientServer = `220 hello world -250-mx.google.com at your service -250-SIZE 35651584 -250-AUTH LOGIN PLAIN -250 8BITMIME -221 OK -` - -var newClientClient = `EHLO localhost -QUIT -` - -func TestNewClient2(t *testing.T) { - server := strings.Join(strings.Split(newClient2Server, "\n"), "\r\n") - client := strings.Join(strings.Split(newClient2Client, "\n"), "\r\n") - - var cmdbuf bytes.Buffer - bcmdbuf := bufio.NewWriter(&cmdbuf) - var fake faker - fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf) - c, err := NewClient(fake, "fake.host") - if err != nil { - t.Fatalf("NewClient: %v", err) - } - if ok, _ := c.Extension("DSN"); ok { - t.Fatalf("Shouldn't support DSN") - } - if err := c.Quit(); err != nil { - t.Fatalf("QUIT failed: %s", err) - } - - bcmdbuf.Flush() - actualcmds := cmdbuf.String() - if client != actualcmds { - t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client) - } -} - -var newClient2Server = `220 hello world -502 EH? -250-mx.google.com at your service -250-SIZE 35651584 -250-AUTH LOGIN PLAIN -250 8BITMIME -221 OK -` - -var newClient2Client = `EHLO localhost -HELO localhost -QUIT -` - -func TestHello(t *testing.T) { - - if len(helloServer) != len(helloClient) { - t.Fatalf("Hello server and client size mismatch") - } - - for i := 0; i < len(helloServer); i++ { - server := strings.Join(strings.Split(baseHelloServer+helloServer[i], "\n"), "\r\n") - client := strings.Join(strings.Split(baseHelloClient+helloClient[i], "\n"), "\r\n") - var cmdbuf bytes.Buffer - bcmdbuf := bufio.NewWriter(&cmdbuf) - var fake faker - fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf) - c, err := NewClient(fake, "fake.host") - if err != nil { - t.Fatalf("NewClient: %v", err) - } - c.localName = "customhost" - err = nil - - switch i { - case 0: - err = c.Hello("customhost") - case 1: - err = c.StartTLS(nil) - if err.Error() == "502 Not implemented" { - err = nil - } - case 2: - err = c.Verify("test@example.com") - case 3: - c.tls = true - c.serverName = "smtp.google.com" - err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com")) - case 4: - err = c.Mail("test@example.com") - case 5: - ok, _ := c.Extension("feature") - if ok { - t.Errorf("Expected FEATURE not to be supported") - } - case 6: - err = c.Reset() - case 7: - err = c.Quit() - case 8: - err = c.Verify("test@example.com") - if err != nil { - err = c.Hello("customhost") - if err != nil { - t.Errorf("Want error, got none") - } - } - default: - t.Fatalf("Unhandled command") - } - - if err != nil { - t.Errorf("Command %d failed: %v", i, err) - } - - bcmdbuf.Flush() - actualcmds := cmdbuf.String() - if client != actualcmds { - t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client) - } - } -} - -var baseHelloServer = `220 hello world -502 EH? -250-mx.google.com at your service -250 FEATURE -` - -var helloServer = []string{ - "", - "502 Not implemented\n", - "250 User is valid\n", - "235 Accepted\n", - "250 Sender ok\n", - "", - "250 Reset ok\n", - "221 Goodbye\n", - "250 Sender ok\n", -} - -var baseHelloClient = `EHLO customhost -HELO customhost -` - -var helloClient = []string{ - "", - "STARTTLS\n", - "VRFY test@example.com\n", - "AUTH PLAIN AHVzZXIAcGFzcw==\n", - "MAIL FROM:\n", - "", - "RSET\n", - "QUIT\n", - "VRFY test@example.com\n", -} - -func TestSendMail(t *testing.T) { - server := strings.Join(strings.Split(sendMailServer, "\n"), "\r\n") - client := strings.Join(strings.Split(sendMailClient, "\n"), "\r\n") - var cmdbuf bytes.Buffer - bcmdbuf := bufio.NewWriter(&cmdbuf) - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatalf("Unable to to create listener: %v", err) - } - defer l.Close() - - // prevent data race on bcmdbuf - var done = make(chan struct{}) - go func(data []string) { - - defer close(done) - - conn, err := l.Accept() - if err != nil { - t.Errorf("Accept error: %v", err) - return - } - defer conn.Close() - - tc := textproto.NewConn(conn) - for i := 0; i < len(data) && data[i] != ""; i++ { - tc.PrintfLine(data[i]) - for len(data[i]) >= 4 && data[i][3] == '-' { - i++ - tc.PrintfLine(data[i]) - } - if data[i] == "221 Goodbye" { - return - } - read := false - for !read || data[i] == "354 Go ahead" { - msg, err := tc.ReadLine() - bcmdbuf.Write([]byte(msg + "\r\n")) - read = true - if err != nil { - t.Errorf("Read error: %v", err) - return - } - if data[i] == "354 Go ahead" && msg == "." { - break - } - } - } - }(strings.Split(server, "\r\n")) - - err = SendMail(l.Addr().String(), nil, "test@example.com", []string{"other@example.com"}, []byte(strings.Replace(`From: test@example.com -To: other@example.com -Subject: SendMail test - -SendMail is working for me. -`, "\n", "\r\n", -1))) - - if err != nil { - t.Errorf("%v", err) - } - - <-done - bcmdbuf.Flush() - actualcmds := cmdbuf.String() - if client != actualcmds { - t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client) - } -} - -var sendMailServer = `220 hello world -502 EH? -250 mx.google.com at your service -250 Sender ok -250 Receiver ok -354 Go ahead -250 Data ok -221 Goodbye -` - -var sendMailClient = `EHLO localhost -HELO localhost -MAIL FROM: -RCPT TO: -DATA -From: test@example.com -To: other@example.com -Subject: SendMail test - -SendMail is working for me. -. -QUIT -` -- cgit v1.2.3