mirror of
https://github.com/hanzoai/mail.git
synced 2026-09-23 23:53:02 +00:00
Go 1.27.1, and the code it can say more simply
Modules declare go 1.27.1 and the build images follow. go fix applied the modernizers; omitzero is not applied, since it changes what the JSON says. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/hanzoai/mail/config"
|
||||
"github.com/hanzoai/mail/dns"
|
||||
"github.com/hanzoai/mail/junk"
|
||||
"github.com/hanzoai/mail/mlog"
|
||||
"github.com/hanzoai/mail/mox-"
|
||||
"github.com/hanzoai/mail/mtasts"
|
||||
@@ -112,14 +111,12 @@ func MakeAccountConfig(addr smtp.Address) config.Account {
|
||||
RejectsMailbox: "Rejects",
|
||||
JunkFilter: &config.JunkFilter{
|
||||
Threshold: 0.95,
|
||||
Params: junk.Params{
|
||||
Onegrams: true,
|
||||
MaxPower: .01,
|
||||
TopWords: 10,
|
||||
IgnoreWords: .1,
|
||||
RareWords: 2,
|
||||
},
|
||||
},
|
||||
NoCustomPassword: true,
|
||||
}
|
||||
account.AutomaticJunkFlags.Enabled = true
|
||||
|
||||
+1
-1
@@ -354,7 +354,7 @@ Accounts:
|
||||
m1 := store.Message{
|
||||
MailboxID: sent.ID,
|
||||
MailboxOrigID: sent.ID,
|
||||
Flags: store.Flags{Seen: true, Junk: true},
|
||||
Seen: true, Junk: true,
|
||||
Size: int64(len(prefix1) + len(msg1)),
|
||||
MsgPrefix: []byte(prefix1),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/hanzoai/mail
|
||||
|
||||
go 1.25.0
|
||||
go 1.27.1
|
||||
|
||||
require (
|
||||
github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea
|
||||
|
||||
@@ -136,7 +136,7 @@ type Opts struct {
|
||||
// Debug-8.
|
||||
func New(conn net.Conn, opts *Opts) (client *Conn, rerr error) {
|
||||
c := Conn{
|
||||
Proto: Proto{conn: conn},
|
||||
conn: conn,
|
||||
}
|
||||
|
||||
var clog *slog.Logger
|
||||
|
||||
+9
-8
@@ -886,15 +886,16 @@ func (p *Proto) xnilString() string {
|
||||
}
|
||||
}
|
||||
|
||||
//go:fix inline
|
||||
func ptr[T any](v T) *T {
|
||||
return &v
|
||||
return new(v)
|
||||
}
|
||||
|
||||
func (p *Proto) xnilptrString() *string {
|
||||
if p.peek('"') {
|
||||
return ptr(p.xquoted())
|
||||
return new(p.xquoted())
|
||||
} else if p.peek('{') {
|
||||
return ptr(string(p.xliteral()))
|
||||
return new(string(p.xliteral()))
|
||||
} else {
|
||||
p.xtake("nil")
|
||||
return nil
|
||||
@@ -1118,11 +1119,11 @@ func (p *Proto) xbodyExtMpart() (ext *BodyExtensionMpart) {
|
||||
if !p.space() {
|
||||
return
|
||||
}
|
||||
ext.Language = ptr(p.xbodyFldLang())
|
||||
ext.Language = new(p.xbodyFldLang())
|
||||
if !p.space() {
|
||||
return
|
||||
}
|
||||
ext.Location = ptr(p.xbodyFldLoc())
|
||||
ext.Location = new(p.xbodyFldLoc())
|
||||
for p.space() {
|
||||
ext.More = append(ext.More, p.xbodyExtension())
|
||||
}
|
||||
@@ -1141,11 +1142,11 @@ func (p *Proto) xbodyExt1Part() (ext *BodyExtension1Part) {
|
||||
if !p.space() {
|
||||
return
|
||||
}
|
||||
ext.Language = ptr(p.xbodyFldLang())
|
||||
ext.Language = new(p.xbodyFldLang())
|
||||
if !p.space() {
|
||||
return
|
||||
}
|
||||
ext.Location = ptr(p.xbodyFldLoc())
|
||||
ext.Location = new(p.xbodyFldLoc())
|
||||
for p.space() {
|
||||
ext.More = append(ext.More, p.xbodyExtension())
|
||||
}
|
||||
@@ -1182,7 +1183,7 @@ func (p *Proto) xbodyFldDsp() (*string, [][2]string) {
|
||||
p.xspace()
|
||||
param := p.xbodyFldParam()
|
||||
p.xtake(")")
|
||||
return ptr(disposition), param
|
||||
return new(disposition), param
|
||||
}
|
||||
|
||||
// ../rfc/9051:6391 ../rfc/3501:4616
|
||||
|
||||
@@ -18,7 +18,8 @@ func tcompare(t *testing.T, a, b any) {
|
||||
}
|
||||
}
|
||||
|
||||
func uint32ptr(v uint32) *uint32 { return &v }
|
||||
//go:fix inline
|
||||
func uint32ptr(v uint32) *uint32 { return new(v) }
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
code, err := ParseCode("COPYUID 1 1:3 2:4")
|
||||
@@ -26,8 +27,8 @@ func TestParse(t *testing.T) {
|
||||
tcompare(t, code,
|
||||
CodeCopyUID{
|
||||
DestUIDValidity: 1,
|
||||
From: []NumRange{{First: 1, Last: uint32ptr(3)}},
|
||||
To: []NumRange{{First: 2, Last: uint32ptr(4)}},
|
||||
From: []NumRange{{First: 1, Last: new(uint32(3))}},
|
||||
To: []NumRange{{First: 2, Last: new(uint32(4))}},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ func testCondstoreQresync(t *testing.T, qresync, uidonly bool) {
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 1, All: esearchall0("1"), ModSeq: clientModseq})
|
||||
|
||||
tc.transactf("ok", "Search Return (Count) 1:* Modseq 0")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Count: uint32ptr(6), ModSeq: clientModseq})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Count: new(uint32(6)), ModSeq: clientModseq})
|
||||
|
||||
tc.transactf("ok", "Search Return (Min Max) 1:* Modseq 0")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 6, ModSeq: clientModseq})
|
||||
|
||||
+21
-21
@@ -59,10 +59,10 @@ func testFetch(t *testing.T, uidonly bool) {
|
||||
bodystructure1 := bodyxstructure1
|
||||
bodystructure1.RespAttr = "BODYSTRUCTURE"
|
||||
bodyext1 := imapclient.BodyExtension1Part{
|
||||
Disposition: ptr((*string)(nil)),
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new((*string)(nil)),
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
}
|
||||
bodystructbody1.Ext = &bodyext1
|
||||
bodystructure1.Body = bodystructbody1
|
||||
@@ -312,19 +312,19 @@ func testFetch(t *testing.T, uidonly bool) {
|
||||
Bodies: []any{
|
||||
imapclient.BodyTypeBasic{MediaType: "AUDIO", MediaSubtype: "BASIC", BodyFields: imapclient.BodyFields{CTE: "BASE64", Octets: 22}, Ext: &bodyext1},
|
||||
imapclient.BodyTypeBasic{MediaType: "IMAGE", MediaSubtype: "JPEG", BodyFields: imapclient.BodyFields{CTE: "BASE64"}, Ext: &imapclient.BodyExtension1Part{
|
||||
Disposition: ptr(ptr("inline")),
|
||||
DispositionParams: ptr([][2]string{{"filename", "image.jpg"}}),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new(new("inline")),
|
||||
DispositionParams: new([][2]string{{"filename", "image.jpg"}}),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
}},
|
||||
},
|
||||
MediaSubtype: "PARALLEL",
|
||||
Ext: &imapclient.BodyExtensionMpart{
|
||||
Params: [][2]string{{"BOUNDARY", "unique-boundary-2"}},
|
||||
Disposition: ptr((*string)(nil)), // Present but nil.
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new((*string)(nil)), // Present but nil.
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
},
|
||||
},
|
||||
imapclient.BodyTypeText{MediaType: "TEXT", MediaSubtype: "ENRICHED", BodyFields: imapclient.BodyFields{Octets: 145}, Lines: 5, Ext: &bodyext1},
|
||||
@@ -343,21 +343,21 @@ func testFetch(t *testing.T, uidonly bool) {
|
||||
MediaType: "TEXT", MediaSubtype: "PLAIN", BodyFields: imapclient.BodyFields{Params: [][2]string{{"CHARSET", "ISO-8859-1"}}, CTE: "QUOTED-PRINTABLE", Octets: 51}, Lines: 1, Ext: &bodyext1},
|
||||
Lines: 7,
|
||||
Ext: &imapclient.BodyExtension1Part{
|
||||
MD5: ptr("MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY="),
|
||||
Disposition: ptr((*string)(nil)),
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string{"en", "de"}),
|
||||
Location: ptr(ptr("http://localhost")),
|
||||
MD5: new("MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY="),
|
||||
Disposition: new((*string)(nil)),
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string{"en", "de"}),
|
||||
Location: new(new("http://localhost")),
|
||||
},
|
||||
},
|
||||
},
|
||||
MediaSubtype: "MIXED",
|
||||
Ext: &imapclient.BodyExtensionMpart{
|
||||
Params: [][2]string{{"BOUNDARY", "unique-boundary-1"}},
|
||||
Disposition: ptr((*string)(nil)), // Present but nil.
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new((*string)(nil)), // Present but nil.
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func testMove(t *testing.T, uidonly bool) {
|
||||
|
||||
tc.transactf("ok", "move 1:* Trash")
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedResult{Status: "OK", Code: imapclient.CodeCopyUID{DestUIDValidity: 1, From: []imapclient.NumRange{{First: 3, Last: uint32ptr(4)}}, To: []imapclient.NumRange{{First: 1, Last: uint32ptr(2)}}}, Text: "moved"},
|
||||
imapclient.UntaggedResult{Status: "OK", Code: imapclient.CodeCopyUID{DestUIDValidity: 1, From: []imapclient.NumRange{{First: 3, Last: new(uint32(4))}}, To: []imapclient.NumRange{{First: 1, Last: new(uint32(2))}}}, Text: "moved"},
|
||||
imapclient.UntaggedExpunge(1),
|
||||
imapclient.UntaggedExpunge(1),
|
||||
)
|
||||
@@ -92,12 +92,12 @@ func testMove(t *testing.T, uidonly bool) {
|
||||
tc.transactf("ok", "uid move 6:5 Trash")
|
||||
if uidonly {
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedResult{Status: "OK", Code: imapclient.CodeCopyUID{DestUIDValidity: 1, From: []imapclient.NumRange{{First: 5, Last: uint32ptr(6)}}, To: []imapclient.NumRange{{First: 3, Last: uint32ptr(4)}}}, Text: "moved"},
|
||||
imapclient.UntaggedResult{Status: "OK", Code: imapclient.CodeCopyUID{DestUIDValidity: 1, From: []imapclient.NumRange{{First: 5, Last: new(uint32(6))}}, To: []imapclient.NumRange{{First: 3, Last: new(uint32(4))}}}, Text: "moved"},
|
||||
imapclient.UntaggedVanished{UIDs: xparseNumSet("5:6")},
|
||||
)
|
||||
} else {
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedResult{Status: "OK", Code: imapclient.CodeCopyUID{DestUIDValidity: 1, From: []imapclient.NumRange{{First: 5, Last: uint32ptr(6)}}, To: []imapclient.NumRange{{First: 3, Last: uint32ptr(4)}}}, Text: "moved"},
|
||||
imapclient.UntaggedResult{Status: "OK", Code: imapclient.CodeCopyUID{DestUIDValidity: 1, From: []imapclient.NumRange{{First: 5, Last: new(uint32(6))}}, To: []imapclient.NumRange{{First: 3, Last: new(uint32(4))}}}, Text: "moved"},
|
||||
imapclient.UntaggedExpunge(1),
|
||||
imapclient.UntaggedExpunge(1),
|
||||
)
|
||||
|
||||
+13
-13
@@ -109,10 +109,10 @@ func testNotify(t *testing.T, uidonly bool) {
|
||||
},
|
||||
Lines: 1,
|
||||
Ext: &imapclient.BodyExtension1Part{
|
||||
Disposition: ptr((*string)(nil)),
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new((*string)(nil)),
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
},
|
||||
},
|
||||
imapclient.BodyTypeText{
|
||||
@@ -124,24 +124,24 @@ func testNotify(t *testing.T, uidonly bool) {
|
||||
},
|
||||
Lines: 1,
|
||||
Ext: &imapclient.BodyExtension1Part{
|
||||
Disposition: ptr((*string)(nil)),
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new((*string)(nil)),
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
},
|
||||
},
|
||||
},
|
||||
MediaSubtype: "ALTERNATIVE",
|
||||
Ext: &imapclient.BodyExtensionMpart{
|
||||
Params: [][2]string{{"BOUNDARY", "x"}},
|
||||
Disposition: ptr((*string)(nil)), // Present but nil.
|
||||
DispositionParams: ptr([][2]string(nil)),
|
||||
Language: ptr([]string(nil)),
|
||||
Location: ptr((*string)(nil)),
|
||||
Disposition: new((*string)(nil)), // Present but nil.
|
||||
DispositionParams: new([][2]string(nil)),
|
||||
Language: new([]string(nil)),
|
||||
Location: new((*string)(nil)),
|
||||
},
|
||||
},
|
||||
},
|
||||
imapclient.FetchPreview{Preview: ptr("this is plain text.")},
|
||||
imapclient.FetchPreview{Preview: new("this is plain text.")},
|
||||
imapclient.FetchModSeq(modseq),
|
||||
),
|
||||
)
|
||||
|
||||
+16
-15
@@ -34,8 +34,9 @@ this is html.
|
||||
--x--
|
||||
`, "\n", "\r\n")
|
||||
|
||||
//go:fix inline
|
||||
func uint32ptr(v uint32) *uint32 {
|
||||
return &v
|
||||
return new(v)
|
||||
}
|
||||
|
||||
func (tc *testconn) xsearch(nums ...uint32) {
|
||||
@@ -316,7 +317,7 @@ func testSearch(t *testing.T, uidonly bool) {
|
||||
tc.xesearch(esearchall("1:3")) // Without any options, "ALL" is implicit.
|
||||
|
||||
tc.transactf("ok", "search return (min max count all) all")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 3, Count: uint32ptr(3), All: esearchall0("1:3")})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 3, Count: new(uint32(3)), All: esearchall0("1:3")})
|
||||
|
||||
tc.transactf("ok", "search return (min) all")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1})
|
||||
@@ -352,25 +353,25 @@ func testSearch(t *testing.T, uidonly bool) {
|
||||
tc.xesearch(imapclient.UntaggedEsearch{})
|
||||
|
||||
tc.transactf("ok", "search return (min max all count) not all")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Count: uint32ptr(0)})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Count: new(uint32(0))})
|
||||
|
||||
tc.transactf("ok", "search return (min max count all) 1,3")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 3, Count: uint32ptr(2), All: esearchall0("1,3")})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 3, Count: new(uint32(2)), All: esearchall0("1,3")})
|
||||
|
||||
tc.transactf("ok", "search return (min max count all) UID 5,7")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 3, Count: uint32ptr(2), All: esearchall0("1,3")})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{Min: 1, Max: 3, Count: new(uint32(2)), All: esearchall0("1,3")})
|
||||
}
|
||||
|
||||
tc.transactf("ok", "UID search return (min max count all) all")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{UID: true, Min: 5, Max: 7, Count: uint32ptr(3), All: esearchall0("5:7")})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{UID: true, Min: 5, Max: 7, Count: new(uint32(3)), All: esearchall0("5:7")})
|
||||
|
||||
if !uidonly {
|
||||
tc.transactf("ok", "uid search return (min max count all) 1,3")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{UID: true, Min: 5, Max: 7, Count: uint32ptr(2), All: esearchall0("5,7")})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{UID: true, Min: 5, Max: 7, Count: new(uint32(2)), All: esearchall0("5,7")})
|
||||
}
|
||||
|
||||
tc.transactf("ok", "uid search return (min max count all) UID 5,7")
|
||||
tc.xesearch(imapclient.UntaggedEsearch{UID: true, Min: 5, Max: 7, Count: uint32ptr(2), All: esearchall0("5,7")})
|
||||
tc.xesearch(imapclient.UntaggedEsearch{UID: true, Min: 5, Max: 7, Count: new(uint32(2)), All: esearchall0("5,7")})
|
||||
|
||||
if !uidonly {
|
||||
tc.transactf("no", `search return () charset unknown text "mox"`)
|
||||
@@ -584,8 +585,8 @@ func testSearchMulti(t *testing.T, selected, uidonly bool) {
|
||||
tc.cmdf("Tag1", `Esearch In (Mailboxes (INBOX Archive Archive)) Return (Min Max Count All) All`)
|
||||
tc.response("ok")
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Min: 5, Max: 7, Count: uint32ptr(3), All: esearchall0("5:7")},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Archive", UIDValidity: 1, UID: true, Min: 1, Max: 1, Count: uint32ptr(1), All: esearchall0("1")},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Min: 5, Max: 7, Count: new(uint32(3)), All: esearchall0("5:7")},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Archive", UIDValidity: 1, UID: true, Min: 1, Max: 1, Count: new(uint32(1)), All: esearchall0("1")},
|
||||
)
|
||||
|
||||
// No response if none of the mailboxes exist.
|
||||
@@ -746,15 +747,15 @@ func testSearchMulti(t *testing.T, selected, uidonly bool) {
|
||||
tc.response("ok")
|
||||
if selected {
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Count: uint32ptr(3)},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Archive", UIDValidity: 1, UID: true, Count: uint32ptr(2)},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Count: new(uint32(3))},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Archive", UIDValidity: 1, UID: true, Count: new(uint32(2))},
|
||||
imapclient.UntaggedExists(4),
|
||||
tc.untaggedFetch(4, 8, imapclient.FetchFlags(nil)),
|
||||
)
|
||||
} else {
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Count: uint32ptr(4)},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Archive", UIDValidity: 1, UID: true, Count: uint32ptr(2)},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Count: new(uint32(4))},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Archive", UIDValidity: 1, UID: true, Count: new(uint32(2))},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -845,7 +846,7 @@ func testSearchMulti(t *testing.T, selected, uidonly bool) {
|
||||
tc.cmdf("Tag1", `Esearch In (Selected) Return (Save Min Max Count) All`)
|
||||
tc.response("ok")
|
||||
tc.xuntagged(
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Min: 5, Max: 8, Count: uint32ptr(4)},
|
||||
imapclient.UntaggedEsearch{Tag: "Tag1", Mailbox: "Inbox", UIDValidity: 1, UID: true, Min: 5, Max: 8, Count: new(uint32(4))},
|
||||
)
|
||||
|
||||
tc.cmdf("Tag1", `Esearch In (Selected) Return () $`)
|
||||
|
||||
@@ -1231,9 +1231,6 @@ func (c *conn) command() {
|
||||
panic(x)
|
||||
}
|
||||
|
||||
var sxerr syntaxError
|
||||
var uerr userError
|
||||
var serr serverError
|
||||
if isClosed(err) {
|
||||
c.log.Infox("imap command ioerror", err, logFields...)
|
||||
result = "ioerror"
|
||||
@@ -1241,7 +1238,7 @@ func (c *conn) command() {
|
||||
debug.PrintStack()
|
||||
}
|
||||
panic(err)
|
||||
} else if errors.As(err, &sxerr) {
|
||||
} else if sxerr, ok := errors.AsType[syntaxError](err); ok {
|
||||
result = "badsyntax"
|
||||
if c.ncmds == 0 {
|
||||
// Other side is likely speaking something else than IMAP, send error message and
|
||||
@@ -1269,12 +1266,12 @@ func (c *conn) command() {
|
||||
c.xflush()
|
||||
panic(fmt.Errorf("aborting connection after syntax error for command with non-sync literal: %w", errProtocol))
|
||||
}
|
||||
} else if errors.As(err, &serr) {
|
||||
} else if _, ok := errors.AsType[serverError](err); ok {
|
||||
result = "servererror"
|
||||
c.log.Errorx("imap command server error", err, logFields...)
|
||||
debug.PrintStack()
|
||||
c.xbwriteresultf("%s NO %s %v", tag, cmd, err)
|
||||
} else if errors.As(err, &uerr) {
|
||||
} else if uerr, ok := errors.AsType[userError](err); ok {
|
||||
result = "usererror"
|
||||
c.log.Debugx("imap command user error", err, logFields...)
|
||||
if uerr.code != "" {
|
||||
|
||||
@@ -42,8 +42,9 @@ func init() {
|
||||
mox.Context = ctxbg
|
||||
}
|
||||
|
||||
//go:fix inline
|
||||
func ptr[T any](v T) *T {
|
||||
return &v
|
||||
return new(v)
|
||||
}
|
||||
|
||||
func tocrlf(s string) string {
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"github.com/hanzoai/mail/config"
|
||||
"github.com/hanzoai/mail/dkim"
|
||||
"github.com/hanzoai/mail/dns"
|
||||
"github.com/hanzoai/mail/junk"
|
||||
"github.com/hanzoai/mail/mlog"
|
||||
"github.com/hanzoai/mail/mox-"
|
||||
"github.com/hanzoai/mail/moxvar"
|
||||
@@ -410,13 +409,11 @@ func writeLocalConfig(log mlog.Log, dir, ip string) (rerr error) {
|
||||
acc.AutomaticJunkFlags.NeutralMailboxRegexp = "^(inbox|neutral|postmaster|dmarc|tlsrpt|rejects)"
|
||||
acc.JunkFilter = &config.JunkFilter{
|
||||
Threshold: 0.95,
|
||||
Params: junk.Params{
|
||||
Onegrams: true,
|
||||
MaxPower: .01,
|
||||
TopWords: 10,
|
||||
IgnoreWords: .1,
|
||||
RareWords: 2,
|
||||
},
|
||||
}
|
||||
|
||||
dkimKeyBuf, err := admin.MakeDKIMEd25519Key(dns.Domain{ASCII: "localserve"}, dns.Domain{ASCII: "localhost"})
|
||||
|
||||
@@ -3478,8 +3478,7 @@ func cmdWebapi(c *cmd) {
|
||||
t := reflect.TypeFor[webapi.Methods]()
|
||||
methods := map[string]reflect.Type{}
|
||||
var ml []string
|
||||
for i := range t.NumMethod() {
|
||||
mt := t.Method(i)
|
||||
for mt := range t.Methods() {
|
||||
methods[mt.Name] = mt.Type
|
||||
ml = append(ml, mt.Name)
|
||||
}
|
||||
|
||||
+1
-2
@@ -328,8 +328,7 @@ func Get(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, domain d
|
||||
}
|
||||
|
||||
func policyFetchFailureDetails(err error) tlsrpt.FailureDetails {
|
||||
var verificationErr *tls.CertificateVerificationError
|
||||
if errors.As(err, &verificationErr) {
|
||||
if verificationErr, ok := errors.AsType[*tls.CertificateVerificationError](err); ok {
|
||||
resultType, reasonCode := tlsrpt.TLSFailureDetails(verificationErr)
|
||||
// Result: ../rfc/8460:601
|
||||
reason := string(resultType)
|
||||
|
||||
+2
-4
@@ -288,8 +288,7 @@ func deliverDirect(qlog mlog.Log, resolver dns.Resolver, dialer smtpclient.Diale
|
||||
remoteMTA = dsn.NameIP{Name: h.XString(false), IP: remoteIP}
|
||||
if result.err != nil {
|
||||
lastErr = result.err
|
||||
var cerr smtpclient.Error
|
||||
if errors.As(result.err, &cerr) {
|
||||
if cerr, ok := errors.AsType[smtpclient.Error](result.err); ok {
|
||||
if cerr.Secode == smtp.SePol7MissingReqTLS30 {
|
||||
nmissingRequireTLS++
|
||||
}
|
||||
@@ -551,8 +550,7 @@ func deliverHost(log mlog.Log, resolver dns.Resolver, dialer smtpclient.Dialer,
|
||||
hostResult = tlsrpt.MakeResult(tlsrpt.NoPolicyFound, tlsaBaseDomain)
|
||||
} else if err != nil {
|
||||
fd := tlsrpt.Details(tlsrpt.ResultTLSAInvalid, "")
|
||||
var errCode adns.ErrorCode
|
||||
if errors.As(err, &errCode) {
|
||||
if errCode, ok := errors.AsType[adns.ErrorCode](err); ok {
|
||||
fd.FailureReasonCode = fmt.Sprintf("extended-dns-error-%d-%s", errCode, strings.ReplaceAll(errCode.String(), " ", "-"))
|
||||
if errCode.IsAuthentication() {
|
||||
// Result: ../rfc/8460:580
|
||||
|
||||
+1
-2
@@ -70,13 +70,12 @@ func failMsgsTx(qlog mlog.Log, tx *bstore.Tx, msgs []*Msg, dialedIPs map[string]
|
||||
m0 := msgs[0]
|
||||
|
||||
var smtpLines []string
|
||||
var cerr smtpclient.Error
|
||||
var permanent bool
|
||||
var errmsg = err.Error()
|
||||
var code int
|
||||
var secodeOpt string
|
||||
var event webhook.OutgoingEvent
|
||||
if errors.As(err, &cerr) {
|
||||
if cerr, ok := errors.AsType[smtpclient.Error](err); ok {
|
||||
if cerr.Line != "" {
|
||||
smtpLines = append([]string{cerr.Line}, cerr.MoreLines...)
|
||||
}
|
||||
|
||||
+1
-2
@@ -54,8 +54,7 @@ func (p *parser) recover(rerr *error) {
|
||||
if !ok {
|
||||
panic(x)
|
||||
}
|
||||
var xerr Error
|
||||
if errors.As(err, &xerr) {
|
||||
if _, ok := errors.AsType[Error](err); ok {
|
||||
*rerr = err
|
||||
return
|
||||
}
|
||||
|
||||
+1
-1
@@ -326,7 +326,7 @@ Only implemented on unix systems, not Windows.
|
||||
|
||||
m := store.Message{
|
||||
Received: time.Now(),
|
||||
Flags: store.Flags{Flagged: true},
|
||||
Flagged: true,
|
||||
}
|
||||
n, err := fmt.Fprintf(f, "Date: %s\r\nSubject: mox %s available\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Transfer-Encoding: 8-bit\r\n\r\nHi!\r\n\r\nVersion %s of mox is available, this install is at %s.\r\n\r\nChanges:\r\n\r\n%s\r\n\r\nPlease report any issues at https://github.com/hanzoai/mail, thanks!\r\n\r\nCheers,\r\nmox\r\n", time.Now().Format(message.RFC5322Z), latest, latest, current, strings.ReplaceAll(cl.String(), "\n", "\r\n"))
|
||||
if err != nil {
|
||||
|
||||
@@ -94,10 +94,8 @@ func TestReputation(t *testing.T) {
|
||||
|
||||
DKIMDomains: dkimDomains,
|
||||
|
||||
Flags: store.Flags{
|
||||
Junk: junk,
|
||||
Notjunk: !junk,
|
||||
},
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -1054,8 +1054,7 @@ func command(c *conn) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var serr smtpError
|
||||
if errors.As(err, &serr) {
|
||||
if serr, ok := errors.AsType[smtpError](err); ok {
|
||||
c.xwritecodeline(serr.code, serr.secode, fmt.Sprintf("%s (%s)", serr.errmsg, mox.ReceivedID(c.cid)), serr.err)
|
||||
if serr.printStack {
|
||||
c.log.Errorx("smtp error", serr.err, slog.Int("code", serr.code), slog.String("secode", serr.secode))
|
||||
|
||||
@@ -725,7 +725,7 @@ func TestSpam(t *testing.T) {
|
||||
MsgFromOrgDomain: "example.org",
|
||||
MsgFromValidated: true,
|
||||
MsgFromValidation: store.ValidationStrict,
|
||||
Flags: store.Flags{Seen: true, Junk: true},
|
||||
Seen: true, Junk: true,
|
||||
Size: int64(len(deliverMessage)),
|
||||
}
|
||||
for range 3 {
|
||||
@@ -963,7 +963,7 @@ func TestDMARCSent(t *testing.T) {
|
||||
MailFrom: "[email protected]",
|
||||
RcptToLocalpart: smtp.Localpart("mjl"),
|
||||
RcptToDomain: "mox.example",
|
||||
Flags: store.Flags{Seen: true},
|
||||
Seen: true,
|
||||
Size: int64(len(deliverMessage)),
|
||||
}
|
||||
// We need at least 50 ham messages for the junk filter to become significant. We
|
||||
|
||||
+6
-12
@@ -355,14 +355,8 @@ var invalidReasons = map[x509.InvalidReason]string{
|
||||
// Errors from crypto/tls, including local and remote alerts, from crypto/x509,
|
||||
// and generic i/o and timeout errors are recognized.
|
||||
func TLSFailureDetails(err error) (ResultType, string) {
|
||||
var invalidErr x509.CertificateInvalidError
|
||||
var hostErr x509.HostnameError
|
||||
var unknownAuthErr x509.UnknownAuthorityError
|
||||
var rootsErr x509.SystemRootsError
|
||||
var verifyErr *tls.CertificateVerificationError
|
||||
var netErr *net.OpError
|
||||
var recordHdrErr tls.RecordHeaderError
|
||||
if errors.As(err, &invalidErr) {
|
||||
if invalidErr, ok := errors.AsType[x509.CertificateInvalidError](err); ok {
|
||||
if invalidErr.Reason == x509.Expired {
|
||||
// Result: ../rfc/8460:546
|
||||
return ResultCertificateExpired, ""
|
||||
@@ -373,16 +367,16 @@ func TLSFailureDetails(err error) (ResultType, string) {
|
||||
}
|
||||
// Result: ../rfc/8460:549
|
||||
return ResultCertificateNotTrusted, s
|
||||
} else if errors.As(err, &hostErr) {
|
||||
} else if _, ok := errors.AsType[x509.HostnameError](err); ok {
|
||||
// Result: ../rfc/8460:541
|
||||
return ResultCertificateHostMismatch, ""
|
||||
} else if errors.As(err, &unknownAuthErr) {
|
||||
} else if _, ok := errors.AsType[x509.UnknownAuthorityError](err); ok {
|
||||
// Result: ../rfc/8460:549
|
||||
return ResultCertificateNotTrusted, ""
|
||||
} else if errors.As(err, &rootsErr) {
|
||||
} else if _, ok := errors.AsType[x509.SystemRootsError](err); ok {
|
||||
// Result: ../rfc/8460:549
|
||||
return ResultCertificateNotTrusted, "no-system-roots"
|
||||
} else if errors.As(err, &verifyErr) {
|
||||
} else if _, ok := errors.AsType[*tls.CertificateVerificationError](err); ok {
|
||||
// We don't know a more specific error. ../rfc/8460:610
|
||||
// Result: ../rfc/8460:567
|
||||
return ResultValidationFailure, "unknown-go-certificate-verification-error"
|
||||
@@ -398,7 +392,7 @@ func TLSFailureDetails(err error) (ResultType, string) {
|
||||
}
|
||||
}
|
||||
return ResultValidationFailure, reasonCode
|
||||
} else if errors.As(err, &recordHdrErr) {
|
||||
} else if _, ok := errors.AsType[tls.RecordHeaderError](err); ok {
|
||||
// Like for AlertError, not a lot of details, but better than nothing.
|
||||
// Result: ../rfc/8460:567
|
||||
return ResultValidationFailure, "tls-record-header-error"
|
||||
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
|
||||
"github.com/hanzoai/mail/config"
|
||||
"github.com/hanzoai/mail/dns"
|
||||
"github.com/hanzoai/mail/junk"
|
||||
"github.com/hanzoai/mail/mlog"
|
||||
"github.com/hanzoai/mail/mox-"
|
||||
"github.com/hanzoai/mail/queue"
|
||||
@@ -498,12 +497,10 @@ func TestAccount(t *testing.T) {
|
||||
api.JunkFilterSave(ctx, nil)
|
||||
jf := config.JunkFilter{
|
||||
Threshold: 0.95,
|
||||
Params: junk.Params{
|
||||
Twograms: true,
|
||||
MaxPower: 0.1,
|
||||
TopWords: 10,
|
||||
IgnoreWords: 0.1,
|
||||
},
|
||||
}
|
||||
api.JunkFilterSave(ctx, &jf)
|
||||
|
||||
|
||||
+1
-1
@@ -1089,7 +1089,7 @@ func (s server) Send(ctx context.Context, req webapi.SendRequest) (resp webapi.S
|
||||
ModSeq: modseq,
|
||||
MailboxID: sentmb.ID,
|
||||
MailboxOrigID: sentmb.ID,
|
||||
Flags: store.Flags{Notjunk: true, Seen: true},
|
||||
Notjunk: true, Seen: true,
|
||||
Size: int64(len(msgPrefix)) + xc.Size,
|
||||
MsgPrefix: []byte(msgPrefix),
|
||||
}
|
||||
|
||||
@@ -238,12 +238,10 @@ func TestServer(t *testing.T) {
|
||||
var sb strings.Builder
|
||||
mp := multipart.NewWriter(&sb)
|
||||
fdSendReq := webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
To: []webapi.NameAddress{{Address: "mø[email protected]"}},
|
||||
// Let server assign date, message-id.
|
||||
Subject: "test",
|
||||
Text: "hi",
|
||||
},
|
||||
// Don't let server add its own user-agent.
|
||||
Headers: [][2]string{{"User-Agent", "test"}},
|
||||
}
|
||||
@@ -297,63 +295,51 @@ func TestServer(t *testing.T) {
|
||||
|
||||
// Trigger various error conditions.
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
To: []webapi.NameAddress{{Address: "[email protected]"}},
|
||||
Subject: "test",
|
||||
},
|
||||
})
|
||||
terrcode(t, err, "missingBody")
|
||||
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
From: []webapi.NameAddress{{Address: "[email protected]"}},
|
||||
To: []webapi.NameAddress{{Address: "[email protected]"}},
|
||||
Subject: "test",
|
||||
Text: "hi",
|
||||
},
|
||||
})
|
||||
terrcode(t, err, "badFrom")
|
||||
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
From: []webapi.NameAddress{{Address: "[email protected]"}, {Address: "[email protected]"}},
|
||||
To: []webapi.NameAddress{{Address: "[email protected]"}},
|
||||
Subject: "test",
|
||||
Text: "hi",
|
||||
},
|
||||
})
|
||||
terrcode(t, err, "multipleFrom")
|
||||
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{Message: webapi.Message{Subject: "test", Text: "hi"}})
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{Subject: "test", Text: "hi"})
|
||||
terrcode(t, err, "noRecipients")
|
||||
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
MessageID: "missingltgt@localhost",
|
||||
To: []webapi.NameAddress{{Address: "mø[email protected]"}},
|
||||
Subject: "test",
|
||||
Text: "hi",
|
||||
},
|
||||
})
|
||||
terrcode(t, err, "malformedMessageID")
|
||||
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
MessageID: "missingltgt@localhost",
|
||||
To: []webapi.NameAddress{{Address: "mø[email protected]"}},
|
||||
Subject: "test",
|
||||
Text: "hi",
|
||||
},
|
||||
})
|
||||
terrcode(t, err, "malformedMessageID")
|
||||
|
||||
_, err = client.Send(ctxbg, webapi.SendRequest{
|
||||
Message: webapi.Message{
|
||||
From: []webapi.NameAddress{{Address: "[email protected]"}},
|
||||
To: []webapi.NameAddress{{Address: "[email protected]"}},
|
||||
Subject: "test",
|
||||
Text: "hi",
|
||||
},
|
||||
})
|
||||
terrcode(t, err, "domainDisabled")
|
||||
|
||||
|
||||
+2
-2
@@ -457,7 +457,7 @@ func (w Webmail) MessageCompose(ctx context.Context, m ComposeMessage, mailboxID
|
||||
ModSeq: modseq,
|
||||
MailboxID: mb.ID,
|
||||
MailboxOrigID: mb.ID,
|
||||
Flags: store.Flags{Notjunk: true},
|
||||
Notjunk: true,
|
||||
Size: xc.Size,
|
||||
}
|
||||
|
||||
@@ -1123,7 +1123,7 @@ func (w Webmail) MessageSubmit(ctx context.Context, m SubmitMessage) {
|
||||
ModSeq: modseq,
|
||||
MailboxID: sentmb.ID,
|
||||
MailboxOrigID: sentmb.ID,
|
||||
Flags: store.Flags{Notjunk: true, Seen: true},
|
||||
Notjunk: true, Seen: true,
|
||||
Size: int64(len(msgPrefix)) + xc.Size,
|
||||
MsgPrefix: []byte(msgPrefix),
|
||||
}
|
||||
|
||||
+8
-8
@@ -221,16 +221,16 @@ func TestAPI(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
tcheck(t, err, "get mailboxes")
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: archive.ID, SpecialUse: store.SpecialUse{Draft: true}}) // Already set.
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{Draft: true}}) // New draft mailbox.
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{Sent: true}})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{Archive: true}})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{Trash: true}})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{Junk: true}})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: archive.ID, Draft: true}) // Already set.
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, Draft: true}) // New draft mailbox.
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, Sent: true})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, Archive: true})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, Trash: true})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, Junk: true})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{}}) // None
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{Draft: true, Sent: true, Archive: true, Trash: true, Junk: true}}) // All
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, Draft: true, Sent: true, Archive: true, Trash: true, Junk: true}) // All
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: testbox1.ID, SpecialUse: store.SpecialUse{}}) // None again.
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: sent.ID, SpecialUse: store.SpecialUse{Sent: true}}) // Sent, for sending mail later.
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: sent.ID, Sent: true}) // Sent, for sending mail later.
|
||||
tneedError(t, func() { api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: 0}) })
|
||||
|
||||
// MailboxesMarkRead
|
||||
|
||||
+8
-16
@@ -385,18 +385,18 @@ func TestView(t *testing.T) {
|
||||
var chmbrename ChangeMailboxRename
|
||||
getChanges(&chmbrename)
|
||||
tcompare(t, chmbrename, ChangeMailboxRename{
|
||||
ChangeRenameMailbox: store.ChangeRenameMailbox{MailboxID: chmbadd.Mailbox.ID, OldName: "Newbox", NewName: "Newbox2", Flags: nil, ModSeq: 13},
|
||||
MailboxID: chmbadd.Mailbox.ID, OldName: "Newbox", NewName: "Newbox2", Flags: nil, ModSeq: 13,
|
||||
})
|
||||
|
||||
// ChangeMailboxSpecialUse
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: chmbadd.Mailbox.ID, SpecialUse: store.SpecialUse{Archive: true}})
|
||||
api.MailboxSetSpecialUse(ctx, store.Mailbox{ID: chmbadd.Mailbox.ID, Archive: true})
|
||||
var chmbspecialuseOld, chmbspecialuseNew ChangeMailboxSpecialUse
|
||||
getChanges(&chmbspecialuseOld, &chmbspecialuseNew)
|
||||
tcompare(t, chmbspecialuseOld, ChangeMailboxSpecialUse{
|
||||
ChangeMailboxSpecialUse: store.ChangeMailboxSpecialUse{MailboxID: archive.ID, MailboxName: "Archive", SpecialUse: store.SpecialUse{}, ModSeq: 14},
|
||||
MailboxID: archive.ID, MailboxName: "Archive", SpecialUse: store.SpecialUse{}, ModSeq: 14,
|
||||
})
|
||||
tcompare(t, chmbspecialuseNew, ChangeMailboxSpecialUse{
|
||||
ChangeMailboxSpecialUse: store.ChangeMailboxSpecialUse{MailboxID: chmbadd.Mailbox.ID, MailboxName: "Newbox2", SpecialUse: store.SpecialUse{Archive: true}, ModSeq: 14},
|
||||
MailboxID: chmbadd.Mailbox.ID, MailboxName: "Newbox2", SpecialUse: store.SpecialUse{Archive: true}, ModSeq: 14,
|
||||
})
|
||||
|
||||
// ChangeMailboxRemove
|
||||
@@ -404,7 +404,7 @@ func TestView(t *testing.T) {
|
||||
var chmbremove ChangeMailboxRemove
|
||||
getChanges(&chmbremove)
|
||||
tcompare(t, chmbremove, ChangeMailboxRemove{
|
||||
ChangeRemoveMailbox: store.ChangeRemoveMailbox{MailboxID: chmbadd.Mailbox.ID, Name: "Newbox2", ModSeq: 15},
|
||||
MailboxID: chmbadd.Mailbox.ID, Name: "Newbox2", ModSeq: 15,
|
||||
})
|
||||
|
||||
// ChangeMsgAdd
|
||||
@@ -417,11 +417,9 @@ func TestView(t *testing.T) {
|
||||
tcompare(t, chmsgadd.MessageItems[0].Message.ID, inboxNew.ID)
|
||||
chmbcounts.Size = 0
|
||||
tcompare(t, chmbcounts, ChangeMailboxCounts{
|
||||
ChangeMailboxCounts: store.ChangeMailboxCounts{
|
||||
MailboxID: inbox.ID,
|
||||
MailboxName: inbox.Name,
|
||||
MailboxCounts: store.MailboxCounts{Total: 4, Unread: 3, Unseen: 3},
|
||||
},
|
||||
Total: 4, Unread: 3, Unseen: 3,
|
||||
})
|
||||
|
||||
// ChangeMsgFlags
|
||||
@@ -431,19 +429,15 @@ func TestView(t *testing.T) {
|
||||
getChanges(&chmsgflags, &chmbcounts, &chmbkeywords)
|
||||
tcompare(t, chmsgadd.ChangeAddUID.MailboxID, inbox.ID)
|
||||
tcompare(t, chmbkeywords, ChangeMailboxKeywords{
|
||||
ChangeMailboxKeywords: store.ChangeMailboxKeywords{
|
||||
MailboxID: inbox.ID,
|
||||
MailboxName: inbox.Name,
|
||||
Keywords: []string{`aaa`, `changelabel`, `testlabel`},
|
||||
},
|
||||
})
|
||||
chmbcounts.Size = 0
|
||||
tcompare(t, chmbcounts, ChangeMailboxCounts{
|
||||
ChangeMailboxCounts: store.ChangeMailboxCounts{
|
||||
MailboxID: inbox.ID,
|
||||
MailboxName: inbox.Name,
|
||||
MailboxCounts: store.MailboxCounts{Total: 4, Unread: 2, Unseen: 2},
|
||||
},
|
||||
Total: 4, Unread: 2, Unseen: 2,
|
||||
})
|
||||
|
||||
// ChangeMsgRemove
|
||||
@@ -454,11 +448,9 @@ func TestView(t *testing.T) {
|
||||
tcompare(t, chmsgremove.ChangeRemoveUIDs.UIDs, []store.UID{inboxMinimal.m.UID, inboxNew.m.UID})
|
||||
chmbcounts.Size = 0
|
||||
tcompare(t, chmbcounts, ChangeMailboxCounts{
|
||||
ChangeMailboxCounts: store.ChangeMailboxCounts{
|
||||
MailboxID: inbox.ID,
|
||||
MailboxName: inbox.Name,
|
||||
MailboxCounts: store.MailboxCounts{Total: 2, Unread: 1, Unseen: 1},
|
||||
},
|
||||
Total: 2, Unread: 1, Unseen: 1,
|
||||
})
|
||||
|
||||
// ChangeMsgThread
|
||||
|
||||
Reference in New Issue
Block a user