author | Alberto Bertogli
<albertito@blitiri.com.ar> 2016-10-08 09:29:04 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2016-10-09 23:51:05 UTC |
parent | 3e6dd12d06f51e1c894009ef48c97c00fe31f64e |
chasquid.go | +15 | -8 |
chasquid_test.go | +17 | -4 |
diff --git a/chasquid.go b/chasquid.go index a7c80c1..c0816ff 100644 --- a/chasquid.go +++ b/chasquid.go @@ -595,8 +595,8 @@ func (c *Conn) NOOP(params string) (code int, msg string) { func (c *Conn) MAIL(params string) (code int, msg string) { // params should be: "FROM:<name@host>", and possibly followed by - // "BODY=8BITMIME" (which we ignore). - // Check that it begins with "FROM:" first, otherwise it's pointless. + // options such as "BODY=8BITMIME" (which we ignore). + // Check that it begins with "FROM:" first, it's mandatory. if !strings.HasPrefix(strings.ToLower(params), "from:") { return 500, "unknown command" } @@ -655,23 +655,30 @@ func (c *Conn) MAIL(params string) (code int, msg string) { } func (c *Conn) RCPT(params string) (code int, msg string) { - // params should be: "TO:<name@host>" - // First, get rid of the "TO:" part (but check it, it's mandatory). - sp := strings.SplitN(strings.ToLower(params), ":", 2) - if len(sp) != 2 || sp[0] != "to" { + // params should be: "TO:<name@host>", and possibly followed by options + // such as "NOTIFY=SUCCESS,DELAY" (which we ignore). + // Check that it begins with "TO:" first, it's mandatory. + if !strings.HasPrefix(strings.ToLower(params), "to:") { return 500, "unknown command" } + rawAddr := "" + _, err := fmt.Sscanf(params[3:], "%s ", &rawAddr) + if err != nil { + return 500, "malformed command - " + err.Error() + } + // RFC says 100 is the minimum limit for this, but it seems excessive. + // https://tools.ietf.org/html/rfc5321#section-4.5.3.1.8 if len(c.rcptTo) > 100 { - return 503, "too many recipients" + return 452, "too many recipients" } // TODO: Write our own parser (we have different needs, mail.ParseAddress // is useful for other things). // Allow utf8, but prevent "control" characters. - e, err := mail.ParseAddress(sp[1]) + e, err := mail.ParseAddress(rawAddr) if err != nil || e.Address == "" { return 501, "malformed address" } diff --git a/chasquid_test.go b/chasquid_test.go index 638f92c..d44344d 100644 --- a/chasquid_test.go +++ b/chasquid_test.go @@ -184,11 +184,9 @@ func TestNullMailFrom(t *testing.T) { c := mustDial(t, ModeSMTP, false) defer c.Close() - addrs := []string{"", "<>", " <>", " < > "} + addrs := []string{"<>", " <>", "<> OPTION"} for _, addr := range addrs { - if err := c.Text.PrintfLine(addr); err != nil { - t.Fatalf("MAIL FROM failed with addr %q: %v", addr, err) - } + simpleCmd(t, c, fmt.Sprintf("MAIL FROM:%s", addr), 250) } } @@ -201,6 +199,21 @@ func TestRcptBeforeMail(t *testing.T) { } } +func TestRcptOption(t *testing.T) { + c := mustDial(t, ModeSMTP, false) + defer c.Close() + + if err := c.Mail("from@localhost"); err != nil { + t.Errorf("Mail: %v", err) + } + + params := []string{ + "<to@localhost>", " <to@localhost>", "<to@localhost> OPTION"} + for _, p := range params { + simpleCmd(t, c, fmt.Sprintf("RCPT TO:%s", p), 250) + } +} + func TestRelayForbidden(t *testing.T) { c := mustDial(t, ModeSMTP, false) defer c.Close()