mirror of
https://github.com/mjl-/mox.git
synced 2025-07-13 00:54:38 +03:00
in integration test, don't read database index files but use imap idle to get notified of message delivery, and make integration & quickstart tests faster by making first-time sender delay configurable, and using a 1s timeout instead of the default 15s
we could make more types of delays configurable. the current approach isn't great, as it results in an a default value of "0s" in the config file, while the actual default is 15s (which is documented just above, but still).
This commit is contained in:
@ -100,7 +100,7 @@ func FuzzServer(f *testing.F) {
|
||||
const submission = false
|
||||
err := serverConn.SetDeadline(time.Now().Add(time.Second))
|
||||
flog(err, "set server deadline")
|
||||
serve("test", cid, dns.Domain{ASCII: "mox.example"}, nil, serverConn, resolver, submission, false, 100<<10, false, false, nil)
|
||||
serve("test", cid, dns.Domain{ASCII: "mox.example"}, nil, serverConn, resolver, submission, false, 100<<10, false, false, nil, 0)
|
||||
cid++
|
||||
}
|
||||
|
||||
|
@ -100,10 +100,10 @@ func limitersInit() {
|
||||
|
||||
var (
|
||||
// Delays for bad/suspicious behaviour. Zero during tests.
|
||||
badClientDelay = time.Second // Before reads and after 1-byte writes for probably spammers.
|
||||
authFailDelay = time.Second // Response to authentication failure.
|
||||
reputationlessSenderDeliveryDelay = 15 * time.Second // Before accepting message from first-time sender.
|
||||
unknownRecipientsDelay = 5 * time.Second // Response when all recipients are unknown.
|
||||
badClientDelay = time.Second // Before reads and after 1-byte writes for probably spammers.
|
||||
authFailDelay = time.Second // Response to authentication failure.
|
||||
unknownRecipientsDelay = 5 * time.Second // Response when all recipients are unknown.
|
||||
firstTimeSenderDelayDefault = 15 * time.Second // Before accepting message from first-time sender.
|
||||
)
|
||||
|
||||
type codes struct {
|
||||
@ -166,6 +166,13 @@ var (
|
||||
|
||||
var jitterRand = mox.NewRand()
|
||||
|
||||
func durationDefault(delay *time.Duration, def time.Duration) time.Duration {
|
||||
if delay == nil {
|
||||
return def
|
||||
}
|
||||
return *delay
|
||||
}
|
||||
|
||||
// Listen initializes network listeners for incoming SMTP connection.
|
||||
// The listeners are stored for a later call to Serve.
|
||||
func Listen() {
|
||||
@ -187,7 +194,8 @@ func Listen() {
|
||||
}
|
||||
port := config.Port(listener.SMTP.Port, 25)
|
||||
for _, ip := range listener.IPs {
|
||||
listen1("smtp", name, ip, port, hostname, tlsConfig, false, false, maxMsgSize, false, listener.SMTP.RequireSTARTTLS, listener.SMTP.DNSBLZones)
|
||||
firstTimeSenderDelay := durationDefault(listener.SMTP.FirstTimeSenderDelay, firstTimeSenderDelayDefault)
|
||||
listen1("smtp", name, ip, port, hostname, tlsConfig, false, false, maxMsgSize, false, listener.SMTP.RequireSTARTTLS, listener.SMTP.DNSBLZones, firstTimeSenderDelay)
|
||||
}
|
||||
}
|
||||
if listener.Submission.Enabled {
|
||||
@ -197,7 +205,7 @@ func Listen() {
|
||||
}
|
||||
port := config.Port(listener.Submission.Port, 587)
|
||||
for _, ip := range listener.IPs {
|
||||
listen1("submission", name, ip, port, hostname, tlsConfig, true, false, maxMsgSize, !listener.Submission.NoRequireSTARTTLS, !listener.Submission.NoRequireSTARTTLS, nil)
|
||||
listen1("submission", name, ip, port, hostname, tlsConfig, true, false, maxMsgSize, !listener.Submission.NoRequireSTARTTLS, !listener.Submission.NoRequireSTARTTLS, nil, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +216,7 @@ func Listen() {
|
||||
}
|
||||
port := config.Port(listener.Submissions.Port, 465)
|
||||
for _, ip := range listener.IPs {
|
||||
listen1("submissions", name, ip, port, hostname, tlsConfig, true, true, maxMsgSize, true, true, nil)
|
||||
listen1("submissions", name, ip, port, hostname, tlsConfig, true, true, maxMsgSize, true, true, nil, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,7 +224,7 @@ func Listen() {
|
||||
|
||||
var servers []func()
|
||||
|
||||
func listen1(protocol, name, ip string, port int, hostname dns.Domain, tlsConfig *tls.Config, submission, xtls bool, maxMessageSize int64, requireTLSForAuth, requireTLSForDelivery bool, dnsBLs []dns.Domain) {
|
||||
func listen1(protocol, name, ip string, port int, hostname dns.Domain, tlsConfig *tls.Config, submission, xtls bool, maxMessageSize int64, requireTLSForAuth, requireTLSForDelivery bool, dnsBLs []dns.Domain, firstTimeSenderDelay time.Duration) {
|
||||
addr := net.JoinHostPort(ip, fmt.Sprintf("%d", port))
|
||||
if os.Getuid() == 0 {
|
||||
xlog.Print("listening for smtp", mlog.Field("listener", name), mlog.Field("address", addr), mlog.Field("protocol", protocol))
|
||||
@ -238,7 +246,7 @@ func listen1(protocol, name, ip string, port int, hostname dns.Domain, tlsConfig
|
||||
continue
|
||||
}
|
||||
resolver := dns.StrictResolver{} // By leaving Pkg empty, it'll be set by each package that uses the resolver, e.g. spf/dkim/dmarc.
|
||||
go serve(name, mox.Cid(), hostname, tlsConfig, conn, resolver, submission, xtls, maxMessageSize, requireTLSForAuth, requireTLSForDelivery, dnsBLs)
|
||||
go serve(name, mox.Cid(), hostname, tlsConfig, conn, resolver, submission, xtls, maxMessageSize, requireTLSForAuth, requireTLSForDelivery, dnsBLs, firstTimeSenderDelay)
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,6 +291,7 @@ type conn struct {
|
||||
cmdStart time.Time // Start of current command.
|
||||
ncmds int // Number of commands processed. Used to abort connection when first incoming command is unknown/invalid.
|
||||
dnsBLs []dns.Domain
|
||||
firstTimeSenderDelay time.Duration
|
||||
|
||||
// If non-zero, taken into account during Read and Write. Set while processing DATA
|
||||
// command, we don't want the entire delivery to take too long.
|
||||
@ -509,7 +518,7 @@ func (c *conn) writelinef(format string, args ...any) {
|
||||
|
||||
var cleanClose struct{} // Sentinel value for panic/recover indicating clean close of connection.
|
||||
|
||||
func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.Config, nc net.Conn, resolver dns.Resolver, submission, tls bool, maxMessageSize int64, requireTLSForAuth, requireTLSForDelivery bool, dnsBLs []dns.Domain) {
|
||||
func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.Config, nc net.Conn, resolver dns.Resolver, submission, tls bool, maxMessageSize int64, requireTLSForAuth, requireTLSForDelivery bool, dnsBLs []dns.Domain, firstTimeSenderDelay time.Duration) {
|
||||
var localIP, remoteIP net.IP
|
||||
if a, ok := nc.LocalAddr().(*net.TCPAddr); ok {
|
||||
localIP = a.IP
|
||||
@ -540,6 +549,7 @@ func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.C
|
||||
requireTLSForAuth: requireTLSForAuth,
|
||||
requireTLSForDelivery: requireTLSForDelivery,
|
||||
dnsBLs: dnsBLs,
|
||||
firstTimeSenderDelay: firstTimeSenderDelay,
|
||||
}
|
||||
c.log = xlog.MoreFields(func() []mlog.Pair {
|
||||
now := time.Now()
|
||||
@ -2454,9 +2464,9 @@ func (c *conn) deliver(ctx context.Context, recvHdrFor func(string) string, msgW
|
||||
// If not dmarc or tls report (Seen set above), and this is a first-time sender,
|
||||
// wait before actually delivering. If this turns out to be a spammer, we've kept
|
||||
// one of their connections busy.
|
||||
if !m.Flags.Seen && a.reason == reasonNoBadSignals && reputationlessSenderDeliveryDelay > 0 {
|
||||
log.Debug("delaying before delivering from sender without reputation", mlog.Field("delay", reputationlessSenderDeliveryDelay))
|
||||
mox.Sleep(mox.Context, reputationlessSenderDeliveryDelay)
|
||||
if !m.Flags.Seen && a.reason == reasonNoBadSignals && c.firstTimeSenderDelay > 0 {
|
||||
log.Debug("delaying before delivering from sender without reputation", mlog.Field("delay", c.firstTimeSenderDelay))
|
||||
mox.Sleep(mox.Context, c.firstTimeSenderDelay)
|
||||
}
|
||||
|
||||
// Gather the message-id before we deliver and the file may be consumed.
|
||||
|
@ -45,7 +45,6 @@ var ctxbg = context.Background()
|
||||
func init() {
|
||||
// Don't make tests slow.
|
||||
badClientDelay = 0
|
||||
reputationlessSenderDeliveryDelay = 0
|
||||
authFailDelay = 0
|
||||
unknownRecipientsDelay = 0
|
||||
}
|
||||
@ -133,7 +132,7 @@ func (ts *testserver) run(fn func(helloErr error, client *smtpclient.Client)) {
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{fakeCert(ts.t)},
|
||||
}
|
||||
serve("test", ts.cid-2, dns.Domain{ASCII: "mox.example"}, tlsConfig, serverConn, ts.resolver, ts.submission, false, 100<<20, false, false, ts.dnsbls)
|
||||
serve("test", ts.cid-2, dns.Domain{ASCII: "mox.example"}, tlsConfig, serverConn, ts.resolver, ts.submission, false, 100<<20, false, false, ts.dnsbls, 0)
|
||||
close(serverdone)
|
||||
}()
|
||||
|
||||
@ -914,7 +913,7 @@ func TestNonSMTP(t *testing.T) {
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{fakeCert(ts.t)},
|
||||
}
|
||||
serve("test", ts.cid-2, dns.Domain{ASCII: "mox.example"}, tlsConfig, serverConn, ts.resolver, ts.submission, false, 100<<20, false, false, ts.dnsbls)
|
||||
serve("test", ts.cid-2, dns.Domain{ASCII: "mox.example"}, tlsConfig, serverConn, ts.resolver, ts.submission, false, 100<<20, false, false, ts.dnsbls, 0)
|
||||
close(serverdone)
|
||||
}()
|
||||
|
||||
|
Reference in New Issue
Block a user