Complete the unittest by adding smtp.Server.VerifyAddress.
authorRobert Sesek <rsesek@bluestatic.org>
Tue, 13 Dec 2016 03:48:20 +0000 (22:48 -0500)
committerRobert Sesek <rsesek@bluestatic.org>
Tue, 13 Dec 2016 03:48:20 +0000 (22:48 -0500)
smtp.go
smtp/conn.go
smtp/conn_test.go
smtp/server.go

diff --git a/smtp.go b/smtp.go
index 156ace163331740782da6a6458839737cd4e6d8a..fd071fd551b6df4d3c4cb65c80a57f96b95f7d96 100644 (file)
--- a/smtp.go
+++ b/smtp.go
@@ -4,6 +4,7 @@ import (
        "crypto/tls"
        "fmt"
        "net"
+       "net/mail"
 
        "src.bluestatic.org/mailpopbox/smtp"
 )
@@ -48,6 +49,10 @@ func (server *smtpServer) TLSConfig() *tls.Config {
        return nil
 }
 
+func (server *smtpServer) VerifyAddress(addr mail.Address) smtp.ReplyLine {
+       return smtp.ReplyOK
+}
+
 func (server *smtpServer) OnEHLO() *smtp.ReplyLine {
        return nil
 }
index ac075951cdee04298ba8ca6537f610bb63361d1e..a2569984391a390f6c26c7b503e68f74d8afbf15 100644 (file)
@@ -165,6 +165,11 @@ func (conn *connection) doRCPT() {
                conn.reply(ReplyBadSyntax)
        }
 
+       if reply := conn.server.VerifyAddress(*address); reply != ReplyOK {
+               conn.reply(reply)
+               return
+       }
+
        conn.rcptTo = append(conn.rcptTo, *address)
 
        conn.state = stateRecipient
index d0998cda5dce7779aca3dc933721709ac7c70225..3456a39fdcdb2e44c74ccc4761c0cd131a93853c 100644 (file)
@@ -1,7 +1,9 @@
 package smtp
 
 import (
+       "fmt"
        "net"
+       "net/mail"
        "net/textproto"
        "path/filepath"
        "runtime"
@@ -9,16 +11,22 @@ import (
        "testing"
 )
 
+func _fl(depth int) string {
+       _, file, line, _ := runtime.Caller(depth + 1)
+       return fmt.Sprintf("[%s:%d]", filepath.Base(file), line)
+}
+
 func ok(t testing.TB, err error) {
        if err != nil {
-               _, file, line, _ := runtime.Caller(1)
-               t.Errorf("[%s:%d] unexpected error: %v", filepath.Base(file), line, err)
+               t.Errorf("%s unexpected error: %v", _fl(1), err)
        }
 }
 
 func readCodeLine(t testing.TB, conn *textproto.Conn, code int) string {
        _, message, err := conn.ReadCodeLine(code)
-       ok(t, err)
+       if err != nil {
+               t.Errorf("%s ReadCodeLine error: %v", _fl(1), err)
+       }
        return message
 }
 
@@ -46,12 +54,22 @@ func runServer(t *testing.T, server Server) net.Listener {
 
 type testServer struct {
        EmptyServerCallbacks
+       blockList []string
 }
 
 func (s *testServer) Name() string {
        return "Test-Server"
 }
 
+func (s *testServer) VerifyAddress(addr mail.Address) ReplyLine {
+       for _, block := range s.blockList {
+               if block == addr.Address {
+                       return ReplyBadMailbox
+               }
+       }
+       return ReplyOK
+}
+
 func createClient(t *testing.T, addr net.Addr) *textproto.Conn {
        conn, err := textproto.Dial(addr.Network(), addr.String())
        if err != nil {
@@ -63,7 +81,9 @@ func createClient(t *testing.T, addr net.Addr) *textproto.Conn {
 
 // RFC 5321 ยง D.1
 func TestScenarioTypical(t *testing.T) {
-       s := testServer{}
+       s := testServer{
+               blockList: []string{"Green@foo.com"},
+       }
        l := runServer(t, &s)
        defer l.Close()
 
@@ -90,7 +110,7 @@ func TestScenarioTypical(t *testing.T) {
        readCodeLine(t, conn, 250)
 
        ok(t, conn.PrintfLine("RCPT TO:<Green@foo.com>"))
-       readCodeLine(t, conn, 250) // TODO: make this 55o by rejecting Green
+       readCodeLine(t, conn, 550)
 
        ok(t, conn.PrintfLine("RCPT TO:<Brown@foo.com>"))
        readCodeLine(t, conn, 250)
index 3ecb24aff6cb3accc8e0b86c5db9fa9231997505..e992cda6a4710978997707da8f1461b09f840a62 100644 (file)
@@ -15,6 +15,7 @@ var (
        ReplyOK          = ReplyLine{250, "OK"}
        ReplyBadSyntax   = ReplyLine{501, "syntax error"}
        ReplyBadSequence = ReplyLine{503, "bad sequence of commands"}
+       ReplyBadMailbox  = ReplyLine{550, "mailbox unavailable"}
 )
 
 type Envelope struct {
@@ -29,6 +30,7 @@ type Server interface {
        Name() string
        TLSConfig() *tls.Config
        OnEHLO() *ReplyLine
+       VerifyAddress(mail.Address) ReplyLine
        OnMessageDelivered(Envelope) *ReplyLine
 }
 
@@ -42,6 +44,10 @@ func (*EmptyServerCallbacks) OnEHLO() *ReplyLine {
        return nil
 }
 
+func (*EmptyServerCallbacks) VerifyAddress(mail.Address) ReplyLine {
+       return ReplyOK
+}
+
 func (*EmptyServerCallbacks) OnMessageDelivered(Envelope) *ReplyLine {
        return nil
 }