update to latest bstore (with support for an index on a []string: Message.DKIMDomains), and cyclic data types (to be used for Message.Part soon); also adds a context.Context to database operations.

This commit is contained in:
Mechiel Lukkien
2023-05-22 14:40:36 +02:00
parent f6ed860ccb
commit e81930ba20
58 changed files with 1970 additions and 1035 deletions

View File

@ -161,7 +161,7 @@ func analyze(ctx context.Context, log *mlog.Log, resolver dns.Resolver, d delive
var reason string
var err error
d.acc.WithRLock(func() {
err = d.acc.DB.Read(func(tx *bstore.Tx) error {
err = d.acc.DB.Read(ctx, func(tx *bstore.Tx) error {
// Set message MailboxID to which mail will be delivered. Reputation is
// per-mailbox. If referenced mailbox is not found (e.g. does not yet exist), we
// can still determine a reputation because we also base it on outgoing
@ -251,13 +251,13 @@ func analyze(ctx context.Context, log *mlog.Log, resolver dns.Resolver, d delive
reason = reasonNoBadSignals
accept := true
var junkSubjectpass bool
f, jf, err := d.acc.OpenJunkFilter(log)
f, jf, err := d.acc.OpenJunkFilter(ctx, log)
if err == nil {
defer func() {
err := f.Close()
log.Check(err, "closing junkfilter")
}()
contentProb, _, _, _, err := f.ClassifyMessageReader(store.FileMsgReader(d.m.MsgPrefix, d.dataFile), d.m.Size)
contentProb, _, _, _, err := f.ClassifyMessageReader(ctx, store.FileMsgReader(d.m.MsgPrefix, d.dataFile), d.m.Size)
if err != nil {
log.Errorx("testing for spam", err)
return reject(smtp.C451LocalErr, smtp.SeSys3Other0, "error processing", err, reasonJunkClassifyError)

View File

@ -1,6 +1,7 @@
package smtpserver
import (
"context"
"fmt"
"os"
@ -11,7 +12,7 @@ import (
)
// compose dsn message and add it to the queue for delivery to rcptTo.
func queueDSN(c *conn, rcptTo smtp.Path, m dsn.Message) error {
func queueDSN(ctx context.Context, c *conn, rcptTo smtp.Path, m dsn.Message) error {
buf, err := m.Compose(c.log, false)
if err != nil {
return err
@ -45,7 +46,7 @@ func queueDSN(c *conn, rcptTo smtp.Path, m dsn.Message) error {
// ../rfc/3464:433
const has8bit = false
const smtputf8 = false
if err := queue.Add(c.log, "", smtp.Path{}, rcptTo, has8bit, smtputf8, int64(len(buf)), nil, f, bufUTF8, true); err != nil {
if err := queue.Add(ctx, c.log, "", smtp.Path{}, rcptTo, has8bit, smtputf8, int64(len(buf)), nil, f, bufUTF8, true); err != nil {
return err
}
err = f.Close()

View File

@ -1,7 +1,6 @@
package smtpserver
import (
"context"
"fmt"
"net"
"os"
@ -30,7 +29,7 @@ func FuzzServer(f *testing.F) {
f.Add("NOOP")
f.Add("QUIT")
mox.Context = context.Background()
mox.Context = ctxbg
mox.ConfigStaticPath = "../testdata/smtp/mox.conf"
mox.MustLoadConfig(false)
dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir)

View File

@ -2,6 +2,7 @@ package smtpserver
import (
"bytes"
"context"
"crypto/sha256"
"fmt"
"io"
@ -40,7 +41,7 @@ func rejectPresent(log *mlog.Log, acc *store.Account, rejectsMailbox string, m *
var exists bool
var err error
acc.WithRLock(func() {
err = acc.DB.Read(func(tx *bstore.Tx) error {
err = acc.DB.Read(context.TODO(), func(tx *bstore.Tx) error {
mbq := bstore.QueryTx[store.Mailbox](tx)
mbq.FilterNonzero(store.Mailbox{Name: rejectsMailbox})
mb, err := mbq.Get()

View File

@ -272,16 +272,8 @@ func reputation(tx *bstore.Tx, log *mlog.Log, m *store.Message) (rjunk *bool, rc
dkimspfsignals := []float64{}
dkimspfmsgs := 0
for _, dom := range m.DKIMDomains {
// todo: should get dkimdomains in an index for faster lookup. bstore does not yet support "in" indexes.
q := messageQuery(nil, year/2, 50)
q.FilterFn(func(m store.Message) bool {
for _, d := range m.DKIMDomains {
if d == dom {
return true
}
}
return false
})
q.FilterIn("DKIMDomains", dom)
msgs := xmessageList(q, "dkimdomain")
if len(msgs) > 0 {
nspam := 0

View File

@ -1,7 +1,6 @@
package smtpserver
import (
"context"
"fmt"
"net"
"os"
@ -77,7 +76,7 @@ func TestReputation(t *testing.T) {
MsgFromLocalpart: msgFrom.Localpart,
MsgFromDomain: msgFrom.Domain.Name(),
MsgFromOrgDomain: publicsuffix.Lookup(context.Background(), msgFrom.Domain).Name(),
MsgFromOrgDomain: publicsuffix.Lookup(ctxbg, msgFrom.Domain).Name(),
MailFromValidated: mailfromValid,
EHLOValidated: ehloValid,
@ -103,11 +102,11 @@ func TestReputation(t *testing.T) {
p := "../testdata/smtpserver-reputation.db"
defer os.Remove(p)
db, err := bstore.Open(p, &bstore.Options{Timeout: 5 * time.Second}, store.Message{}, store.Recipient{}, store.Mailbox{})
db, err := bstore.Open(ctxbg, p, &bstore.Options{Timeout: 5 * time.Second}, store.Message{}, store.Recipient{}, store.Mailbox{})
tcheck(t, err, "open db")
defer db.Close()
err = db.Write(func(tx *bstore.Tx) error {
err = db.Write(ctxbg, func(tx *bstore.Tx) error {
err = tx.Insert(&store.Mailbox{ID: 1, Name: "Inbox"})
tcheck(t, err, "insert into db")
@ -117,7 +116,7 @@ func TestReputation(t *testing.T) {
rcptToDomain, err := dns.ParseDomain(hm.RcptToDomain)
tcheck(t, err, "parse rcptToDomain")
rcptToOrgDomain := publicsuffix.Lookup(context.Background(), rcptToDomain)
rcptToOrgDomain := publicsuffix.Lookup(ctxbg, rcptToDomain)
r := store.Recipient{MessageID: hm.ID, Localpart: hm.RcptToLocalpart, Domain: hm.RcptToDomain, OrgDomain: rcptToOrgDomain.Name(), Sent: hm.Received}
err = tx.Insert(&r)
tcheck(t, err, "insert recipient")
@ -130,7 +129,7 @@ func TestReputation(t *testing.T) {
var isjunk *bool
var conclusive bool
var method reputationMethod
err = db.Read(func(tx *bstore.Tx) error {
err = db.Read(ctxbg, func(tx *bstore.Tx) error {
var err error
isjunk, conclusive, method, err = reputation(tx, xlog, &m)
return err

View File

@ -1028,7 +1028,7 @@ func (c *conn) cmdAuth(p *parser) {
}()
var ipadhash, opadhash hash.Hash
acc.WithRLock(func() {
err := acc.DB.Read(func(tx *bstore.Tx) error {
err := acc.DB.Read(context.TODO(), func(tx *bstore.Tx) error {
password, err := bstore.QueryTx[store.Password](tx).Get()
if err == bstore.ErrAbsent {
xsmtpUserErrorf(smtp.C535AuthBadCreds, smtp.SePol7AuthBadCreds8, "bad user/pass")
@ -1101,7 +1101,7 @@ func (c *conn) cmdAuth(p *parser) {
}
var xscram store.SCRAM
acc.WithRLock(func() {
err := acc.DB.Read(func(tx *bstore.Tx) error {
err := acc.DB.Read(context.TODO(), func(tx *bstore.Tx) error {
password, err := bstore.QueryTx[store.Password](tx).Get()
if authVariant == "scram-sha-1" {
xscram = password.SCRAMSHA1
@ -1672,7 +1672,7 @@ func (c *conn) submit(ctx context.Context, recvHdrFor func(string) string, msgWr
// Limit damage to the internet and our reputation in case of account compromise by
// limiting the max number of messages sent in a 24 hour window, both total number
// of messages and number of first-time recipients.
err = c.account.DB.Read(func(tx *bstore.Tx) error {
err = c.account.DB.Read(ctx, func(tx *bstore.Tx) error {
conf, _ := c.account.Conf()
msgmax := conf.MaxOutgoingMessagesPerDay
if msgmax == 0 {
@ -1828,7 +1828,7 @@ func (c *conn) submit(ctx context.Context, recvHdrFor func(string) string, msgWr
metricSubmission.WithLabelValues("ok").Inc()
c.log.Info("submitted message delivered", mlog.Field("mailfrom", *c.mailFrom), mlog.Field("rcptto", rcptAcc.rcptTo), mlog.Field("smtputf8", c.smtputf8), mlog.Field("msgsize", msgSize))
err := c.account.DB.Insert(&store.Outgoing{Recipient: rcptAcc.rcptTo.XString(true)})
err := c.account.DB.Insert(ctx, &store.Outgoing{Recipient: rcptAcc.rcptTo.XString(true)})
xcheckf(err, "adding outgoing message")
}
})
@ -1852,7 +1852,7 @@ func (c *conn) submit(ctx context.Context, recvHdrFor func(string) string, msgWr
}
msgSize := int64(len(xmsgPrefix)) + msgWriter.Size
if err := queue.Add(c.log, c.account.Name, *c.mailFrom, rcptAcc.rcptTo, msgWriter.Has8bit, c.smtputf8, msgSize, xmsgPrefix, dataFile, nil, i == len(c.recipients)-1); err != nil {
if err := queue.Add(ctx, c.log, c.account.Name, *c.mailFrom, rcptAcc.rcptTo, msgWriter.Has8bit, c.smtputf8, msgSize, xmsgPrefix, dataFile, nil, i == len(c.recipients)-1); err != nil {
// Aborting the transaction is not great. But continuing and generating DSNs will
// probably result in errors as well...
metricSubmission.WithLabelValues("queueerror").Inc()
@ -1862,7 +1862,7 @@ func (c *conn) submit(ctx context.Context, recvHdrFor func(string) string, msgWr
metricSubmission.WithLabelValues("ok").Inc()
c.log.Info("message queued for delivery", mlog.Field("mailfrom", *c.mailFrom), mlog.Field("rcptto", rcptAcc.rcptTo), mlog.Field("smtputf8", c.smtputf8), mlog.Field("msgsize", msgSize))
err := c.account.DB.Insert(&store.Outgoing{Recipient: rcptAcc.rcptTo.XString(true)})
err := c.account.DB.Insert(ctx, &store.Outgoing{Recipient: rcptAcc.rcptTo.XString(true)})
xcheckf(err, "adding outgoing message")
}
}
@ -2267,7 +2267,7 @@ func (c *conn) deliver(ctx context.Context, recvHdrFor func(string) string, msgW
// account. They may fill up the mailbox, either with messages that have to be
// purged, or by filling the disk. We check both cases for IP's and networks.
var rateError bool // Whether returned error represents a rate error.
err = acc.DB.Read(func(tx *bstore.Tx) (retErr error) {
err = acc.DB.Read(ctx, func(tx *bstore.Tx) (retErr error) {
now := time.Now()
defer func() {
log.Debugx("checking message and size delivery rates", retErr, mlog.Field("duration", time.Since(now)))
@ -2575,7 +2575,7 @@ func (c *conn) deliver(ctx context.Context, recvHdrFor func(string) string, msgW
if Localserve {
c.log.Error("not queueing dsn for incoming delivery due to localserve")
} else if err := queueDSN(c, *c.mailFrom, dsnMsg); err != nil {
} else if err := queueDSN(context.TODO(), c, *c.mailFrom, dsnMsg); err != nil {
metricServerErrors.WithLabelValues("queuedsn").Inc()
c.log.Errorx("queuing DSN for incoming delivery, no DSN sent", err)
}

View File

@ -39,6 +39,8 @@ import (
"github.com/mjl-/mox/tlsrptdb"
)
var ctxbg = context.Background()
func init() {
// Don't make tests slow.
badClientDelay = 0
@ -88,7 +90,7 @@ func newTestServer(t *testing.T, configPath string, resolver dns.Resolver) *test
ts := testserver{t: t, cid: 1, resolver: resolver, tlsmode: smtpclient.TLSOpportunistic}
mox.Context = context.Background()
mox.Context = ctxbg
mox.ConfigStaticPath = configPath
mox.MustLoadConfig(false)
dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir)
@ -138,7 +140,7 @@ func (ts *testserver) run(fn func(helloErr error, client *smtpclient.Client)) {
authLine = fmt.Sprintf("AUTH PLAIN %s", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("\u0000%s\u0000%s", ts.user, ts.pass))))
}
client, err := smtpclient.New(context.Background(), xlog.WithCid(ts.cid-1), clientConn, ts.tlsmode, "mox.example", authLine)
client, err := smtpclient.New(ctxbg, xlog.WithCid(ts.cid-1), clientConn, ts.tlsmode, "mox.example", authLine)
if err != nil {
clientConn.Close()
} else {
@ -199,7 +201,7 @@ func TestSubmission(t *testing.T) {
mailFrom := "mjl@mox.example"
rcptTo := "remote@example.org"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(submitMessage)), strings.NewReader(submitMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(submitMessage)), strings.NewReader(submitMessage), false, false)
}
var cerr smtpclient.Error
if expErr == nil && err != nil || expErr != nil && (err == nil || !errors.As(err, &cerr) || cerr.Secode != expErr.Secode) {
@ -230,7 +232,7 @@ func TestDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@127.0.0.10"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C550MailboxUnavail {
@ -242,7 +244,7 @@ func TestDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@test.example" // Not configured as destination.
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C550MailboxUnavail {
@ -254,7 +256,7 @@ func TestDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "unknown@mox.example" // User unknown.
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C550MailboxUnavail {
@ -266,7 +268,7 @@ func TestDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C451LocalErr {
@ -280,7 +282,7 @@ func TestDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
tcheck(t, err, "deliver to remote")
@ -319,12 +321,12 @@ func tretrain(t *testing.T, acc *store.Account) {
bloomPath := filepath.Join(basePath, acc.Name, "junkfilter.bloom")
os.Remove(dbPath)
os.Remove(bloomPath)
jf, _, err := acc.OpenJunkFilter(xlog)
jf, _, err := acc.OpenJunkFilter(ctxbg, xlog)
tcheck(t, err, "open junk filter")
defer jf.Close()
// Fetch messags to retrain on.
q := bstore.QueryDB[store.Message](acc.DB)
q := bstore.QueryDB[store.Message](ctxbg, acc.DB)
q.FilterFn(func(m store.Message) bool {
return m.Flags.Junk || m.Flags.Notjunk
})
@ -339,7 +341,7 @@ func tretrain(t *testing.T, acc *store.Account) {
tcheck(t, err, "open message")
r := store.FileMsgReader(m.MsgPrefix, f)
jf.TrainMessage(r, m.Size, ham)
jf.TrainMessage(ctxbg, r, m.Size, ham)
err = r.Close()
tcheck(t, err, "close message")
@ -388,11 +390,11 @@ func TestSpam(t *testing.T) {
checkRejectsCount := func(expect int) {
t.Helper()
q := bstore.QueryDB[store.Mailbox](ts.acc.DB)
q := bstore.QueryDB[store.Mailbox](ctxbg, ts.acc.DB)
q.FilterNonzero(store.Mailbox{Name: "Rejects"})
mb, err := q.Get()
tcheck(t, err, "get rejects mailbox")
qm := bstore.QueryDB[store.Message](ts.acc.DB)
qm := bstore.QueryDB[store.Message](ctxbg, ts.acc.DB)
qm.FilterNonzero(store.Message{MailboxID: mb.ID})
n, err := qm.Count()
tcheck(t, err, "count messages in rejects mailbox")
@ -406,7 +408,7 @@ func TestSpam(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C451LocalErr {
@ -418,7 +420,7 @@ func TestSpam(t *testing.T) {
})
// Mark the messages as having good reputation.
q := bstore.QueryDB[store.Message](ts.acc.DB)
q := bstore.QueryDB[store.Message](ctxbg, ts.acc.DB)
_, err := q.UpdateFields(map[string]any{"Junk": false, "Notjunk": true})
tcheck(t, err, "update junkiness")
@ -427,7 +429,7 @@ func TestSpam(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
tcheck(t, err, "deliver")
@ -437,7 +439,7 @@ func TestSpam(t *testing.T) {
// Undo dmarc pass, mark messages as junk, and train the filter.
resolver.TXT = nil
q = bstore.QueryDB[store.Message](ts.acc.DB)
q = bstore.QueryDB[store.Message](ctxbg, ts.acc.DB)
_, err = q.UpdateFields(map[string]any{"Junk": true, "Notjunk": false})
tcheck(t, err, "update junkiness")
tretrain(t, ts.acc)
@ -447,7 +449,7 @@ func TestSpam(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C451LocalErr {
@ -488,7 +490,7 @@ func TestDMARCSent(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C451LocalErr {
@ -499,7 +501,7 @@ func TestDMARCSent(t *testing.T) {
// Insert a message that we sent to the address that is about to send to us.
var sentMsg store.Message
tinsertmsg(t, ts.acc, "Sent", &sentMsg, deliverMessage)
err := ts.acc.DB.Insert(&store.Recipient{MessageID: sentMsg.ID, Localpart: "remote", Domain: "example.org", OrgDomain: "example.org", Sent: time.Now()})
err := ts.acc.DB.Insert(ctxbg, &store.Recipient{MessageID: sentMsg.ID, Localpart: "remote", Domain: "example.org", OrgDomain: "example.org", Sent: time.Now()})
tcheck(t, err, "inserting message recipient")
// We should now be accepting the message because we recently sent a message.
@ -507,7 +509,7 @@ func TestDMARCSent(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
tcheck(t, err, "deliver")
})
@ -540,7 +542,7 @@ func TestBlocklistedSubjectpass(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C451LocalErr {
@ -559,7 +561,7 @@ func TestBlocklistedSubjectpass(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C550MailboxUnavail {
@ -577,7 +579,7 @@ func TestBlocklistedSubjectpass(t *testing.T) {
rcptTo := "mjl@mox.example"
passMessage := strings.Replace(deliverMessage, "Subject: test", "Subject: test "+pass, 1)
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(passMessage)), strings.NewReader(passMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(passMessage)), strings.NewReader(passMessage), false, false)
}
tcheck(t, err, "deliver with subjectpass")
})
@ -619,11 +621,11 @@ func TestDMARCReport(t *testing.T) {
msg := msgb.String()
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false)
}
tcheck(t, err, "deliver")
records, err := dmarcdb.Records(context.Background())
records, err := dmarcdb.Records(ctxbg)
tcheck(t, err, "dmarcdb records")
if len(records) != n {
t.Fatalf("got %d dmarcdb records, expected %d or more", len(records), n)
@ -736,16 +738,16 @@ func TestTLSReport(t *testing.T) {
tcheck(t, xerr, "write msg")
msg := msgb.String()
headers, xerr := dkim.Sign(context.Background(), "remote", dns.Domain{ASCII: "example.org"}, dkimConf, false, strings.NewReader(msg))
headers, xerr := dkim.Sign(ctxbg, "remote", dns.Domain{ASCII: "example.org"}, dkimConf, false, strings.NewReader(msg))
tcheck(t, xerr, "dkim sign")
msg = headers + msg
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false)
}
tcheck(t, err, "deliver")
records, err := tlsrptdb.Records(context.Background())
records, err := tlsrptdb.Records(ctxbg)
tcheck(t, err, "tlsrptdb records")
if len(records) != n {
t.Fatalf("got %d tlsrptdb records, expected %d", len(records), n)
@ -840,11 +842,11 @@ func TestRatelimitDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
tcheck(t, err, "deliver to remote")
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C452StorageFull {
t.Fatalf("got err %v, expected smtpclient error with code 452 for storage full", err)
@ -857,7 +859,7 @@ func TestRatelimitDelivery(t *testing.T) {
// Message was already delivered once. We'll do another one. But the 3rd will fail.
// We need the actual size with prepended headers, since that is used in the
// calculations.
msg, err := bstore.QueryDB[store.Message](ts.acc.DB).Get()
msg, err := bstore.QueryDB[store.Message](ctxbg, ts.acc.DB).Get()
if err != nil {
t.Fatalf("getting delivered message for its size: %v", err)
}
@ -869,11 +871,11 @@ func TestRatelimitDelivery(t *testing.T) {
mailFrom := "remote@example.org"
rcptTo := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
}
tcheck(t, err, "deliver to remote")
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
var cerr smtpclient.Error
if err == nil || !errors.As(err, &cerr) || cerr.Code != smtp.C452StorageFull {
t.Fatalf("got err %v, expected smtpclient error with code 452 for storage full", err)
@ -933,7 +935,7 @@ func TestLimitOutgoing(t *testing.T) {
ts.pass = "testtest"
ts.submission = true
err := ts.acc.DB.Insert(&store.Outgoing{Recipient: "a@other.example", Submitted: time.Now().Add(-24*time.Hour - time.Minute)})
err := ts.acc.DB.Insert(ctxbg, &store.Outgoing{Recipient: "a@other.example", Submitted: time.Now().Add(-24*time.Hour - time.Minute)})
tcheck(t, err, "inserting outgoing/recipient past 24h window")
testSubmit := func(rcptTo string, expErr *smtpclient.Error) {
@ -942,7 +944,7 @@ func TestLimitOutgoing(t *testing.T) {
t.Helper()
mailFrom := "mjl@mox.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(submitMessage)), strings.NewReader(submitMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(submitMessage)), strings.NewReader(submitMessage), false, false)
}
var cerr smtpclient.Error
if expErr == nil && err != nil || expErr != nil && (err == nil || !errors.As(err, &cerr) || cerr.Secode != expErr.Secode) {
@ -979,7 +981,7 @@ func TestCatchall(t *testing.T) {
t.Helper()
mailFrom := "mjl@other.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(submitMessage)), strings.NewReader(submitMessage), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(submitMessage)), strings.NewReader(submitMessage), false, false)
}
var cerr smtpclient.Error
if expErr == nil && err != nil || expErr != nil && (err == nil || !errors.As(err, &cerr) || cerr.Secode != expErr.Secode) {
@ -993,14 +995,14 @@ func TestCatchall(t *testing.T) {
testDeliver("MJL+TEST@mox.example", nil) // Again, and case insensitive.
testDeliver("unknown@mox.example", nil) // Catchall address, to account catchall.
n, err := bstore.QueryDB[store.Message](ts.acc.DB).Count()
n, err := bstore.QueryDB[store.Message](ctxbg, ts.acc.DB).Count()
tcheck(t, err, "checking delivered messages")
tcompare(t, n, 3)
acc, err := store.OpenAccount("catchall")
tcheck(t, err, "open account")
defer acc.Close()
n, err = bstore.QueryDB[store.Message](acc.DB).Count()
n, err = bstore.QueryDB[store.Message](ctxbg, acc.DB).Count()
tcheck(t, err, "checking delivered messages to catchall account")
tcompare(t, n, 1)
}
@ -1072,21 +1074,21 @@ test email
rcptTo := "remote@example.org"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false)
err = client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msg)), strings.NewReader(msg), false, false)
}
tcheck(t, err, "deliver")
msgs, err := queue.List()
msgs, err := queue.List(ctxbg)
tcheck(t, err, "listing queue")
n++
tcompare(t, len(msgs), n)
sort.Slice(msgs, func(i, j int) bool {
return msgs[i].ID > msgs[j].ID
})
f, err := queue.OpenMessage(msgs[0].ID)
f, err := queue.OpenMessage(ctxbg, msgs[0].ID)
tcheck(t, err, "open message in queue")
defer f.Close()
results, err := dkim.Verify(context.Background(), resolver, false, dkim.DefaultPolicy, f, false)
results, err := dkim.Verify(ctxbg, resolver, false, dkim.DefaultPolicy, f, false)
tcheck(t, err, "verifying dkim message")
tcompare(t, len(results), 1)
tcompare(t, results[0].Status, dkim.StatusPass)
@ -1117,7 +1119,7 @@ func TestPostmaster(t *testing.T) {
t.Helper()
mailFrom := "mjl@other.example"
if err == nil {
err = client.Deliver(context.Background(), mailFrom, rcptTo, int64(len(deliverMessage)), strings.NewReader(deliverMessage), false, false)
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) {