mirror of
https://github.com/mjl-/mox.git
synced 2025-04-21 21:40:01 +03:00
Run modernize to rewrite some older go constructs to newer ones
Mostly using slice.Sort, using min/max, slices.Concat, range of int and fmt.Appendf for byte slices instead of strings.
This commit is contained in:
parent
f6132bdbc0
commit
64f2f788b1
61 changed files with 146 additions and 232 deletions
admin
ctl.godane
dkim
dmarcdb
dsn
http
imapclient
imapserver
junk
main.gomessage
mlog
mox-
moxio
queue
quickstart.goratelimit
sasl
serve_unix.gosmtp
smtpclient
smtpserver
spf
store
tlsrptsend
webadmin
webapisrv
webmail
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/mjl-/mox/config"
|
||||
"github.com/mjl-/mox/dns"
|
||||
"github.com/mjl-/mox/mox-"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type TLSMode uint8
|
||||
|
@ -130,9 +131,7 @@ func ClientConfigsDomain(d dns.Domain) (ClientConfigs, error) {
|
|||
for name := range mox.Conf.Static.Listeners {
|
||||
listeners = append(listeners, name)
|
||||
}
|
||||
sort.Slice(listeners, func(i, j int) bool {
|
||||
return listeners[i] < listeners[j]
|
||||
})
|
||||
slices.Sort(listeners)
|
||||
|
||||
note := func(tls bool, requiretls bool) string {
|
||||
if !tls {
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"crypto/x509"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/mjl-/adns"
|
||||
|
@ -21,6 +20,7 @@ import (
|
|||
"github.com/mjl-/mox/smtp"
|
||||
"github.com/mjl-/mox/spf"
|
||||
"github.com/mjl-/mox/tlsrpt"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// todo: find a way to automatically create the dns records as it would greatly simplify setting up email for a domain. we could also dynamically make changes, e.g. providing grace periods after disabling a dkim key, only automatically removing the dkim dns key after a few days. but this requires some kind of api and authentication to the dns server. there doesn't appear to be a single commonly used api for dns management. each of the numerous cloud providers have their own APIs and rather large SKDs to use them. we don't want to link all of them in.
|
||||
|
@ -135,9 +135,7 @@ func DomainRecords(domConf config.Domain, domain dns.Domain, hasDNSSEC bool, cer
|
|||
for name := range domConf.DKIM.Selectors {
|
||||
selectors = append(selectors, name)
|
||||
}
|
||||
sort.Slice(selectors, func(i, j int) bool {
|
||||
return selectors[i] < selectors[j]
|
||||
})
|
||||
slices.Sort(selectors)
|
||||
for _, name := range selectors {
|
||||
sel := domConf.DKIM.Selectors[name]
|
||||
dkimr := dkim.Record{
|
||||
|
|
11
ctl.go
11
ctl.go
|
@ -15,7 +15,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -34,6 +33,7 @@ import (
|
|||
"github.com/mjl-/mox/smtp"
|
||||
"github.com/mjl-/mox/store"
|
||||
"github.com/mjl-/mox/webapi"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// ctl represents a connection to the ctl unix domain socket of a running mox instance.
|
||||
|
@ -242,10 +242,7 @@ func (s *ctlreader) Read(buf []byte) (N int, Err error) {
|
|||
}
|
||||
s.npending = int(n)
|
||||
}
|
||||
rn := len(buf)
|
||||
if rn > s.npending {
|
||||
rn = s.npending
|
||||
}
|
||||
rn := min(len(buf), s.npending)
|
||||
n, err := s.r.Read(buf[:rn])
|
||||
s.xcheck(err, "read from ctl")
|
||||
s.npending -= n
|
||||
|
@ -1375,9 +1372,7 @@ func servectlcmd(ctx context.Context, ctl *ctl, cid int64, shutdown func()) {
|
|||
for k := range l {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return keys[i] < keys[j]
|
||||
})
|
||||
slices.Sort(keys)
|
||||
s := ""
|
||||
for _, k := range keys {
|
||||
ks := k
|
||||
|
|
10
dane/dane.go
10
dane/dane.go
|
@ -65,6 +65,7 @@ import (
|
|||
"github.com/mjl-/mox/dns"
|
||||
"github.com/mjl-/mox/mlog"
|
||||
"github.com/mjl-/mox/stub"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -214,12 +215,9 @@ func Dial(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, network
|
|||
if allowedUsages != nil {
|
||||
o := 0
|
||||
for _, r := range records {
|
||||
for _, usage := range allowedUsages {
|
||||
if r.Usage == usage {
|
||||
records[o] = r
|
||||
o++
|
||||
break
|
||||
}
|
||||
if slices.Contains(allowedUsages, r.Usage) {
|
||||
records[o] = r
|
||||
o++
|
||||
}
|
||||
}
|
||||
records = records[:o]
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/mjl-/mox/publicsuffix"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
"github.com/mjl-/mox/stub"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// If set, signatures for top-level domain "localhost" are accepted.
|
||||
|
@ -173,7 +174,7 @@ func Sign(ctx context.Context, elog *slog.Logger, localpart smtp.Localpart, doma
|
|||
sig.Domain = domain
|
||||
sig.Selector = sel.Domain
|
||||
sig.Identity = &Identity{&localpart, domain}
|
||||
sig.SignedHeaders = append([]string{}, sel.Headers...)
|
||||
sig.SignedHeaders = slices.Clone(sel.Headers)
|
||||
if sel.SealHeaders {
|
||||
// ../rfc/6376:2156
|
||||
// Each time a header name is added to the signature, the next unused value is
|
||||
|
@ -839,8 +840,8 @@ func parseHeaders(br *bufio.Reader) ([]header, int, error) {
|
|||
return nil, 0, fmt.Errorf("empty header key")
|
||||
}
|
||||
lkey = strings.ToLower(key)
|
||||
value = append([]byte{}, t[1]...)
|
||||
raw = append([]byte{}, line...)
|
||||
value = slices.Clone(t[1])
|
||||
raw = slices.Clone(line)
|
||||
}
|
||||
if key != "" {
|
||||
l = append(l, header{key, lkey, value, raw})
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestParseRecord(t *testing.T) {
|
|||
}
|
||||
if r != nil {
|
||||
pk := r.Pubkey
|
||||
for i := 0; i < 2; i++ {
|
||||
for range 2 {
|
||||
ntxt, err := r.Record()
|
||||
if err != nil {
|
||||
t.Fatalf("making record: %v", err)
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/mjl-/mox/mox-"
|
||||
"github.com/mjl-/mox/moxio"
|
||||
"github.com/mjl-/mox/queue"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func tcheckf(t *testing.T, err error, format string, args ...any) {
|
||||
|
@ -301,7 +302,7 @@ func TestSendReports(t *testing.T) {
|
|||
// Read message file. Also write copy to disk for inspection.
|
||||
buf, err := io.ReadAll(&moxio.AtReader{R: msgFile})
|
||||
tcheckf(t, err, "read report message")
|
||||
err = os.WriteFile("../testdata/dmarcdb/data/report.eml", append(append([]byte{}, qm.MsgPrefix...), buf...), 0600)
|
||||
err = os.WriteFile("../testdata/dmarcdb/data/report.eml", slices.Concat(qm.MsgPrefix, buf), 0600)
|
||||
tcheckf(t, err, "write report message")
|
||||
|
||||
var feedback *dmarcrpt.Feedback
|
||||
|
|
|
@ -340,10 +340,7 @@ func (m *Message) Compose(log mlog.Log, smtputf8 bool) ([]byte, error) {
|
|||
data := base64.StdEncoding.EncodeToString(headers)
|
||||
for len(data) > 0 {
|
||||
line := data
|
||||
n := len(line)
|
||||
if n > 78 {
|
||||
n = 78
|
||||
}
|
||||
n := min(len(line), 78)
|
||||
line, data = data[:n], data[n:]
|
||||
if _, err := origp.Write([]byte(line + "\r\n")); err != nil {
|
||||
return nil, err
|
||||
|
|
13
dsn/parse.go
13
dsn/parse.go
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/mjl-/mox/message"
|
||||
"github.com/mjl-/mox/mlog"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Parse reads a DSN message.
|
||||
|
@ -217,15 +218,9 @@ func parseRecipientHeader(mr *textproto.Reader, utf8 bool) (Recipient, error) {
|
|||
case "Action":
|
||||
a := Action(strings.ToLower(v))
|
||||
actions := []Action{Failed, Delayed, Delivered, Relayed, Expanded}
|
||||
var ok bool
|
||||
for _, x := range actions {
|
||||
if a == x {
|
||||
ok = true
|
||||
r.Action = a
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
if slices.Contains(actions, a) {
|
||||
r.Action = a
|
||||
} else {
|
||||
err = fmt.Errorf("unrecognized action %q", v)
|
||||
}
|
||||
case "Status":
|
||||
|
|
|
@ -64,7 +64,7 @@ func (m dict) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|||
case int:
|
||||
tokens = []xml.Token{
|
||||
xml.StartElement{Name: xml.Name{Local: "integer"}},
|
||||
xml.CharData([]byte(fmt.Sprintf("%d", v))),
|
||||
xml.CharData(fmt.Appendf(nil, "%d", v)),
|
||||
xml.EndElement{Name: xml.Name{Local: "integer"}},
|
||||
}
|
||||
case bool:
|
||||
|
|
|
@ -14,10 +14,7 @@ type prefixConn struct {
|
|||
|
||||
func (c *prefixConn) Read(buf []byte) (int, error) {
|
||||
if len(c.prefix) > 0 {
|
||||
n := len(buf)
|
||||
if n > len(c.prefix) {
|
||||
n = len(c.prefix)
|
||||
}
|
||||
n := min(len(buf), len(c.prefix))
|
||||
copy(buf[:n], c.prefix[:n])
|
||||
c.prefix = c.prefix[n:]
|
||||
if len(c.prefix) == 0 {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/mjl-/mox/imapclient"
|
||||
"github.com/mjl-/mox/mox-"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func TestCondstore(t *testing.T) {
|
||||
|
@ -577,7 +578,7 @@ func testQresync(t *testing.T, tc *testconn, clientModseq int64) {
|
|||
}
|
||||
|
||||
makeUntagged := func(l ...imapclient.Untagged) []imapclient.Untagged {
|
||||
return append(append([]imapclient.Untagged{}, baseUntagged...), l...)
|
||||
return slices.Concat(baseUntagged, l)
|
||||
}
|
||||
|
||||
// uidvalidity 1, highest known modseq 1, sends full current state.
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/mjl-/mox/mox-"
|
||||
"github.com/mjl-/mox/moxio"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// functions to handle fetch attribute requests are defined on fetchCmd.
|
||||
|
@ -203,9 +204,7 @@ func (c *conn) cmdxFetch(isUID bool, tag, cmdstr string, p *parser) {
|
|||
}
|
||||
|
||||
// First sort the uids we already found, for fast lookup.
|
||||
sort.Slice(vanishedUIDs, func(i, j int) bool {
|
||||
return vanishedUIDs[i] < vanishedUIDs[j]
|
||||
})
|
||||
slices.Sort(vanishedUIDs)
|
||||
|
||||
// We'll be gathering any more vanished uids in more.
|
||||
more := map[store.UID]struct{}{}
|
||||
|
@ -239,9 +238,7 @@ func (c *conn) cmdxFetch(isUID bool, tag, cmdstr string, p *parser) {
|
|||
if len(vanishedUIDs) > 0 {
|
||||
// Mention all vanished UIDs in compact numset form.
|
||||
// ../rfc/7162:1985
|
||||
sort.Slice(vanishedUIDs, func(i, j int) bool {
|
||||
return vanishedUIDs[i] < vanishedUIDs[j]
|
||||
})
|
||||
slices.Sort(vanishedUIDs)
|
||||
// No hard limit on response sizes, but clients are recommended to not send more
|
||||
// than 8k. We send a more conservative max 4k.
|
||||
for _, s := range compactUIDSet(vanishedUIDs).Strings(4*1024 - 32) {
|
||||
|
@ -734,10 +731,7 @@ func (cmd *fetchCmd) xbody(a fetchAtt) (string, token) {
|
|||
var offset int64
|
||||
count := m.Size
|
||||
if a.partial != nil {
|
||||
offset = int64(a.partial.offset)
|
||||
if offset > m.Size {
|
||||
offset = m.Size
|
||||
}
|
||||
offset = min(int64(a.partial.offset), m.Size)
|
||||
count = int64(a.partial.count)
|
||||
if offset+count > m.Size {
|
||||
count = m.Size - offset
|
||||
|
|
|
@ -15,10 +15,7 @@ type prefixConn struct {
|
|||
|
||||
func (c *prefixConn) Read(buf []byte) (int, error) {
|
||||
if len(c.prefix) > 0 {
|
||||
n := len(buf)
|
||||
if n > len(c.prefix) {
|
||||
n = len(c.prefix)
|
||||
}
|
||||
n := min(len(buf), len(c.prefix))
|
||||
copy(buf[:n], c.prefix[:n])
|
||||
c.prefix = c.prefix[n:]
|
||||
if len(c.prefix) == 0 {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/mjl-/mox/message"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Search returns messages matching criteria specified in parameters.
|
||||
|
@ -454,12 +455,7 @@ func (s *search) match0(sk searchKey) bool {
|
|||
case "$mdnsent":
|
||||
return s.m.MDNSent
|
||||
default:
|
||||
for _, k := range s.m.Keywords {
|
||||
if k == kw {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(s.m.Keywords, kw)
|
||||
}
|
||||
case "SEEN":
|
||||
return s.m.Seen
|
||||
|
@ -483,12 +479,7 @@ func (s *search) match0(sk searchKey) bool {
|
|||
case "$mdnsent":
|
||||
return !s.m.MDNSent
|
||||
default:
|
||||
for _, k := range s.m.Keywords {
|
||||
if k == kw {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return !slices.Contains(s.m.Keywords, kw)
|
||||
}
|
||||
case "UNSEEN":
|
||||
return !s.m.Seen
|
||||
|
|
|
@ -66,7 +66,7 @@ func TestSearch(t *testing.T) {
|
|||
// Add 5 and delete first 4 messages. So UIDs start at 5.
|
||||
received := time.Date(2020, time.January, 1, 10, 0, 0, 0, time.UTC)
|
||||
saveDate := time.Now()
|
||||
for i := 0; i < 5; i++ {
|
||||
for range 5 {
|
||||
tc.client.Append("inbox", makeAppendTime(exampleMsg, received))
|
||||
}
|
||||
tc.client.StoreFlagsSet("1:4", true, `\Deleted`)
|
||||
|
@ -394,7 +394,7 @@ func TestSearch(t *testing.T) {
|
|||
// More than 1mb total for literals.
|
||||
_, err = fmt.Fprintf(tc.client, "x0 uid search")
|
||||
tcheck(t, err, "write start of uit search")
|
||||
for i := 0; i < 10; i++ {
|
||||
for range 10 {
|
||||
writeTextLit(100*1024, true)
|
||||
}
|
||||
writeTextLit(1, false)
|
||||
|
@ -402,7 +402,7 @@ func TestSearch(t *testing.T) {
|
|||
// More than 1000 literals.
|
||||
_, err = fmt.Fprintf(tc.client, "x0 uid search")
|
||||
tcheck(t, err, "write start of uit search")
|
||||
for i := 0; i < 1000; i++ {
|
||||
for range 1000 {
|
||||
writeTextLit(1, true)
|
||||
}
|
||||
writeTextLit(1, false)
|
||||
|
|
|
@ -2760,9 +2760,7 @@ func (c *conn) cmdSelectExamine(isselect bool, tag, cmd string, p *parser) {
|
|||
// Now that we have all vanished UIDs, send them over compactly.
|
||||
if len(vanishedUIDs) > 0 {
|
||||
l := maps.Keys(vanishedUIDs)
|
||||
sort.Slice(l, func(i, j int) bool {
|
||||
return l[i] < l[j]
|
||||
})
|
||||
slices.Sort(l)
|
||||
// ../rfc/7162:1985
|
||||
for _, s := range compactUIDSet(l).Strings(4*1024 - 32) {
|
||||
c.bwritelinef("* VANISHED (EARLIER) %s", s)
|
||||
|
@ -3913,9 +3911,7 @@ func (c *conn) gatherCopyMoveUIDs(isUID bool, nums numSet) ([]store.UID, []any)
|
|||
// response and interpret it differently than we intended.
|
||||
// ../rfc/9051:5072
|
||||
uids := c.xnumSetUIDs(isUID, nums)
|
||||
sort.Slice(uids, func(i, j int) bool {
|
||||
return uids[i] < uids[j]
|
||||
})
|
||||
slices.Sort(uids)
|
||||
uidargs := make([]any, len(uids))
|
||||
for i, uid := range uids {
|
||||
uidargs[i] = uid
|
||||
|
@ -4200,7 +4196,7 @@ func (c *conn) cmdxMove(isUID bool, tag, cmd string, p *parser) {
|
|||
c.bwritelinef("* OK [COPYUID %d %s %s] moved", mbDst.UIDValidity, compactUIDSet(uids).String(), newUIDs.String())
|
||||
qresync := c.enabled[capQresync]
|
||||
var vanishedUIDs numSet
|
||||
for i := 0; i < len(uids); i++ {
|
||||
for i := range uids {
|
||||
seq := c.xsequence(uids[i])
|
||||
c.sequenceRemove(seq, uids[i])
|
||||
if qresync {
|
||||
|
@ -4452,7 +4448,7 @@ func (c *conn) cmdxStore(isUID bool, tag, cmd string, p *parser) {
|
|||
|
||||
origFlags := m.Flags
|
||||
m.Flags = m.Flags.Set(mask, flags)
|
||||
oldKeywords := append([]string{}, m.Keywords...)
|
||||
oldKeywords := slices.Clone(m.Keywords)
|
||||
if minus {
|
||||
m.Keywords, _ = store.RemoveKeywords(m.Keywords, keywords)
|
||||
} else if plus {
|
||||
|
@ -4463,7 +4459,7 @@ func (c *conn) cmdxStore(isUID bool, tag, cmd string, p *parser) {
|
|||
|
||||
keywordsChanged := func() bool {
|
||||
sort.Strings(oldKeywords)
|
||||
n := append([]string{}, m.Keywords...)
|
||||
n := slices.Clone(m.Keywords)
|
||||
sort.Strings(n)
|
||||
return !slices.Equal(oldKeywords, n)
|
||||
}
|
||||
|
@ -4581,9 +4577,7 @@ func (c *conn) cmdxStore(isUID bool, tag, cmd string, p *parser) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(mnums, func(i, j int) bool {
|
||||
return mnums[i] < mnums[j]
|
||||
})
|
||||
slices.Sort(mnums)
|
||||
set := compactUIDSet(mnums)
|
||||
// ../rfc/7162:2506
|
||||
c.writeresultf("%s OK [MODIFIED %s] conditional store did not modify all", tag, set.String())
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/mjl-/mox/mox-"
|
||||
"github.com/mjl-/mox/moxvar"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var ctxbg = context.Background()
|
||||
|
@ -210,7 +211,7 @@ func (tc *testconn) xuntagged(exps ...imapclient.Untagged) {
|
|||
|
||||
func (tc *testconn) xuntaggedOpt(all bool, exps ...imapclient.Untagged) {
|
||||
tc.t.Helper()
|
||||
last := append([]imapclient.Untagged{}, tc.lastUntagged...)
|
||||
last := slices.Clone(tc.lastUntagged)
|
||||
var mismatch any
|
||||
next:
|
||||
for ei, exp := range exps {
|
||||
|
@ -572,13 +573,13 @@ func TestState(t *testing.T) {
|
|||
defer tc.close()
|
||||
|
||||
// Not authenticated, lots of commands not allowed.
|
||||
for _, cmd := range append(append([]string{}, authenticatedOrSelected...), selected...) {
|
||||
for _, cmd := range slices.Concat(authenticatedOrSelected, selected) {
|
||||
tc.transactf("no", "%s", cmd)
|
||||
}
|
||||
|
||||
// Some commands not allowed when authenticated.
|
||||
tc.transactf("ok", `login mjl@mox.example "%s"`, password0)
|
||||
for _, cmd := range append(append([]string{}, notAuthenticated...), selected...) {
|
||||
for _, cmd := range slices.Concat(notAuthenticated, selected) {
|
||||
tc.transactf("no", "%s", cmd)
|
||||
}
|
||||
|
||||
|
|
|
@ -70,14 +70,14 @@ func NewBloom(data []byte, k int) (*Bloom, error) {
|
|||
|
||||
func (b *Bloom) Add(s string) {
|
||||
h := hash([]byte(s), b.w)
|
||||
for i := 0; i < b.k; i++ {
|
||||
for range b.k {
|
||||
b.set(h.nextPos())
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bloom) Has(s string) bool {
|
||||
h := hash([]byte(s), b.w)
|
||||
for i := 0; i < b.k; i++ {
|
||||
for range b.k {
|
||||
if !b.has(h.nextPos()) {
|
||||
return false
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func (b *Bloom) Modified() bool {
|
|||
// Ones returns the number of ones.
|
||||
func (b *Bloom) Ones() (n int) {
|
||||
for _, d := range b.data {
|
||||
for i := 0; i < 8; i++ {
|
||||
for range 8 {
|
||||
if d&1 != 0 {
|
||||
n++
|
||||
}
|
||||
|
|
|
@ -62,26 +62,26 @@ func TestBloom(t *testing.T) {
|
|||
|
||||
func TestBits(t *testing.T) {
|
||||
b := &bits{width: 1, buf: []byte{0xff, 0xff}}
|
||||
for i := 0; i < 16; i++ {
|
||||
for range 16 {
|
||||
if b.nextPos() != 1 {
|
||||
t.Fatalf("pos not 1")
|
||||
}
|
||||
}
|
||||
b = &bits{width: 2, buf: []byte{0xff, 0xff}}
|
||||
for i := 0; i < 8; i++ {
|
||||
for range 8 {
|
||||
if b.nextPos() != 0b11 {
|
||||
t.Fatalf("pos not 0b11")
|
||||
}
|
||||
}
|
||||
|
||||
b = &bits{width: 1, buf: []byte{0b10101010, 0b10101010}}
|
||||
for i := 0; i < 16; i++ {
|
||||
for i := range 16 {
|
||||
if b.nextPos() != ((i + 1) % 2) {
|
||||
t.Fatalf("bad pos")
|
||||
}
|
||||
}
|
||||
b = &bits{width: 2, buf: []byte{0b10101010, 0b10101010}}
|
||||
for i := 0; i < 8; i++ {
|
||||
for range 8 {
|
||||
if b.nextPos() != 0b10 {
|
||||
t.Fatalf("pos not 0b10")
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ func TestSet(t *testing.T) {
|
|||
0b01010101,
|
||||
},
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
for i := range 8 {
|
||||
v := b.has(i)
|
||||
if v != (i%2 == 0) {
|
||||
t.Fatalf("bad has")
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/mjl-/mox/message"
|
||||
"github.com/mjl-/mox/mlog"
|
||||
"github.com/mjl-/mox/moxvar"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -270,9 +271,7 @@ func (f *Filter) Save() error {
|
|||
words[i] = w
|
||||
i++
|
||||
}
|
||||
sort.Slice(words, func(i, j int) bool {
|
||||
return words[i] < words[j]
|
||||
})
|
||||
slices.Sort(words)
|
||||
|
||||
f.log.Debug("inserting words in junkfilter db", slog.Any("words", len(f.changed)))
|
||||
// start := time.Now()
|
||||
|
@ -336,9 +335,7 @@ func (f *Filter) Save() error {
|
|||
}
|
||||
|
||||
func loadWords(ctx context.Context, db *bstore.DB, l []string, dst map[string]word) error {
|
||||
sort.Slice(l, func(i, j int) bool {
|
||||
return l[i] < l[j]
|
||||
})
|
||||
slices.Sort(l)
|
||||
|
||||
err := db.Read(ctx, func(tx *bstore.Tx) error {
|
||||
for _, w := range l {
|
||||
|
@ -478,14 +475,8 @@ func (f *Filter) ClassifyWords(ctx context.Context, words map[string]struct{}) (
|
|||
return a.Score > b.Score
|
||||
})
|
||||
|
||||
nham := f.TopWords
|
||||
if nham > len(topHam) {
|
||||
nham = len(topHam)
|
||||
}
|
||||
nspam := f.TopWords
|
||||
if nspam > len(topSpam) {
|
||||
nspam = len(topSpam)
|
||||
}
|
||||
nham := min(f.TopWords, len(topHam))
|
||||
nspam := min(f.TopWords, len(topSpam))
|
||||
topHam = topHam[:nham]
|
||||
topSpam = topSpam[:nspam]
|
||||
|
||||
|
|
|
@ -253,10 +253,7 @@ func (r *htmlTextReader) Read(buf []byte) (n int, err error) {
|
|||
// todo: deal with inline elements? they shouldn't cause a word break.
|
||||
|
||||
give := func(nbuf []byte) (int, error) {
|
||||
n := len(buf)
|
||||
if n > len(nbuf) {
|
||||
n = len(nbuf)
|
||||
}
|
||||
n := min(len(buf), len(nbuf))
|
||||
copy(buf, nbuf[:n])
|
||||
nbuf = nbuf[n:]
|
||||
if len(nbuf) < cap(r.buf) {
|
||||
|
|
8
main.go
8
main.go
|
@ -1223,7 +1223,7 @@ error too, for reference.
|
|||
|
||||
xwriteFile(prefix+".ed25519privatekey.pkcs8.pem", privKeyBufPEM, "private key")
|
||||
xwriteFile(prefix+".certificate.pem", certBufPEM, "certificate")
|
||||
combinedPEM := append(append([]byte{}, privKeyBufPEM...), certBufPEM...)
|
||||
combinedPEM := slices.Concat(privKeyBufPEM, certBufPEM)
|
||||
xwriteFile(prefix+".ed25519privatekey-certificate.pem", combinedPEM, "combined private key and certificate")
|
||||
|
||||
shabuf := sha256.Sum256(tlsCert.Leaf.RawSubjectPublicKeyInfo)
|
||||
|
@ -3229,7 +3229,7 @@ func cmdWebapi(c *cmd) {
|
|||
t := reflect.TypeFor[webapi.Methods]()
|
||||
methods := map[string]reflect.Type{}
|
||||
var ml []string
|
||||
for i := 0; i < t.NumMethod(); i++ {
|
||||
for i := range t.NumMethod() {
|
||||
mt := t.Method(i)
|
||||
methods[mt.Name] = mt.Type
|
||||
ml = append(ml, mt.Name)
|
||||
|
@ -3999,7 +3999,7 @@ For testing the pagination. Operates directly on queue database.
|
|||
xcheckf(err, "removing temporary webhook after forwarding autoincrement sequence")
|
||||
fh.ID -= int64(n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
t0 := now.Add(-time.Duration(i) * time.Second)
|
||||
last := now.Add(-time.Duration(i/10) * time.Second)
|
||||
mr := queue.MsgRetired{
|
||||
|
@ -4037,7 +4037,7 @@ For testing the pagination. Operates directly on queue database.
|
|||
xcheckf(err, "inserting retired message")
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
t0 := now.Add(-time.Duration(i) * time.Second)
|
||||
last := now.Add(-time.Duration(i/10) * time.Second)
|
||||
var event string
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"github.com/mjl-/mox/mlog"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Pedantic enables stricter parsing.
|
||||
|
@ -848,10 +849,8 @@ func (b *bufAt) maxLineLength() int {
|
|||
|
||||
// ensure makes sure b.nbuf is up to maxLineLength, unless eof is encountered.
|
||||
func (b *bufAt) ensure() error {
|
||||
for _, c := range b.buf[:b.nbuf] {
|
||||
if c == '\n' {
|
||||
return nil
|
||||
}
|
||||
if slices.Contains(b.buf[:b.nbuf], '\n') {
|
||||
return nil
|
||||
}
|
||||
if b.scratch == nil {
|
||||
b.scratch = make([]byte, b.maxLineLength())
|
||||
|
@ -1014,10 +1013,7 @@ func (b *boundReader) Read(buf []byte) (count int, rerr error) {
|
|||
for {
|
||||
// Read data from earlier line.
|
||||
if b.nbuf > 0 {
|
||||
n := b.nbuf
|
||||
if n > len(buf) {
|
||||
n = len(buf)
|
||||
}
|
||||
n := min(b.nbuf, len(buf))
|
||||
copy(buf, b.buf[:n])
|
||||
copy(b.buf, b.buf[n:])
|
||||
buf = buf[n:]
|
||||
|
@ -1046,10 +1042,7 @@ func (b *boundReader) Read(buf []byte) (count int, rerr error) {
|
|||
return count, err
|
||||
}
|
||||
if len(b.crlf) > 0 {
|
||||
n := len(b.crlf)
|
||||
if n > len(buf) {
|
||||
n = len(buf)
|
||||
}
|
||||
n := min(len(b.crlf), len(buf))
|
||||
copy(buf, b.crlf[:n])
|
||||
count += n
|
||||
buf = buf[n:]
|
||||
|
|
|
@ -56,10 +56,7 @@ func (w *Writer) Write(buf []byte) (int, error) {
|
|||
// Update w.tail after having written. Regardless of error, writers can't expect
|
||||
// subsequent writes to work again properly anyway.
|
||||
defer func() {
|
||||
n := len(buf)
|
||||
if n > 3 {
|
||||
n = 3
|
||||
}
|
||||
n := min(len(buf), 3)
|
||||
copy(w.tail[:], w.tail[n:])
|
||||
copy(w.tail[3-n:], buf[len(buf)-n:])
|
||||
}()
|
||||
|
|
11
mlog/log.go
11
mlog/log.go
|
@ -28,6 +28,7 @@ import (
|
|||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var noctx = context.Background()
|
||||
|
@ -452,7 +453,7 @@ func stringValue(iscid, nested bool, v any) string {
|
|||
}
|
||||
b := &strings.Builder{}
|
||||
b.WriteString("[")
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
if i > 0 {
|
||||
b.WriteString(";")
|
||||
}
|
||||
|
@ -469,10 +470,10 @@ func stringValue(iscid, nested bool, v any) string {
|
|||
// We first try making a string without recursing into structs/pointers/interfaces,
|
||||
// but will try again with those fields if we otherwise would otherwise log an
|
||||
// empty string.
|
||||
for j := 0; j < 2; j++ {
|
||||
for j := range 2 {
|
||||
first := true
|
||||
b := &strings.Builder{}
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
fv := rv.Field(i)
|
||||
if !t.Field(i).IsExported() {
|
||||
continue
|
||||
|
@ -636,7 +637,7 @@ func (w *errWriter) Write(buf []byte) (int, error) {
|
|||
func (h *handler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
nh := *h
|
||||
if h.Attrs != nil {
|
||||
nh.Attrs = append([]slog.Attr{}, h.Attrs...)
|
||||
nh.Attrs = slices.Clone(h.Attrs)
|
||||
}
|
||||
nh.Attrs = append(nh.Attrs, attrs...)
|
||||
return &nh
|
||||
|
@ -654,7 +655,7 @@ func (h *handler) WithGroup(name string) slog.Handler {
|
|||
func (h *handler) WithPkg(pkg string) *handler {
|
||||
nh := *h
|
||||
if nh.Pkgs != nil {
|
||||
nh.Pkgs = append([]string{}, nh.Pkgs...)
|
||||
nh.Pkgs = slices.Clone(nh.Pkgs)
|
||||
}
|
||||
nh.Pkgs = append(nh.Pkgs, pkg)
|
||||
return &nh
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -199,9 +198,7 @@ func (c *Config) Domains() (l []string) {
|
|||
l = append(l, name)
|
||||
}
|
||||
})
|
||||
sort.Slice(l, func(i, j int) bool {
|
||||
return l[i] < l[j]
|
||||
})
|
||||
slices.Sort(l)
|
||||
return l
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
func FillNil(rv reflect.Value) (nv reflect.Value, changed bool) {
|
||||
switch rv.Kind() {
|
||||
case reflect.Struct:
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
for i := range rv.NumField() {
|
||||
if !rv.Type().Field(i).IsExported() {
|
||||
continue
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func FillNil(rv reflect.Value) (nv reflect.Value, changed bool) {
|
|||
if ch && !rv.CanSet() {
|
||||
// Make struct settable.
|
||||
nrv := reflect.New(rv.Type()).Elem()
|
||||
for j := 0; j < rv.NumField(); j++ {
|
||||
for j := range rv.NumField() {
|
||||
nrv.Field(j).Set(rv.Field(j))
|
||||
}
|
||||
rv = nrv
|
||||
|
@ -34,7 +34,7 @@ func FillNil(rv reflect.Value) (nv reflect.Value, changed bool) {
|
|||
return reflect.MakeSlice(rv.Type(), 0, 0), true
|
||||
}
|
||||
n := rv.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
rve := rv.Index(i)
|
||||
nrv, ch := FillNil(rve)
|
||||
if ch {
|
||||
|
@ -90,7 +90,7 @@ func FillExample(seen []reflect.Type, rv reflect.Value) reflect.Value {
|
|||
|
||||
switch rv.Kind() {
|
||||
case reflect.Struct:
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
for i := range rv.NumField() {
|
||||
if !rvt.Field(i).IsExported() {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ func GeneratePassword() string {
|
|||
chars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-_;:,<.>/"
|
||||
s := ""
|
||||
buf := make([]byte, 1)
|
||||
for i := 0; i < 12; i++ {
|
||||
for range 12 {
|
||||
for {
|
||||
cryptorand.Read(buf)
|
||||
i := int(buf[0])
|
||||
|
|
|
@ -9,10 +9,7 @@ func TXTStrings(s string) string {
|
|||
|
||||
r := "(\n"
|
||||
for len(s) > 0 {
|
||||
n := len(s)
|
||||
if n > 100 {
|
||||
n = 100
|
||||
}
|
||||
n := min(len(s), 100)
|
||||
if r != "" {
|
||||
r += " "
|
||||
}
|
||||
|
|
|
@ -39,10 +39,7 @@ type lineWrapper struct {
|
|||
func (lw *lineWrapper) Write(buf []byte) (int, error) {
|
||||
wrote := 0
|
||||
for len(buf) > 0 {
|
||||
n := 78 - lw.n
|
||||
if n > len(buf) {
|
||||
n = len(buf)
|
||||
}
|
||||
n := min(78-lw.n, len(buf))
|
||||
nn, err := lw.w.Write(buf[:n])
|
||||
if nn > 0 {
|
||||
wrote += nn
|
||||
|
|
|
@ -54,7 +54,7 @@ func (b *Bufpool) put(log mlog.Log, buf []byte, n int) {
|
|||
return
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
buf[i] = 0
|
||||
}
|
||||
select {
|
||||
|
|
|
@ -15,7 +15,7 @@ func TestBufpool(t *testing.T) {
|
|||
bp := NewBufpool(1, 8)
|
||||
a := bp.get()
|
||||
b := bp.get()
|
||||
for i := 0; i < len(a); i++ {
|
||||
for i := range a {
|
||||
a[i] = 1
|
||||
}
|
||||
log := mlog.New("moxio", nil)
|
||||
|
|
|
@ -50,7 +50,7 @@ func NewWorkQueue[T, R any](procs, size int, preparer func(in, out chan Work[T,
|
|||
}
|
||||
|
||||
wq.wg.Add(procs)
|
||||
for i := 0; i < procs; i++ {
|
||||
for range procs {
|
||||
go func() {
|
||||
defer wq.wg.Done()
|
||||
preparer(wq.work, wq.done)
|
||||
|
|
|
@ -429,7 +429,7 @@ func TestFromIDIncomingDelivery(t *testing.T) {
|
|||
tcheck(t, err, "get added hook")
|
||||
h.URL = hs.URL
|
||||
handler = handleError
|
||||
for i := 0; i < len(hookIntervals); i++ {
|
||||
for i := range hookIntervals {
|
||||
hookDeliver(pkglog, h)
|
||||
<-hookDeliveryResults
|
||||
err := DB.Get(ctxbg, &h)
|
||||
|
@ -557,7 +557,7 @@ func TestHookListFilterSort(t *testing.T) {
|
|||
// Descending by submitted,id.
|
||||
l, err = HookList(ctxbg, HookFilter{}, HookSort{Field: "Submitted"})
|
||||
tcheck(t, err, "list")
|
||||
ll := append(append([]Hook{}, hlrev[1:]...), hl[5])
|
||||
ll := append(slices.Clone(hlrev[1:]), hl[5])
|
||||
tcompare(t, l, ll)
|
||||
|
||||
// Filter by all fields to get a single.
|
||||
|
|
|
@ -1372,7 +1372,7 @@ func deliver(log mlog.Log, resolver dns.Resolver, m0 Msg) {
|
|||
}
|
||||
|
||||
backoff = time.Duration(7*60+30+jitter.IntN(10)-5) * time.Second
|
||||
for i := 0; i < m0.Attempts; i++ {
|
||||
for range m0.Attempts {
|
||||
backoff *= time.Duration(2)
|
||||
}
|
||||
m0.Attempts++
|
||||
|
|
|
@ -310,10 +310,10 @@ func TestQueue(t *testing.T) {
|
|||
writeline("250-" + ext)
|
||||
}
|
||||
writeline("250 pipelining")
|
||||
for tx := 0; tx < ntx; tx++ {
|
||||
for range ntx {
|
||||
readline("mail")
|
||||
writeline("250 ok")
|
||||
for i := 0; i < rcpts; i++ {
|
||||
for i := range rcpts {
|
||||
readline("rcpt")
|
||||
if onercpt && i > 0 {
|
||||
writeline("552 ok")
|
||||
|
@ -462,7 +462,7 @@ func TestQueue(t *testing.T) {
|
|||
fmt.Fprintf(server, "235 2.7.0 auth ok\r\n")
|
||||
br.ReadString('\n') // Should be MAIL FROM.
|
||||
fmt.Fprintf(server, "250 ok\r\n")
|
||||
for i := 0; i < nrcpt; i++ {
|
||||
for range nrcpt {
|
||||
br.ReadString('\n') // Should be RCPT TO.
|
||||
fmt.Fprintf(server, "250 ok\r\n")
|
||||
}
|
||||
|
@ -520,7 +520,7 @@ func TestQueue(t *testing.T) {
|
|||
|
||||
// Wait for all results.
|
||||
timer.Reset(time.Second)
|
||||
for i := 0; i < nresults; i++ {
|
||||
for range nresults {
|
||||
select {
|
||||
case <-deliveryResults:
|
||||
case <-timer.C:
|
||||
|
@ -1331,7 +1331,7 @@ func TestListFilterSort(t *testing.T) {
|
|||
// Descending by queued,id.
|
||||
l, err = List(ctxbg, Filter{}, Sort{Field: "Queued"})
|
||||
tcheck(t, err, "list messages")
|
||||
ql := append(append([]Msg{}, qmlrev[1:]...), qml[5])
|
||||
ql := append(slices.Clone(qmlrev[1:]), qml[5])
|
||||
tcompare(t, l, ql)
|
||||
|
||||
// Filter by all fields to get a single.
|
||||
|
|
|
@ -39,6 +39,7 @@ import (
|
|||
"github.com/mjl-/mox/rdap"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
//go:embed mox.service
|
||||
|
@ -344,9 +345,7 @@ Troubleshooting hints:
|
|||
for k := range names {
|
||||
nameList = append(nameList, strings.TrimRight(k, "."))
|
||||
}
|
||||
sort.Slice(nameList, func(i, j int) bool {
|
||||
return nameList[i] < nameList[j]
|
||||
})
|
||||
slices.Sort(nameList)
|
||||
if len(nameList) == 0 {
|
||||
dnshostname, err = dns.ParseDomain(hostnameStr + "." + domain.Name())
|
||||
if err != nil {
|
||||
|
@ -534,7 +533,7 @@ messages over SMTP.
|
|||
fmt.Printf("\nWARNING: %s", fmt.Sprintf(format, args...))
|
||||
warned = true
|
||||
}
|
||||
for i := 0; i < len(ips); i++ {
|
||||
for range ips {
|
||||
r := <-results
|
||||
if r.Err != nil {
|
||||
warnf("looking up reverse name for %s: %v", r.IP, r.Err)
|
||||
|
|
|
@ -55,7 +55,7 @@ func (l *Limiter) checkAdd(add bool, ip net.IP, tm time.Time, n int64) bool {
|
|||
l.WindowLimits[i].Counts = pl.Counts
|
||||
}
|
||||
|
||||
for j := 0; j < 3; j++ {
|
||||
for j := range 3 {
|
||||
if i == 0 {
|
||||
l.ipmasked[j] = l.maskIP(j, ip)
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func (l *Limiter) checkAdd(add bool, ip net.IP, tm time.Time, n int64) bool {
|
|||
}
|
||||
// Finally record.
|
||||
for _, pl := range l.WindowLimits {
|
||||
for j := 0; j < 3; j++ {
|
||||
for j := range 3 {
|
||||
pl.Counts[struct {
|
||||
Index uint8
|
||||
IPMasked [16]byte
|
||||
|
@ -90,7 +90,7 @@ func (l *Limiter) Reset(ip net.IP, tm time.Time) {
|
|||
defer l.Unlock()
|
||||
|
||||
// Prepare masked ip's.
|
||||
for i := 0; i < 3; i++ {
|
||||
for i := range 3 {
|
||||
l.ipmasked[i] = l.maskIP(i, ip)
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ func (l *Limiter) Reset(ip net.IP, tm time.Time) {
|
|||
continue
|
||||
}
|
||||
var n int64
|
||||
for j := 0; j < 3; j++ {
|
||||
for j := range 3 {
|
||||
k := struct {
|
||||
Index uint8
|
||||
IPMasked [16]byte
|
||||
|
|
|
@ -77,7 +77,7 @@ func (a *clientPlain) Next(fromServer []byte) (toServer []byte, last bool, rerr
|
|||
defer func() { a.step++ }()
|
||||
switch a.step {
|
||||
case 0:
|
||||
return []byte(fmt.Sprintf("\u0000%s\u0000%s", a.Username, a.Password)), true, nil
|
||||
return fmt.Appendf(nil, "\u0000%s\u0000%s", a.Username, a.Password), true, nil
|
||||
default:
|
||||
return nil, false, fmt.Errorf("invalid step %d", a.step)
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ func (a *clientCRAMMD5) Next(fromServer []byte) (toServer []byte, last bool, rer
|
|||
opadh.Write(ipadh.Sum(nil))
|
||||
|
||||
// ../rfc/2195:88
|
||||
return []byte(fmt.Sprintf("%s %x", a.Username, opadh.Sum(nil))), true, nil
|
||||
return fmt.Appendf(nil, "%s %x", a.Username, opadh.Sum(nil)), true, nil
|
||||
|
||||
default:
|
||||
return nil, false, fmt.Errorf("invalid step %d", a.step)
|
||||
|
|
|
@ -85,7 +85,7 @@ func monitorDNSBL(log mlog.Log) {
|
|||
last = time.Now()
|
||||
|
||||
// Gather zones.
|
||||
zones := append([]dns.Domain{}, publicListener.SMTP.DNSBLZones...)
|
||||
zones := slices.Clone(publicListener.SMTP.DNSBLZones)
|
||||
conf := mox.Conf.DynamicConfig()
|
||||
for _, zone := range conf.MonitorDNSBLZones {
|
||||
if !slices.Contains(zones, zone) {
|
||||
|
|
|
@ -164,10 +164,7 @@ func (r *DataReader) Read(p []byte) (int, error) {
|
|||
// Reject "[^\r]\n.\n" and "[^\r]\n.\r\n"
|
||||
r.badcrlf = true
|
||||
}
|
||||
n := len(r.buf)
|
||||
if n > len(p) {
|
||||
n = len(p)
|
||||
}
|
||||
n := min(len(r.buf), len(p))
|
||||
copy(p, r.buf[:n])
|
||||
if n == 1 {
|
||||
r.plast, r.last = r.last, r.buf[0]
|
||||
|
|
|
@ -1243,7 +1243,7 @@ func (c *Client) DeliverMultiple(ctx context.Context, mailFrom string, rcptTo []
|
|||
// Read responses to RCPT TO.
|
||||
rcptResps = make([]Response, len(rcptTo))
|
||||
nok := 0
|
||||
for i := 0; i < len(rcptTo); i++ {
|
||||
for i := range rcptTo {
|
||||
code, secode, firstLine, moreLines, err := c.read()
|
||||
// 552 should be treated as temporary historically, ../rfc/5321:3576
|
||||
permanent := code/100 == 5 && code != smtp.C552MailboxFull
|
||||
|
|
|
@ -273,7 +273,7 @@ func TestClient(t *testing.T) {
|
|||
if n == 0 {
|
||||
n = 1
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
readline("RCPT TO:")
|
||||
resp := "250 ok"
|
||||
if i < len(opts.resps) {
|
||||
|
@ -293,7 +293,7 @@ func TestClient(t *testing.T) {
|
|||
|
||||
readline("MAIL FROM:")
|
||||
writeline("250 ok")
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
readline("RCPT TO:")
|
||||
resp := "250 ok"
|
||||
if i < len(opts.resps) {
|
||||
|
@ -366,7 +366,7 @@ func TestClient(t *testing.T) {
|
|||
}()
|
||||
|
||||
var errs []error
|
||||
for i := 0; i < 2; i++ {
|
||||
for range 2 {
|
||||
err := <-result
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
|
@ -907,7 +907,7 @@ func run(t *testing.T, server func(s xserver), client func(conn net.Conn)) {
|
|||
client(clientConn)
|
||||
}()
|
||||
var errs []error
|
||||
for i := 0; i < 2; i++ {
|
||||
for range 2 {
|
||||
err := <-result
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
|
|
|
@ -104,7 +104,7 @@ func TestGatherDestinations(t *testing.T) {
|
|||
|
||||
var zerodom dns.Domain
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
for i := range 2 {
|
||||
authic := i == 1
|
||||
resolver.AllAuthentic = authic
|
||||
// Basic with simple MX.
|
||||
|
@ -187,7 +187,7 @@ func TestGatherIPs(t *testing.T) {
|
|||
return r
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
for i := range 2 {
|
||||
authic := i == 1
|
||||
resolver.AllAuthentic = authic
|
||||
|
||||
|
|
|
@ -3203,7 +3203,7 @@ func (c *conn) deliver(ctx context.Context, recvHdrFor func(string) string, msgW
|
|||
rcptDMARCMethod.Comment += "override " + strings.Join(dmarcOverrides, ",")
|
||||
}
|
||||
rcptAuthResults := authResults
|
||||
rcptAuthResults.Methods = append([]message.AuthMethod{}, authResults.Methods...)
|
||||
rcptAuthResults.Methods = slices.Clone(authResults.Methods)
|
||||
rcptAuthResults.Methods = append(rcptAuthResults.Methods, rcptDMARCMethod)
|
||||
|
||||
// Prepend reason as message header, for easy viewing in mail clients.
|
||||
|
|
|
@ -727,7 +727,7 @@ func TestSpam(t *testing.T) {
|
|||
Flags: store.Flags{Seen: true, Junk: true},
|
||||
Size: int64(len(deliverMessage)),
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
for range 3 {
|
||||
nm := m
|
||||
tinsertmsg(t, ts.acc, "Inbox", &nm, deliverMessage)
|
||||
nm = m
|
||||
|
@ -868,7 +868,7 @@ happens to come from forwarding mail server.
|
|||
mailFrom = "remote@bad.example"
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
for range 10 {
|
||||
err := client.Deliver(ctxbg, mailFrom, rcptTo, int64(len(msgBad)), strings.NewReader(msgBad), false, false, false)
|
||||
tcheck(t, err, "deliver message")
|
||||
}
|
||||
|
@ -967,7 +967,7 @@ func TestDMARCSent(t *testing.T) {
|
|||
}
|
||||
// We need at least 50 ham messages for the junk filter to become significant. We
|
||||
// offset it with negative messages for mediocre score.
|
||||
for i := 0; i < 50; i++ {
|
||||
for range 50 {
|
||||
nm := m
|
||||
nm.Junk = true
|
||||
tinsertmsg(t, ts.acc, "Archive", &nm, deliverMessage)
|
||||
|
|
|
@ -806,7 +806,7 @@ func expandDomainSpec(ctx context.Context, resolver dns.Resolver, domainSpec str
|
|||
if reverse {
|
||||
nt := len(t)
|
||||
h := nt / 2
|
||||
for i := 0; i < h; i++ {
|
||||
for i := range h {
|
||||
t[i], t[nt-1-i] = t[nt-1-i], t[i]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3198,7 +3198,7 @@ func RemoveKeywords(l, remove []string) ([]string, bool) {
|
|||
for _, k := range remove {
|
||||
if i := slices.Index(l, k); i >= 0 {
|
||||
if !copied {
|
||||
l = append([]string{}, l...)
|
||||
l = slices.Clone(l)
|
||||
copied = true
|
||||
}
|
||||
copy(l[i:], l[i+1:])
|
||||
|
@ -3219,7 +3219,7 @@ func MergeKeywords(l, add []string) ([]string, bool) {
|
|||
for _, k := range add {
|
||||
if !slices.Contains(l, k) {
|
||||
if !copied {
|
||||
l = append([]string{}, l...)
|
||||
l = slices.Clone(l)
|
||||
copied = true
|
||||
}
|
||||
l = append(l, k)
|
||||
|
|
|
@ -234,14 +234,14 @@ func TestMailbox(t *testing.T) {
|
|||
})
|
||||
|
||||
// Run the auth tests twice for possible cache effects.
|
||||
for i := 0; i < 2; i++ {
|
||||
for range 2 {
|
||||
_, _, err := OpenEmailAuth(log, "mjl@mox.example", "bogus", false)
|
||||
if err != ErrUnknownCredentials {
|
||||
t.Fatalf("got %v, expected ErrUnknownCredentials", err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
for range 2 {
|
||||
acc2, _, err := OpenEmailAuth(log, "mjl@mox.example", "testtest", false)
|
||||
tcheck(t, err, "open for email with auth")
|
||||
err = acc2.Close()
|
||||
|
|
|
@ -99,7 +99,7 @@ func TestLoginAttempt(t *testing.T) {
|
|||
|
||||
// Insert 3 failing entries. Then add another and see we still have 3.
|
||||
loginAttemptsMaxPerAccount = 3
|
||||
for i := 0; i < loginAttemptsMaxPerAccount; i++ {
|
||||
for i := range loginAttemptsMaxPerAccount {
|
||||
a := a2
|
||||
a.UserAgent = fmt.Sprintf("%d", i)
|
||||
LoginAttemptAdd(ctxbg, pkglog, a)
|
||||
|
|
|
@ -696,7 +696,7 @@ func composeMessage(ctx context.Context, log mlog.Log, mf *os.File, policyDomain
|
|||
selectors := mox.DKIMSelectors(confDKIM)
|
||||
for i, sel := range selectors {
|
||||
// Also sign the TLS-Report headers. ../rfc/8460:940
|
||||
sel.Headers = append(append([]string{}, sel.Headers...), "TLS-Report-Domain", "TLS-Report-Submitter")
|
||||
sel.Headers = append(slices.Clone(sel.Headers), "TLS-Report-Domain", "TLS-Report-Submitter")
|
||||
selectors[i] = sel
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/mjl-/mox/queue"
|
||||
"github.com/mjl-/mox/tlsrpt"
|
||||
"github.com/mjl-/mox/tlsrptdb"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var ctxbg = context.Background()
|
||||
|
@ -423,7 +424,7 @@ func TestSendReports(t *testing.T) {
|
|||
tcheckf(t, err, "read report message")
|
||||
p := fmt.Sprintf("../testdata/tlsrptsend/data/report%d.eml", index)
|
||||
index++
|
||||
err = os.WriteFile(p, append(append([]byte{}, qml[0].MsgPrefix...), buf...), 0600)
|
||||
err = os.WriteFile(p, slices.Concat(qml[0].MsgPrefix, buf), 0600)
|
||||
tcheckf(t, err, "write report message")
|
||||
|
||||
reportJSON, err := tlsrpt.ParseMessage(log.Logger, msgFile)
|
||||
|
|
|
@ -657,7 +657,7 @@ EOF
|
|||
}
|
||||
}
|
||||
r.IPRev.IPNames = map[string][]string{}
|
||||
for i := 0; i < n; i++ {
|
||||
for range n {
|
||||
lr := <-results
|
||||
host, addrs, ip, err := lr.Host, lr.Addrs, lr.IP, lr.Err
|
||||
if err != nil {
|
||||
|
@ -1598,9 +1598,7 @@ func (Admin) DomainLocalparts(ctx context.Context, domain string) (localpartAcco
|
|||
// Accounts returns the names of all configured and all disabled accounts.
|
||||
func (Admin) Accounts(ctx context.Context) (all, disabled []string) {
|
||||
all, disabled = mox.Conf.AccountsDisabled()
|
||||
sort.Slice(all, func(i, j int) bool {
|
||||
return all[i] < all[j]
|
||||
})
|
||||
slices.Sort(all)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1862,7 +1860,7 @@ func (Admin) DNSBLStatus(ctx context.Context) (results map[string]map[string]str
|
|||
func dnsblsStatus(ctx context.Context, log mlog.Log, resolver dns.Resolver) (results map[string]map[string]string, using, monitoring []dns.Domain) {
|
||||
// todo: check health before using dnsbl?
|
||||
using = mox.Conf.Static.Listeners["public"].SMTP.DNSBLZones
|
||||
zones := append([]dns.Domain{}, using...)
|
||||
zones := slices.Clone(using)
|
||||
conf := mox.Conf.DynamicConfig()
|
||||
for _, zone := range conf.MonitorDNSBLZones {
|
||||
if !slices.Contains(zones, zone) {
|
||||
|
|
|
@ -202,7 +202,7 @@ func init() {
|
|||
var methods []string
|
||||
mt := reflect.TypeFor[webapi.Methods]()
|
||||
n := mt.NumMethod()
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
methods = append(methods, mt.Method(i).Name)
|
||||
}
|
||||
docsIndexTmpl := htmltemplate.Must(htmltemplate.New("index").Parse(`<!doctype html>
|
||||
|
@ -877,10 +877,7 @@ func (s server) Send(ctx context.Context, req webapi.SendRequest) (resp webapi.S
|
|||
|
||||
for len(base64Data) > 0 {
|
||||
line := base64Data
|
||||
n := len(line)
|
||||
if n > 78 {
|
||||
n = 78
|
||||
}
|
||||
n := min(len(line), 78)
|
||||
line, base64Data = base64Data[:n], base64Data[n:]
|
||||
_, err := p.Write([]byte(line))
|
||||
xcheckf(err, "writing attachment")
|
||||
|
|
|
@ -132,11 +132,11 @@ func TestServer(t *testing.T) {
|
|||
testHTTP("PUT", "/v0/Send", http.StatusMethodNotAllowed, "")
|
||||
testHTTP("POST", "/v0/Send", http.StatusUnauthorized, "")
|
||||
|
||||
for i := 0; i < 11; i++ {
|
||||
for range 11 {
|
||||
// Missing auth doesn't trigger auth rate limiter.
|
||||
testHTTP("POST", "/v0/Send", http.StatusUnauthorized, "")
|
||||
}
|
||||
for i := 0; i < 21; i++ {
|
||||
for i := range 21 {
|
||||
// Bad auth does.
|
||||
expCode := http.StatusUnauthorized
|
||||
tooMany := i >= 10
|
||||
|
|
|
@ -826,10 +826,7 @@ func (w Webmail) MessageSubmit(ctx context.Context, m SubmitMessage) {
|
|||
|
||||
for len(base64Data) > 0 {
|
||||
line := base64Data
|
||||
n := len(line)
|
||||
if n > 78 {
|
||||
n = 78
|
||||
}
|
||||
n := min(len(line), 78)
|
||||
line, base64Data = base64Data[:n], base64Data[n:]
|
||||
_, err := ap.Write(line)
|
||||
xcheckf(ctx, err, "writing attachment")
|
||||
|
|
|
@ -143,7 +143,7 @@ func TestAPI(t *testing.T) {
|
|||
testLogin("bad@bad.example", pw0, "user:loginFailed")
|
||||
}
|
||||
// Ensure rate limiter is triggered, also for slow tests.
|
||||
for i := 0; i < 10; i++ {
|
||||
for range 10 {
|
||||
testLogin("bad@bad.example", pw0, "user:loginFailed", "user:error")
|
||||
}
|
||||
testLogin("bad@bad.example", pw0, "user:error")
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/mjl-/mox/moxio"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
"github.com/mjl-/mox/store"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// todo: we should have all needed information for messageItem in store.Message (perhaps some data in message.Part) for fast access, not having to parse the on-disk message file.
|
||||
|
@ -139,12 +140,7 @@ func formatFirstLine(r io.Reader) (string, error) {
|
|||
if len(l) >= 5 {
|
||||
return false
|
||||
}
|
||||
for _, line := range l {
|
||||
if line == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return !slices.Contains(l, "")
|
||||
}
|
||||
|
||||
result := ""
|
||||
|
@ -287,7 +283,7 @@ func parsedMessage(log mlog.Log, m store.Message, state *msgState, full, msgitem
|
|||
if mt == "MULTIPART/SIGNED" && i >= 1 {
|
||||
continue
|
||||
}
|
||||
usePart(sp, i, &p, append(append([]int{}, path...), i), newParentMixed)
|
||||
usePart(sp, i, &p, append(slices.Clone(path), i), newParentMixed)
|
||||
}
|
||||
switch mt {
|
||||
case "TEXT/PLAIN", "/":
|
||||
|
@ -313,7 +309,7 @@ func parsedMessage(log mlog.Log, m store.Message, state *msgState, full, msgitem
|
|||
return
|
||||
}
|
||||
pm.Texts = append(pm.Texts, string(buf))
|
||||
pm.TextPaths = append(pm.TextPaths, append([]int{}, path...))
|
||||
pm.TextPaths = append(pm.TextPaths, slices.Clone(path))
|
||||
}
|
||||
if msgitem && pm.firstLine == "" {
|
||||
pm.firstLine, rerr = formatFirstLine(p.ReaderUTF8OrBinary())
|
||||
|
@ -326,7 +322,7 @@ func parsedMessage(log mlog.Log, m store.Message, state *msgState, full, msgitem
|
|||
case "TEXT/HTML":
|
||||
pm.HasHTML = true
|
||||
if full && pm.HTMLPath == nil {
|
||||
pm.HTMLPath = append([]int{}, path...)
|
||||
pm.HTMLPath = slices.Clone(path)
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -353,7 +349,7 @@ func parsedMessage(log mlog.Log, m store.Message, state *msgState, full, msgitem
|
|||
return
|
||||
}
|
||||
pm.Texts = append(pm.Texts, string(buf))
|
||||
pm.TextPaths = append(pm.TextPaths, append([]int{}, path...))
|
||||
pm.TextPaths = append(pm.TextPaths, slices.Clone(path))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -365,7 +361,7 @@ func parsedMessage(log mlog.Log, m store.Message, state *msgState, full, msgitem
|
|||
return
|
||||
}
|
||||
pm.Texts = append(pm.Texts, string(buf))
|
||||
pm.TextPaths = append(pm.TextPaths, append([]int{}, path...))
|
||||
pm.TextPaths = append(pm.TextPaths, slices.Clone(path))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1971,7 +1971,7 @@ func (q Query) envFilterFn(log mlog.Log, state *msgState) func(m store.Message)
|
|||
return false
|
||||
}
|
||||
if len(filterTo) > 0 || len(notFilterTo) > 0 {
|
||||
to := append(append(append([]message.Address{}, env.To...), env.CC...), env.BCC...)
|
||||
to := slices.Concat(env.To, env.CC, env.BCC)
|
||||
if len(filterTo) > 0 && !contains(filterTo, to, true) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ func TestView(t *testing.T) {
|
|||
|
||||
// Token
|
||||
tokens := []string{}
|
||||
for i := 0; i < 20; i++ {
|
||||
for range 20 {
|
||||
tokens = append(tokens, api.Token(ctx))
|
||||
}
|
||||
// Only last 10 tokens are still valid and around, checked below.
|
||||
|
|
Loading…
Reference in a new issue