]>
src.bluestatic.org Git - mailpopbox.git/blob - smtp/conn_test.go
14 "github.com/uber-go/zap"
17 func _fl(depth
int) string {
18 _
, file
, line
, _
:= runtime
.Caller(depth
+ 1)
19 return fmt
.Sprintf("[%s:%d]", filepath
.Base(file
), line
)
22 func ok(t testing
.TB
, err error
) {
24 t
.Errorf("%s unexpected error: %v", _fl(1), err
)
28 func readCodeLine(t testing
.TB
, conn
*textproto
.Conn
, code
int) string {
29 _
, message
, err
:= conn
.ReadCodeLine(code
)
31 t
.Errorf("%s ReadCodeLine error: %v", _fl(1), err
)
36 // runServer creates a TCP socket, runs a listening server, and returns the connection.
37 // The server exits when the Conn is closed.
38 func runServer(t
*testing
.T
, server Server
) net
.Listener
{
39 l
, err
:= net
.Listen("tcp", "localhost:0")
47 conn
, err
:= l
.Accept()
51 go AcceptConnection(conn
, server
, zap
.New(zap
.NullEncoder()))
58 type testServer
struct {
63 func (s
*testServer
) Name() string {
67 func (s
*testServer
) VerifyAddress(addr mail
.Address
) ReplyLine
{
68 for _
, block
:= range s
.blockList
{
69 if strings
.ToLower(block
) == addr
.Address
{
70 return ReplyBadMailbox
76 func createClient(t
*testing
.T
, addr net
.Addr
) *textproto
.Conn
{
77 conn
, err
:= textproto
.Dial(addr
.Network(), addr
.String())
85 type requestResponse
struct {
88 handler
func(testing
.TB
, *textproto
.Conn
)
91 func runTableTest(t testing
.TB
, conn
*textproto
.Conn
, seq
[]requestResponse
) {
92 for i
, rr
:= range seq
{
93 t
.Logf("%s case %d", _fl(1), i
)
94 ok(t
, conn
.PrintfLine(rr
.request
))
95 if rr
.handler
!= nil {
98 readCodeLine(t
, conn
, rr
.responseCode
)
104 func TestScenarioTypical(t
*testing
.T
) {
106 blockList
: []string{"Green@foo.com"},
108 l
:= runServer(t
, &s
)
111 conn
:= createClient(t
, l
.Addr())
113 message
:= readCodeLine(t
, conn
, 220)
114 if !strings
.HasPrefix(message
, s
.Name()) {
115 t
.Errorf("Greeting does not have server name, got %q", message
)
118 greet
:= "greeting.TestScenarioTypical"
119 ok(t
, conn
.PrintfLine("EHLO "+greet
))
121 _
, message
, err
:= conn
.ReadResponse(250)
123 if !strings
.Contains(message
, greet
) {
124 t
.Errorf("EHLO response does not contain greeting, got %q", message
)
127 ok(t
, conn
.PrintfLine("MAIL FROM:<Smith@bar.com>"))
128 readCodeLine(t
, conn
, 250)
130 ok(t
, conn
.PrintfLine("RCPT TO:<Jones@foo.com>"))
131 readCodeLine(t
, conn
, 250)
133 ok(t
, conn
.PrintfLine("RCPT TO:<Green@foo.com>"))
134 readCodeLine(t
, conn
, 550)
136 ok(t
, conn
.PrintfLine("RCPT TO:<Brown@foo.com>"))
137 readCodeLine(t
, conn
, 250)
139 ok(t
, conn
.PrintfLine("DATA"))
140 readCodeLine(t
, conn
, 354)
142 ok(t
, conn
.PrintfLine("Blah blah blah..."))
143 ok(t
, conn
.PrintfLine("...etc. etc. etc."))
144 ok(t
, conn
.PrintfLine("."))
145 readCodeLine(t
, conn
, 250)
147 ok(t
, conn
.PrintfLine("QUIT"))
148 readCodeLine(t
, conn
, 221)
151 func TestVerifyAddress(t
*testing
.T
) {
153 blockList
: []string{"banned@test.mail"},
155 l
:= runServer(t
, &s
)
158 conn
:= createClient(t
, l
.Addr())
159 readCodeLine(t
, conn
, 220)
161 runTableTest(t
, conn
, []requestResponse
{
162 {"EHLO test", 0, func(t testing
.TB
, conn
*textproto
.Conn
) { conn
.ReadResponse(250) }},
163 {"VRFY banned@test.mail", 252, nil},
164 {"VRFY allowed@test.mail", 252, nil},
165 {"MAIL FROM:<sender@example.com>", 250, nil},
166 {"RCPT TO:<banned@test.mail>", 550, nil},
171 func TestBadAddress(t
*testing
.T
) {
172 l
:= runServer(t
, &testServer
{})
175 conn
:= createClient(t
, l
.Addr())
176 readCodeLine(t
, conn
, 220)
178 runTableTest(t
, conn
, []requestResponse
{
179 {"EHLO test", 0, func(t testing
.TB
, conn
*textproto
.Conn
) { conn
.ReadResponse(250) }},
180 {"MAIL FROM:<sender>", 501, nil},
181 {"MAIL FROM:<sender@foo.com> SIZE=2163", 250, nil},
182 {"RCPT TO:<banned.net>", 501, nil},
187 func TestCaseSensitivty(t
*testing
.T
) {
189 s
.blockList
= []string{"reject@mail.com"}
193 conn
:= createClient(t
, l
.Addr())
194 readCodeLine(t
, conn
, 220)
196 runTableTest(t
, conn
, []requestResponse
{
198 {"ehLO test.TEST", 0, func(t testing
.TB
, conn
*textproto
.Conn
) { conn
.ReadResponse(250) }},
199 {"mail FROM:<sender@example.com>", 250, nil},
200 {"RcPT tO:<receive@mail.com>", 250, nil},
201 {"RCPT TO:<reject@MAIL.com>", 550, nil},
202 {"RCPT TO:<reject@mail.com>", 550, nil},
203 {"DATa", 0, func(t testing
.TB
, conn
*textproto
.Conn
) {
204 readCodeLine(t
, conn
, 354)
206 ok(t
, conn
.PrintfLine("."))
207 readCodeLine(t
, conn
, 250)
209 {"MAIL FR:", 501, nil},
214 func TestGetReceivedInfo(t
*testing
.T
) {
216 server
: &testServer
{},
217 remoteAddr
: &net
.IPAddr
{net
.IPv4(127, 0, 0, 1), ""},
223 const line1
= "Received: from remote.test. (localhost [127.0.0.1])" + crlf
224 const line2
= "by Test-Server (mailpopbox) with "
225 const msgId
= "abcdef.hijk"
226 lineLast
:= now
.Format(time
.RFC1123Z
) + crlf
240 {params
{"remote.test.", true, false, "foo@bar.com"},
242 line2
+ "ESMTP id " + msgId
+ crlf
,
243 "for <foo@bar.com>" + crlf
,
244 "(using PLAINTEXT);" + crlf
,
248 for _
, test
:= range tests
{
249 t
.Logf("%#v", test
.params
)
251 conn
.ehlo
= test
.params
.ehlo
252 conn
.esmtp
= test
.params
.esmtp
253 //conn.tls = test.params.tls
255 envelope
:= Envelope
{
256 RcptTo
: []mail
.Address
{{"", test
.params
.address
}},
261 actual
:= conn
.getReceivedInfo(envelope
)
262 actualLines
:= strings
.SplitAfter(string(actual
), crlf
)
264 if len(actualLines
) != len(test
.expect
) {
265 t
.Errorf("wrong numbber of lines, expected %d, got %d", len(test
.expect
), len(actualLines
))
269 for i
, line
:= range actualLines
{
270 expect
:= test
.expect
[i
]
271 if expect
!= strings
.TrimLeft(line
, " ") {
272 t
.Errorf("Expected equal string %q, got %q", expect
, line
)