1package imapserver
2
3import (
4 "testing"
5
6 "github.com/mjl-/mox/imapclient"
7)
8
9func TestAppend(t *testing.T) {
10 defer mockUIDValidity()()
11
12 tc := start(t) // note: with switchboard because this connection stays alive unlike tc2.
13 defer tc.close()
14
15 tc2 := startNoSwitchboard(t) // note: without switchboard because this connection will break during tests.
16 defer tc2.close()
17
18 tc3 := startNoSwitchboard(t)
19 defer tc3.close()
20
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)
26
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.
30
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.close()
35 tc2.client.Login("mjl@mox.example", password0)
36 tc2.client.Select("inbox")
37
38 tc2.transactf("bad", "append inbox () \"bad time\" {1+}\r\nx") // Bad time.
39 tc2 = startNoSwitchboard(t)
40 defer tc2.close()
41 tc2.client.Login("mjl@mox.example", password0)
42 tc2.client.Select("inbox")
43
44 tc2.transactf("no", "append nobox (\\Seen) \" 1-Jan-2022 10:10:00 +0100\" {1}")
45 tc2.xcode("TRYCREATE")
46
47 tc2.transactf("ok", "append inbox (\\Seen Label1 $label2) \" 1-Jan-2022 10:10:00 +0100\" {1+}\r\nx")
48 tc2.xuntagged(imapclient.UntaggedExists(1))
49 tc2.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UID: 1})
50
51 tc.transactf("ok", "noop")
52 uid1 := imapclient.FetchUID(1)
53 flags := imapclient.FetchFlags{`\Seen`, "$label2", "label1"}
54 tc.xuntagged(imapclient.UntaggedExists(1), imapclient.UntaggedFetch{Seq: 1, Attrs: []imapclient.FetchAttr{uid1, flags}})
55 tc3.transactf("ok", "noop")
56 tc3.xuntagged() // Inbox is not selected, nothing to report.
57
58 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)")
59 tc2.xuntagged(imapclient.UntaggedExists(2))
60 tc2.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UID: 2})
61
62 tc2.transactf("ok", "append inbox (\\Seen) \" 1-Jan-2022 10:10:00 +0100\" UTF8 ({31+}\r\ncontent-type: text/plain;\n\ntest)")
63 tc2.xuntagged(imapclient.UntaggedExists(3))
64 tc2.xcodeArg(imapclient.CodeAppendUID{UIDValidity: 1, UID: 3})
65
66 // Messages that we cannot parse are marked as application/octet-stream. Perhaps
67 // the imap client knows how to deal with them.
68 tc2.transactf("ok", "uid fetch 2 body")
69 uid2 := imapclient.FetchUID(2)
70 xbs := imapclient.FetchBodystructure{
71 RespAttr: "BODY",
72 Body: imapclient.BodyTypeBasic{
73 MediaType: "APPLICATION",
74 MediaSubtype: "OCTET-STREAM",
75 BodyFields: imapclient.BodyFields{
76 Octets: 4,
77 },
78 },
79 }
80 tc2.xuntagged(imapclient.UntaggedFetch{Seq: 2, Attrs: []imapclient.FetchAttr{uid2, xbs}})
81
82 tclimit := startArgs(t, false, false, true, true, "limit")
83 defer tclimit.close()
84 tclimit.client.Login("limit@mox.example", password0)
85 tclimit.client.Select("inbox")
86 // First message of 1 byte is within limits.
87 tclimit.transactf("ok", "append inbox (\\Seen Label1 $label2) \" 1-Jan-2022 10:10:00 +0100\" {1+}\r\nx")
88 tclimit.xuntagged(imapclient.UntaggedExists(1))
89 // Second message would take account past limit.
90 tclimit.transactf("no", "append inbox (\\Seen Label1 $label2) \" 1-Jan-2022 10:10:00 +0100\" {1+}\r\nx")
91 tclimit.xcode("OVERQUOTA")
92}
93