1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
package mail
import (
"fmt"
"log"
"net"
"testing"
"time"
)
func TestSendRace(t *testing.T) {
port := 56666
port2 := 56667
timeout := 1 * time.Second
responses := []string{
`220 test connected`,
`250 after helo`,
`250 after mail from`,
`250 after rcpt to`,
`354 after data`,
}
startService(port, responses, 5*time.Second)
startService(port2, responses, 0)
server := NewSMTPClient()
server.ConnectTimeout = timeout
server.SendTimeout = timeout
server.KeepAlive = false
server.Host = `127.0.0.1`
server.Port = port
smtpClient, err := server.Connect()
if err != nil {
log.Fatalf("couldn't connect: %s", err.Error())
}
defer smtpClient.Close()
// create another server in other port to test timeouts
server.Port = port2
smtpClient2, err := server.Connect()
if err != nil {
log.Fatalf("couldn't connect: %s", err.Error())
}
defer smtpClient2.Close()
msg := NewMSG().
SetFrom(`foo@bar`).
AddTo(`rcpt@bar`).
SetSubject("subject").
SetBody(TextPlain, "body")
// the smtpClient2 has not timeout
err = msg.Send(smtpClient2)
if err != nil {
log.Fatalf("couldn't send: %s", err.Error())
}
// the smtpClient send to listener with the last response is after SendTimeout, so when this error is returned the test succeed.
err = msg.Send(smtpClient)
if err != nil && err.Error() != "Mail Error: SMTP Send timed out" {
log.Fatalf("couldn't send: %s", err.Error())
}
}
func startService(port int, responses []string, timeout time.Duration) {
log.Printf("starting service at %d...\n", port)
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("couldn't listen to port %d: %s", port, err)
}
go func() {
for {
conn, err := listener.Accept()
if err != nil {
log.Fatalf("couldn't listen accept the request in port %d", port)
}
go respond(conn, responses, timeout)
}
}()
}
func respond(conn net.Conn, responses []string, timeout time.Duration) {
buf := make([]byte, 1024)
for _, resp := range responses {
write(conn, resp)
n, err := conn.Read(buf)
if err != nil {
log.Println("couldn't read data")
return
}
readStr := string(buf[:n])
log.Printf("READ:%s", string(readStr))
}
// if timeout, sleep for that time, otherwise sent a 250 OK
if timeout > 0 {
time.Sleep(timeout)
} else {
write(conn, "250 OK")
}
conn.Close()
fmt.Print("\n\n")
}
func write(conn net.Conn, command string) {
log.Printf("WRITE:%s", command)
conn.Write([]byte(command + "\n"))
}
|