6 "github.com/mjl-/mox/imapclient"
9func TestAppend(t *testing.T) {
10 defer mockUIDValidity()()
12 tc := start(t) // note: with switchboard because this connection stays alive unlike tc2.
15 tc2 := startNoSwitchboard(t) // note: without switchboard because this connection will break during tests.
16 defer tc2.closeNoWait()
18 tc3 := startNoSwitchboard(t)
19 defer tc3.closeNoWait()
21 tc2.client.Login("mjl@mox.example", password0)
22 tc2.client.Select("inbox")
23 tc.client.Login("mjl@mox.example", password0)
24 tc.client.Select("inbox")
25 tc3.client.Login("mjl@mox.example", password0)
27 tc2.transactf("bad", "append") // Missing params.
28 tc2.transactf("bad", `append inbox`) // Missing message.
29 tc2.transactf("bad", `append inbox "test"`) // Message must be literal.
31 // Syntax error for line ending in literal causes connection abort.
32 tc2.transactf("bad", "append inbox (\\Badflag) {1+}\r\nx") // Unknown flag.
33 tc2 = startNoSwitchboard(t)
34 defer tc2.closeNoWait()
35 tc2.client.Login("mjl@mox.example", password0)
36 tc2.client.Select("inbox")
38 tc2.transactf("bad", "append inbox () \"bad time\" {1+}\r\nx") // Bad time.
39 tc2 = startNoSwitchboard(t)
40 defer tc2.closeNoWait()
41 tc2.client.Login("mjl@mox.example", password0)
42 tc2.client.Select("inbox")
44 tc2.transactf("no", "append nobox (\\Seen) \" 1-Jan-2022 10:10:00 +0100\" {1}")
45 tc2.xcode("TRYCREATE")
47 tc2.transactf("no", "append expungebox (\\Seen) {1}")
48 tc2.xcode("TRYCREATE")
50 tc2.transactf("ok", "append inbox (\\Seen Label1 $label2) \" 1-Jan-2022 10:10:00 +0100\" {1+}\r\nx")
51 tc2.xuntagged(imapclient.UntaggedExists(1))
52 tc2.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UIDs: xparseUIDRange("1")})
54 tc.transactf("ok", "noop")
55 uid1 := imapclient.FetchUID(1)
56 flags := imapclient.FetchFlags{`\Seen`, "$label2", "label1"}
57 tc.xuntagged(imapclient.UntaggedExists(1), imapclient.UntaggedFetch{Seq: 1, Attrs: []imapclient.FetchAttr{uid1, flags}})
58 tc3.transactf("ok", "noop")
59 tc3.xuntagged() // Inbox is not selected, nothing to report.
61 tc2.transactf("ok", "append inbox (\\Seen) \" 1-Jan-2022 10:10:00 +0100\" UTF8 (~{47+}\r\ncontent-type: just completely invalid;;\r\n\r\ntest)")
62 tc2.xuntagged(imapclient.UntaggedExists(2))
63 tc2.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UIDs: xparseUIDRange("2")})
65 tc2.transactf("ok", "append inbox (\\Seen) \" 1-Jan-2022 10:10:00 +0100\" UTF8 (~{31+}\r\ncontent-type: text/plain;\n\ntest)")
66 tc2.xuntagged(imapclient.UntaggedExists(3))
67 tc2.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UIDs: xparseUIDRange("3")})
69 // Messages that we cannot parse are marked as application/octet-stream. Perhaps
70 // the imap client knows how to deal with them.
71 tc2.transactf("ok", "uid fetch 2 body")
72 uid2 := imapclient.FetchUID(2)
73 xbs := imapclient.FetchBodystructure{
75 Body: imapclient.BodyTypeBasic{
76 MediaType: "APPLICATION",
77 MediaSubtype: "OCTET-STREAM",
78 BodyFields: imapclient.BodyFields{
83 tc2.xuntagged(imapclient.UntaggedFetch{Seq: 2, Attrs: []imapclient.FetchAttr{uid2, xbs}})
85 // Multiappend with two messages.
86 tc.transactf("ok", "noop") // Flush pending untagged responses.
87 tc.transactf("ok", "append inbox {6+}\r\ntest\r\n ~{6+}\r\ntost\r\n")
88 tc.xuntagged(imapclient.UntaggedExists(5))
89 tc.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UIDs: xparseUIDRange("4:5")})
91 // Cancelled with zero-length message.
92 tc.transactf("no", "append inbox {6+}\r\ntest\r\n {0+}\r\n")
94 tclimit := startArgs(t, false, false, true, true, "limit")
96 tclimit.client.Login("limit@mox.example", password0)
97 tclimit.client.Select("inbox")
98 // First message of 1 byte is within limits.
99 tclimit.transactf("ok", "append inbox (\\Seen Label1 $label2) \" 1-Jan-2022 10:10:00 +0100\" {1+}\r\nx")
100 tclimit.xuntagged(imapclient.UntaggedExists(1))
101 // Second message would take account past limit.
102 tclimit.transactf("no", "append inbox (\\Seen Label1 $label2) \" 1-Jan-2022 10:10:00 +0100\" {1+}\r\nx")
103 tclimit.xcode("OVERQUOTA")
106 tclimit.transactf("ok", `store 1 flags (\deleted)`)
107 tclimit.transactf("ok", "expunge")
109 // Multiappend with first message within quota, and second message with sync
110 // literal causing quota error. Request should get error response immediately.
111 tclimit.transactf("no", "append inbox {1+}\r\nx {100000}")
112 tclimit.xcode("OVERQUOTA")
114 // Again, but second message now with non-sync literal, which is fully consumed by server.
115 tclimit.client.Commandf("", "append inbox {1+}\r\nx {4000+}")
116 buf := make([]byte, 4000, 4002)
120 buf = append(buf, "\r\n"...)
121 _, err := tclimit.client.Write(buf)
122 tclimit.check(err, "write append message")
123 tclimit.response("no")
124 tclimit.xcode("OVERQUOTA")