1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 10:07:02 +00:00

Add many more SMTP handler tests

This commit is contained in:
James Hillyerd
2013-10-29 17:01:54 -07:00
parent 38c124875e
commit e5b6ed2230

View File

@@ -1,6 +1,7 @@
package smtpd package smtpd
import ( import (
"fmt"
"github.com/jhillyerd/inbucket/config" "github.com/jhillyerd/inbucket/config"
"io/ioutil" "io/ioutil"
"net" "net"
@@ -15,68 +16,201 @@ type scriptStep struct {
expect int expect int
} }
func TestHelo(t *testing.T) { // Test commands in GREET state
func TestGreetState(t *testing.T) {
server := setupSmtpServer() server := setupSmtpServer()
defer teardownSmtpServer(server) defer teardownSmtpServer(server)
var script []scriptStep
// Test out some manged HELOs // Test out some mangled HELOs
playSession(t, server, []scriptStep{ script = []scriptStep{
{"HELLO", 500}, {"HELLO", 500},
})
playSession(t, server, []scriptStep{
{"HELL", 500}, {"HELL", 500},
})
playSession(t, server, []scriptStep{
{"hello", 500}, {"hello", 500},
}) {"Outlook", 500},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Valid HELOs // Valid HELOs
playSession(t, server, []scriptStep{ if err := playSession(t, server, []scriptStep{{"HELO", 250}}); err != nil {
{"HELO", 250}, t.Error(err)
}) }
playSession(t, server, []scriptStep{ if err := playSession(t, server, []scriptStep{{"HELO mydomain", 250}}); err != nil {
{"HELO mydomain", 250}, t.Error(err)
}) }
playSession(t, server, []scriptStep{ if err := playSession(t, server, []scriptStep{{"HELO mydom.com", 250}}); err != nil {
{"HELO mydom.com", 250}, t.Error(err)
}) }
playSession(t, server, []scriptStep{ if err := playSession(t, server, []scriptStep{{"HelO mydom.com", 250}}); err != nil {
{"HelO mydom.com", 250}, t.Error(err)
}) }
}
// Test commands in READY state
func TestReadyState(t *testing.T) {
server := setupSmtpServer()
defer teardownSmtpServer(server)
var script []scriptStep
// Test out some mangled READY commands
script = []scriptStep{
{"HELO localhost", 250},
{"FOOB", 500},
{"HELO", 503},
{"DATA", 503},
{"MAIL", 501},
{"MAIL FROM john@gmail.com", 501},
{"MAIL FROM:john@gmail.com", 501},
{"MAIL FROM:<john@gmail.com> SIZE=147KB", 501},
{"MAIL FROM: <john@gmail.com> SIZE147", 501},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Test out some valid MAIL commands
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"RSET", 250},
{"MAIL FROM: <john@gmail.com>", 250},
{"RSET", 250},
{"MAIL FROM: <john@gmail.com> BODY=8BITMIME", 250},
{"RSET", 250},
{"MAIL FROM:<john@gmail.com> SIZE=1024", 250},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
}
// Test commands in MAIL state
func TestMailState(t *testing.T) {
server := setupSmtpServer()
defer teardownSmtpServer(server)
var script []scriptStep
// Test out some mangled READY commands
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"FOOB", 500},
{"HELO", 503},
{"DATA", 503},
{"MAIL", 503},
{"RCPT", 501},
{"RCPT TO", 501},
{"RCPT TO james@gmail.com", 501},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Test out some good RCPT commands
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"RCPT TO:<u1@gmail.com>", 250},
{"RCPT TO: <u2@gmail.com>", 250},
{"RCPT TO:u3@gmail.com", 250},
{"RCPT TO: u4@gmail.com", 250},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Test out recipient limit
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"RCPT TO:<u1@gmail.com>", 250},
{"RCPT TO:<u2@gmail.com>", 250},
{"RCPT TO:<u3@gmail.com>", 250},
{"RCPT TO:<u4@gmail.com>", 250},
{"RCPT TO:<u5@gmail.com>", 250},
{"RCPT TO:<u6@gmail.com>", 552},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Test DATA
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"RCPT TO:<u1@gmail.com>", 250},
{"DATA", 354},
{".", 250},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Test RSET
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"RCPT TO:<u1@gmail.com>", 250},
{"RSET", 250},
{"MAIL FROM:<john@gmail.com>", 250},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
// Test QUIT
script = []scriptStep{
{"HELO localhost", 250},
{"MAIL FROM:<john@gmail.com>", 250},
{"RCPT TO:<u1@gmail.com>", 250},
{"QUIT", 221},
}
if err := playSession(t, server, script); err != nil {
t.Error(err)
}
} }
// playSession creates a new session, reads the greeting and then plays the script // playSession creates a new session, reads the greeting and then plays the script
func playSession(t *testing.T, server *Server, script []scriptStep) { func playSession(t *testing.T, server *Server, script []scriptStep) error {
pipe := setupSmtpSession(server) pipe := setupSmtpSession(server)
c := textproto.NewConn(pipe) c := textproto.NewConn(pipe)
if code, _, err := c.ReadCodeLine(220); err != nil { if code, _, err := c.ReadCodeLine(220); err != nil {
t.Fatalf("Expected a 220 greeting, got %v", code) return fmt.Errorf("Expected a 220 greeting, got %v", code)
return
} }
playScriptAgainst(t, c, script) err := playScriptAgainst(t, c, script)
c.Cmd("QUIT") c.Cmd("QUIT")
c.ReadCodeLine(221) c.ReadCodeLine(221)
return err
} }
// playScriptAgainst an existing connection, does not handle server greeting // playScriptAgainst an existing connection, does not handle server greeting
func playScriptAgainst(t *testing.T, c *textproto.Conn, script []scriptStep) { func playScriptAgainst(t *testing.T, c *textproto.Conn, script []scriptStep) error {
for i, step := range script { for i, step := range script {
id, err := c.Cmd(step.send) id, err := c.Cmd(step.send)
if err != nil { if err != nil {
t.Fatalf("Step %d, failed to send %q: %v", i, step.send, err) return fmt.Errorf("Step %d, failed to send %q: %v", i, step.send, err)
return
} }
c.StartResponse(id) c.StartResponse(id)
if code, msg, err := c.ReadCodeLine(step.expect); err != nil { code, msg, err := c.ReadCodeLine(step.expect)
t.Errorf("Step %d, sent %q, expected %v, got %v: %q", if err != nil {
err = fmt.Errorf("Step %d, sent %q, expected %v, got %v: %q",
i, step.send, step.expect, code, msg) i, step.send, step.expect, code, msg)
} }
defer c.EndResponse(id) c.EndResponse(id)
if err != nil {
// Return after c.EndResponse so we don't hang the connection
return err
}
} }
return nil
} }
// net.Pipe does not implement deadlines // net.Pipe does not implement deadlines