diff --git a/server/smtpd/lib.go b/server/smtpd/lib.go index 0574c50..49f1382 100644 --- a/server/smtpd/lib.go +++ b/server/smtpd/lib.go @@ -29,7 +29,9 @@ var ( Debug = false rcptToRE = regexp.MustCompile(`[Tt][Oo]:\s?<(.+)>`) mailFromRE = regexp.MustCompile(`[Ff][Rr][Oo][Mm]:\s?<(.*)>(\s(.*))?`) // Delivery Status Notifications are sent with "MAIL FROM:<>" - mailSizeRE = regexp.MustCompile(`[Ss][Ii][Zz][Ee]=(\d+)`) + + // extract mail size from 'MAIL FROM' parameter + mailFromSizeRE = regexp.MustCompile(`(?U)(^| |,)[Ss][Ii][Zz][Ee]=(.*)($|,| )`) ) // Handler function called upon successful receipt of an email. @@ -411,12 +413,13 @@ loop: } else { // Validate the SIZE parameter if one was sent. if len(match[2]) > 0 { // A parameter is present - sizeMatch := mailSizeRE.FindStringSubmatch(match[3]) + sizeMatch := mailFromSizeRE.FindStringSubmatch(match[3]) if sizeMatch == nil { - s.writef("501 5.5.4 Syntax error in parameters or arguments (invalid SIZE parameter)") + // ignore other parameter + s.writef("250 2.1.0 Ok") } else { // Enforce the maximum message size if one is set. - size, err := strconv.Atoi(sizeMatch[1]) + size, err := strconv.Atoi(sizeMatch[2]) if err != nil { // Bad SIZE parameter s.writef("501 5.5.4 Syntax error in parameters or arguments (invalid SIZE parameter)") } else if s.srv.MaxSize > 0 && size > s.srv.MaxSize { // SIZE above maximum size, if set diff --git a/server/smtpd/smtpd_test.go b/server/smtpd/smtpd_test.go index af590d6..6f8cf61 100644 --- a/server/smtpd/smtpd_test.go +++ b/server/smtpd/smtpd_test.go @@ -148,11 +148,15 @@ func TestCmdMAIL(t *testing.T) { cmdCode(t, conn, "MAIL FROM: SIZE=1000", "250") // MAIL with bad size parameter should return 501 syntax error - cmdCode(t, conn, "MAIL FROM: SIZE", "501") cmdCode(t, conn, "MAIL FROM: SIZE=", "501") cmdCode(t, conn, "MAIL FROM: SIZE= ", "501") cmdCode(t, conn, "MAIL FROM: SIZE=foo", "501") + // MAIL with options should be ignored except for SIZE + cmdCode(t, conn, "MAIL FROM: BODY=8BITMIME", "250") // ignored + cmdCode(t, conn, "MAIL FROM: BODY=8BITMIME,SIZE=1000", "250") // size detected + cmdCode(t, conn, "MAIL FROM: BODY=8BITMIME,SIZE=foo", "501") // ignored + // TODO: MAIL with valid AUTH parameter should return 250 Ok // TODO: MAIL with invalid AUTH parameter must return 501 syntax error @@ -170,7 +174,6 @@ func TestCmdMAILMaxSize(t *testing.T) { cmdCode(t, conn, "MAIL FROM:", "250") // MAIL with bad size parameter should return 501 syntax error - cmdCode(t, conn, "MAIL FROM: SIZE", "501") cmdCode(t, conn, "MAIL FROM: SIZE=", "501") cmdCode(t, conn, "MAIL FROM: SIZE= ", "501") cmdCode(t, conn, "MAIL FROM: SIZE=foo", "501")