aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgo/go/net/smtp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgo/go/net/smtp')
-rw-r--r--gcc-4.8.1/libgo/go/net/smtp/auth.go98
-rw-r--r--gcc-4.8.1/libgo/go/net/smtp/smtp.go341
-rw-r--r--gcc-4.8.1/libgo/go/net/smtp/smtp_test.go468
3 files changed, 0 insertions, 907 deletions
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:<user@gmail.com> BODY=8BITMIME
-VRFY user1@gmail.com
-VRFY user2@gmail.com
-AUTH PLAIN AHVzZXIAcGFzcw==
-MAIL FROM:<user@gmail.com> BODY=8BITMIME
-RCPT TO:<golang-nuts@googlegroups.com>
-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:<test@example.com>\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:<test@example.com>
-RCPT TO:<other@example.com>
-DATA
-From: test@example.com
-To: other@example.com
-Subject: SendMail test
-
-SendMail is working for me.
-.
-QUIT
-`