github.com/go-email-validator/go-email-validator@v0.0.0-20230409163946-b8b9e6a0552e/test/mock/ev/evsmtp/server.go (about) 1 package mockevsmtp 2 3 import ( 4 "bufio" 5 "bytes" 6 "net" 7 "net/textproto" 8 "sync" 9 "testing" 10 "time" 11 ) 12 13 // Separator separate mock message of Server 14 const Separator = "\r\n" 15 16 // SuccessServer contents success smtp server response 17 var SuccessServer = []string{ 18 "220 hello world", 19 "502 EH?", 20 "250 mx.google.com at your service", 21 "250 Sender ok", 22 "550 address does not exist", 23 "250 Receiver ok", 24 "221 Goodbye", 25 } 26 27 // Server to testing SMTP 28 // Partial copy of TestSendMail from smtp.TestSendMail 29 func Server( 30 t testing.TB, 31 server []string, 32 timeout time.Duration, 33 addr string, 34 infinite bool, 35 ) (string, chan string) { 36 var cmdbuf bytes.Buffer 37 bcmdbuf := bufio.NewWriter(&cmdbuf) 38 39 if addr == "" { 40 addr = "0.0.0.0:0" 41 } 42 43 l, err := net.Listen("tcp", addr) 44 if err != nil { 45 t.Fatalf("Unable to create listener: %v", err) 46 } 47 48 var done = make(chan string) 49 closedMu := &sync.Mutex{} 50 closed := false 51 closeServer := func() { 52 closedMu.Lock() 53 if !closed { 54 closed = true 55 bcmdbuf.Flush() 56 done <- cmdbuf.String() 57 close(done) 58 l.Close() 59 } 60 closedMu.Unlock() 61 } 62 go func(data []string) { 63 defer closeServer() 64 65 if len(data) == 0 { 66 return 67 } 68 for { 69 func() { 70 conn, err := l.Accept() 71 if err != nil { 72 t.Errorf("Accept error: %v", err) 73 return 74 } 75 defer conn.Close() 76 77 tc := textproto.NewConn(conn) 78 79 for i := 0; i < len(data) && data[i] != ""; i++ { 80 tc.PrintfLine(data[i]) 81 for len(data[i]) >= 4 && data[i][3] == '-' { 82 i++ 83 tc.PrintfLine(data[i]) 84 } 85 if data[i] == "221 Goodbye" { 86 return 87 } 88 read := false 89 for !read || data[i] == "354 Go ahead" { 90 msg, err := tc.ReadLine() 91 bcmdbuf.Write([]byte(msg + Separator)) 92 read = true 93 if err != nil { 94 t.Errorf("Read error: %v", err) 95 return 96 } 97 if data[i] == "354 Go ahead" && msg == "." { 98 break 99 } 100 } 101 } 102 }() 103 104 if !infinite { 105 break 106 } 107 } 108 }(server) 109 110 go func() { 111 if timeout > 0 { 112 time.Sleep(timeout) 113 closeServer() 114 } 115 }() 116 117 return l.Addr().String(), done 118 }