diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2a579e9 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +DEPS = $(go list -f '{{range .TestImports}}{{.}} {{end}}' ./...) + +all: deps + go-bindata assets/... + go install + +test: test-deps + go list ./... | xargs -n1 go test + +release: release-deps + gox + +deps: + go get github.com/jteeuwen/go-bindata/... + go get labix.org/v2/mgo + +test-deps: + go get github.com/stretchr/testify + +release-deps: + go get github.com/mitchellh/gox + +.PNONY: all test deps diff --git a/README.md b/README.md index a0342b2..a70d0a2 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,9 @@ go get https://github.com/jteeuwen/go-bindata/... go-bindata assets/... ``` -Run tests using ```go test```. You'll need a copy of MailHog running for tests to pass. +If you build using ```make install```, necessary dependencies will be installed for you. + +Run tests using ```make test```. You'll need a copy of MailHog running for tests to pass. (Tests currently fail using in-memory storage, use MongoDB!) If you make any changes, run ```go fmt``` before submitting a pull request. diff --git a/mailhog/smtp/session.go b/mailhog/smtp/session.go index 1747e0e..4b2175b 100644 --- a/mailhog/smtp/session.go +++ b/mailhog/smtp/session.go @@ -7,6 +7,7 @@ import ( "net" "strings" "regexp" + "errors" "github.com/ian-kent/MailHog/mailhog/config" "github.com/ian-kent/MailHog/mailhog/storage" "github.com/ian-kent/MailHog/mailhog/data" @@ -202,11 +203,14 @@ func (c *Session) Process(line string) { } case "MAIL": c.log("Got MAIL command, switching to RCPT state") - r, _ := regexp.Compile("(?i:From):<([^>]+)>") - match := r.FindStringSubmatch(args) - c.message.From = match[1] + from, err := ParseMAIL(args) + if err != nil { + c.Write("550", err.Error()) + return + } + c.message.From = from c.state = RCPT - c.Write("250", "Sender " + match[1] + " ok") + c.Write("250", "Sender " + from + " ok") default: c.log("Got unknown command for MAIL state: '%s'", command) c.Write("500", "Unrecognised command") @@ -215,11 +219,14 @@ func (c *Session) Process(line string) { switch command { case "RCPT": c.log("Got RCPT command") - r, _ := regexp.Compile("(?i:To):<([^>]+)>") - match := r.FindStringSubmatch(args) - c.message.To = append(c.message.To, match[1]) + to, err := ParseRCPT(args) + if err != nil { + c.Write("550", err.Error()) + return + } + c.message.To = append(c.message.To, to) c.state = RCPT - c.Write("250", "Recipient " + match[1] + " ok") + c.Write("250", "Recipient " + to + " ok") case "DATA": c.log("Got DATA command, switching to DATA state") c.state = DATA @@ -230,3 +237,21 @@ func (c *Session) Process(line string) { } } } + +func ParseMAIL(mail string) (string, error) { + r := regexp.MustCompile("(?i:From):<([^>]+)>") + match := r.FindStringSubmatch(mail) + if(len(match) != 2) { + return "", errors.New("Invalid sender") + } + return match[1], nil; +} + +func ParseRCPT(rcpt string) (string, error) { + r := regexp.MustCompile("(?i:To):<([^>]+)>") + match := r.FindStringSubmatch(rcpt) + if(len(match) != 2) { + return "", errors.New("Invalid recipient") + } + return match[1], nil; +} diff --git a/mailhog/smtp/session_test.go b/mailhog/smtp/session_test.go new file mode 100644 index 0000000..48da6c1 --- /dev/null +++ b/mailhog/smtp/session_test.go @@ -0,0 +1,114 @@ +package smtp + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestMAILParsing(t *testing.T) { + from, err := ParseMAIL("From:") + assert.Equal(t, from, "foo@bar") + assert.Nil(t, err) + + from, err = ParseMAIL("From:") + assert.Equal(t, from, "foo@bar.com") + assert.Nil(t, err) + + from, err = ParseMAIL("From:") + assert.Equal(t, from, "foo") + assert.Nil(t, err) + + from, err = ParseMAIL("To:") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("To:") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("To:") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("INVALID") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("From:INVALID") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("From:foo") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("From:foo@bar") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") + + from, err = ParseMAIL("From: ") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid sender") +} + +func TestRCPTParsing(t *testing.T) { + from, err := ParseRCPT("To:") + assert.Equal(t, from, "foo@bar") + assert.Nil(t, err) + + from, err = ParseRCPT("To:") + assert.Equal(t, from, "foo@bar.com") + assert.Nil(t, err) + + from, err = ParseRCPT("To:") + assert.Equal(t, from, "foo") + assert.Nil(t, err) + + from, err = ParseRCPT("From:") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("From:") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("From:") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("INVALID") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("To:INVALID") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("To:foo") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("To:foo@bar") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") + + from, err = ParseRCPT("To: ") + assert.Equal(t, from, "") + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "Invalid recipient") +}