6 "github.com/mjl-/mox/imapclient"
9func TestReplace(t *testing.T) {
10 defer mockUIDValidity()()
15 tc2 := startNoSwitchboard(t)
16 defer tc2.closeNoWait()
18 tc.client.Login("mjl@mox.example", password0)
19 tc.client.Select("inbox")
21 // Append 3 messages, remove first. Leaves msgseq 1,2 with uid 2,3.
22 tc.client.Append("inbox", makeAppend(exampleMsg), makeAppend(exampleMsg), makeAppend(exampleMsg))
23 tc.client.StoreFlagsSet("1", true, `\deleted`)
26 tc.transactf("no", "replace 2 expungebox {1}") // Mailbox no longer exists.
29 tc2.client.Login("mjl@mox.example", password0)
30 tc2.client.Select("inbox")
32 // Replace last message (msgseq 2, uid 3) in same mailbox.
33 tc.lastUntagged, tc.lastResult, tc.lastErr = tc.client.Replace("2", "INBOX", makeAppend(searchMsg))
34 tcheck(tc.t, tc.lastErr, "read imap response")
36 imapclient.UntaggedResult{Status: "OK", RespText: imapclient.RespText{Code: "APPENDUID", CodeArg: imapclient.CodeAppendUID{UIDValidity: 1, UIDs: xparseUIDRange("4")}, More: ""}},
37 imapclient.UntaggedExists(3),
38 imapclient.UntaggedExpunge(2),
40 tc.xcodeArg(imapclient.CodeHighestModSeq(8))
42 // Check that other client sees Exists and Expunge.
43 tc2.transactf("ok", "noop")
45 imapclient.UntaggedExpunge(2),
46 imapclient.UntaggedExists(2),
47 imapclient.UntaggedFetch{Seq: 2, Attrs: []imapclient.FetchAttr{imapclient.FetchUID(4), imapclient.FetchFlags(nil)}},
50 // Enable qresync, replace uid 2 (msgseq 1) to different mailbox, see that we get vanished instead of expunged.
51 tc.transactf("ok", "enable qresync")
52 tc.lastUntagged, tc.lastResult, tc.lastErr = tc.client.UIDReplace("2", "INBOX", makeAppend(searchMsg))
53 tcheck(tc.t, tc.lastErr, "read imap response")
55 imapclient.UntaggedResult{Status: "OK", RespText: imapclient.RespText{Code: "APPENDUID", CodeArg: imapclient.CodeAppendUID{UIDValidity: 1, UIDs: xparseUIDRange("5")}, More: ""}},
56 imapclient.UntaggedExists(3),
57 imapclient.UntaggedVanished{UIDs: xparseNumSet("2")},
59 tc.xcodeArg(imapclient.CodeHighestModSeq(9))
61 // Non-existent mailbox with non-synchronizing literal should consume the literal.
62 tc.transactf("no", "replace 1 bogusbox {1+}\r\nx")
65 tc.transactf("bad", "replace 1 inbox () {6+}\r\ntest\r\n ")
68func TestReplaceBigNonsyncLit(t *testing.T) {
72 tc.client.Login("mjl@mox.example", password0)
73 tc.client.Select("inbox")
75 // Adding a message >1mb with non-sync literal to non-existent mailbox should abort entire connection.
76 tc.transactf("bad", "replace 12345 inbox {2000000+}")
78 imapclient.UntaggedBye{Code: "ALERT", More: "error condition and non-synchronizing literal too big"},
83func TestReplaceQuota(t *testing.T) {
85 tc := startArgs(t, true, false, true, true, "limit")
88 tc.client.Login("limit@mox.example", password0)
89 tc.client.Select("inbox")
90 tc.client.Append("inbox", makeAppend("x"))
92 // Synchronizing literal, we get failure immediately.
93 tc.transactf("no", "replace 1 inbox {6}\r\n")
96 // Synchronizing literal to non-existent mailbox, we get failure immediately.
97 tc.transactf("no", "replace 1 badbox {6}\r\n")
100 buf := make([]byte, 4000, 4002)
104 buf = append(buf, "\r\n"...)
106 // Non-synchronizing literal. We get to write our data.
107 tc.client.Commandf("", "replace 1 inbox ~{4000+}")
108 _, err := tc.client.Write(buf)
109 tc.check(err, "write replace message")
111 tc.xcode("OVERQUOTA")
113 // Non-synchronizing literal to bad mailbox.
114 tc.client.Commandf("", "replace 1 badbox {4000+}")
115 _, err = tc.client.Write(buf)
116 tc.check(err, "write replace message")
118 tc.xcode("TRYCREATE")
121func TestReplaceExpunged(t *testing.T) {
125 tc.client.Login("mjl@mox.example", password0)
126 tc.client.Select("inbox")
127 tc.client.Append("inbox", makeAppend(exampleMsg))
129 // We start the command, but don't write data yet.
130 tc.client.Commandf("", "replace 1 inbox {4000}")
132 // Get in with second client and remove the message we are replacing.
133 tc2 := startNoSwitchboard(t)
134 defer tc2.closeNoWait()
135 tc2.client.Login("mjl@mox.example", password0)
136 tc2.client.Select("inbox")
137 tc2.client.StoreFlagsSet("1", true, `\Deleted`)
139 tc2.client.Unselect()
142 // Now continue trying to replace the message. We should get an error and an expunge.
143 tc.readprefixline("+ ")
144 buf := make([]byte, 4000, 4002)
148 buf = append(buf, "\r\n"...)
149 _, err := tc.client.Write(buf)
150 tc.check(err, "write replace message")
153 imapclient.UntaggedFetch{Seq: 1, Attrs: []imapclient.FetchAttr{imapclient.FetchUID(1), imapclient.FetchFlags{`\Deleted`}}},
154 imapclient.UntaggedExpunge(1),