diff --git a/imapserver/server_test.go b/imapserver/server_test.go index 1dacdce..b9b264f 100644 --- a/imapserver/server_test.go +++ b/imapserver/server_test.go @@ -387,8 +387,12 @@ func TestLogin(t *testing.T) { tc.close() tc = start(t) - defer tc.close() tc.transactf("ok", `login "mjl@mox.example" "testtest"`) + tc.close() + + tc = start(t) + tc.transactf("ok", `login "\"\"@mox.example" "testtest"`) + defer tc.close() tc.transactf("bad", "logout badarg") tc.transactf("ok", "logout") diff --git a/smtpserver/parse.go b/smtpserver/parse.go index d9ba1f2..d4cfdc3 100644 --- a/smtpserver/parse.go +++ b/smtpserver/parse.go @@ -336,6 +336,7 @@ func (p *parser) xlocalpart() smtp.Localpart { // ../rfc/5321:2324 func (p *parser) xquotedString(islocalpart bool) string { + p.xtake(`"`) var s string var esc bool for { diff --git a/smtpserver/server_test.go b/smtpserver/server_test.go index d0e41ae..aa6d522 100644 --- a/smtpserver/server_test.go +++ b/smtpserver/server_test.go @@ -1133,3 +1133,34 @@ func TestPostmaster(t *testing.T) { testDeliver("postmaster@mox.example", nil) // Postmaster address without explicitly configured destination. testDeliver("postmaster@unknown.example", &smtpclient.Error{Code: smtp.C550MailboxUnavail, Secode: smtp.SeAddr1UnknownDestMailbox1}) } + +// Test to address with empty localpart. +func TestEmptylocalpart(t *testing.T) { + resolver := dns.MockResolver{ + A: map[string][]string{ + "other.example.": {"127.0.0.10"}, // For mx check. + }, + PTR: map[string][]string{ + "127.0.0.10": {"other.example."}, + }, + } + ts := newTestServer(t, "../testdata/smtp/mox.conf", resolver) + defer ts.close() + + testDeliver := func(rcptTo string, expErr *smtpclient.Error) { + t.Helper() + ts.run(func(err error, client *smtpclient.Client) { + t.Helper() + mailFrom := `""@other.example` + if err == nil { + err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false) + } + var cerr smtpclient.Error + if expErr == nil && err != nil || expErr != nil && (err == nil || !errors.As(err, &cerr) || cerr.Code != expErr.Code || cerr.Secode != expErr.Secode) { + t.Fatalf("got err %#v, expected %#v", err, expErr) + } + }) + } + + testDeliver(`""@mox.example`, nil) +} diff --git a/testdata/imap/domains.conf b/testdata/imap/domains.conf index 3ba0f08..5ece6a6 100644 --- a/testdata/imap/domains.conf +++ b/testdata/imap/domains.conf @@ -6,6 +6,7 @@ Accounts: Domain: mox.example Destinations: mjl@mox.example: nil + ""@mox.example: nil JunkFilter: Threshold: 0.95 Params: diff --git a/testdata/smtp/domains.conf b/testdata/smtp/domains.conf index e74182d..d9a4170 100644 --- a/testdata/smtp/domains.conf +++ b/testdata/smtp/domains.conf @@ -7,6 +7,7 @@ Accounts: Destinations: mjl@mox.example: nil mjl@mox2.example: nil + ""@mox.example: nil JunkFilter: Threshold: 0.9 Params: