MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 95.2% 199 / 0 / 209
Functions: 95.5% 21 / 0 / 22
Branches: 83.2% 154 / 0 / 185

service/ImapBodyFetch.cpp
Line Branch Exec Source
1 #include "ImapBodyFetch.h"
2
3 #include "ImapCommandTable.h"
4 #include "ImapPushSession.h"
5
6 #include <QLoggingCategory>
7 #include <QSettings>
8 #include <QTimer>
9
10 #include <algorithm>
11 #include <utility>
12
13 Q_DECLARE_LOGGING_CATEGORY(lcImap)
14
15 1401 ImapBodyFetch::ImapBodyFetch(QObject *owner, ImapCommandTable &commands,
16 ImapPushSession &push, const State &state,
17 1401 SelectedMailbox mailbox, Deps deps)
18 1401 : m_owner(owner), m_commands(commands), m_push(push), m_state(state),
19 1401 m_mailbox(mailbox), m_deps(std::move(deps)) {}
20
21 4 void ImapBodyFetch::fetchBody(qint64 uid) {
22 4 const qint64 acceptedBytes = configuredMaxMessageBytes();
23 4 fetchBodyWithLimits(0, uid, acceptedBytes, acceptedBytes + 1);
24 4 }
25
26 34 void ImapBodyFetch::fetchBody(qint64 uid, qint64 maxBytes) {
27
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 5 taken 33 times.
34 if (maxBytes <= 0) {
28 1 fetchBody(uid);
29 1 return;
30 }
31 33 const qint64 acceptedBytes = qMin(maxBytes, ImapService::MAX_LITERAL_SIZE);
32 33 fetchBodyWithLimits(0, uid, acceptedBytes, acceptedBytes);
33 }
34
35 3 void ImapBodyFetch::requestBody(quint64 requestId, qint64 uid) {
36 3 const qint64 acceptedBytes = configuredMaxMessageBytes();
37 3 fetchBodyWithLimits(requestId, uid, acceptedBytes, acceptedBytes + 1);
38 3 }
39
40 202 qint64 ImapBodyFetch::configuredMaxMessageBytes() {
41
1/1
✓ Branch 2 → 3 taken 202 times.
202 QSettings settings;
42 202 bool ok = false;
43 const int configured =
44
1/1
✓ Branch 8 → 9 taken 202 times.
606 settings.value(QStringLiteral("network/maxMessageSizeMiB"),
45 ImapService::DefaultMaxMessageSizeMiB)
46
1/1
✓ Branch 9 → 10 taken 202 times.
202 .toInt(&ok);
47 const int sizeMiB =
48
2/3
✓ Branch 14 → 15 taken 202 times.
✗ Branch 14 → 17 not taken.
✓ Branch 15 → 16 taken 202 times.
202 ok ? qBound(ImapService::MinMaxMessageSizeMiB, configured, ImapService::MaxMaxMessageSizeMiB)
49 202 : ImapService::DefaultMaxMessageSizeMiB;
50 202 return static_cast<qint64>(sizeMiB) * 1024 * 1024;
51 202 }
52
53 42 void ImapBodyFetch::fetchBodyWithLimits(quint64 requestId, qint64 uid,
54 qint64 acceptedBytes,
55 qint64 requestedBytes) {
56
2/2
✓ Branch 2 → 3 taken 10 times.
✓ Branch 2 → 23 taken 32 times.
42 if (m_state != State::Selected) {
57
5/5
✓ Branch 3 → 4 taken 10 times.
✓ Branch 7 → 8 taken 10 times.
✓ Branch 8 → 9 taken 10 times.
✓ Branch 12 → 5 taken 10 times.
✓ Branch 12 → 13 taken 10 times.
20 qCWarning(lcImap) << "Cannot fetch body: no folder selected";
58
2/2
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 22 taken 9 times.
10 if (requestId > 0) {
59 2 m_deps.bodyRequestCompleted(
60
1/7
✓ Branch 18 → 19 taken 1 time.
✗ Branch 49 → 50 not taken.
✗ Branch 49 → 51 not taken.
✗ Branch 55 → 56 not taken.
✗ Branch 55 → 57 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 58 → 60 not taken.
2 BodyResult{requestId, m_mailbox.selectedFolder, uid, BodyOutcome::Failed, {},
61 1 QStringLiteral("No folder selected"), 0});
62 }
63 10 return;
64 }
65
1/2
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 27 taken 32 times.
32 if (!m_push.probeBeforeUse("FETCH_BODY")) {
66 ✗ completeUndispatched(requestId, m_mailbox.selectedFolder, uid);
67 ✗ return;
68 }
69
2/2
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 33 taken 31 times.
32 if (m_commands.hasStatefulCommandInFlight()) {
70
1/1
✓ Branch 30 → 31 taken 1 time.
1 park(requestId, m_mailbox.selectedFolder, uid,
71
1/1
✓ Branch 29 → 30 taken 1 time.
1 [this, requestId, uid, acceptedBytes, requestedBytes]() {
72 1 fetchBodyWithLimits(requestId, uid, acceptedBytes, requestedBytes);
73 1 });
74 1 return;
75 }
76
77 31 m_activeBodyRequestId = requestId;
78 31 m_activeBodyRequestFolder = m_mailbox.selectedFolder;
79 31 m_activeBodyFetchLimit = acceptedBytes;
80 31 m_activeBodyFetchRequestBytes = requestedBytes;
81 31 m_activeBodyFetchUid = uid;
82 31 m_bodyFetchRequiresSelect = false;
83 31 m_bodyFetchRetried = false;
84
3/3
✓ Branch 34 → 35 taken 31 times.
✓ Branch 35 → 36 taken 31 times.
✓ Branch 36 → 37 taken 31 times.
31 m_commands.sendCommand("FETCH_BODY", buildFetchBodyCommand(uid, requestedBytes));
85 }
86
87 // T-205: Pipeline SELECT + FETCH BODY — sends both commands back-to-back
88 // so the body connection doesn't need to wait for SELECT OK before fetching.
89 3 void ImapBodyFetch::selectAndFetchBody(const QString &folderPath, qint64 uid) {
90 3 requestBodyInFolder(0, folderPath, uid);
91 3 }
92
93 19 void ImapBodyFetch::requestBodyInFolder(quint64 requestId,
94 const QString &folderPath, qint64 uid) {
95
4/4
✓ Branch 2 → 3 taken 14 times.
✓ Branch 2 → 24 taken 5 times.
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 24 taken 12 times.
19 if (m_state != State::Authenticated && m_state != State::Selected) {
96
5/5
✓ Branch 4 → 5 taken 2 times.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 13 → 6 taken 2 times.
✓ Branch 13 → 14 taken 2 times.
4 qCWarning(lcImap) << "Cannot selectAndFetchBody: not authenticated";
97
2/2
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 23 taken 1 time.
2 if (requestId > 0) {
98 2 m_deps.bodyRequestCompleted(
99
1/7
✓ Branch 19 → 20 taken 1 time.
✗ Branch 115 → 116 not taken.
✗ Branch 115 → 117 not taken.
✗ Branch 121 → 122 not taken.
✗ Branch 121 → 123 not taken.
✗ Branch 124 → 125 not taken.
✗ Branch 124 → 126 not taken.
2 BodyResult{requestId, folderPath, uid, BodyOutcome::Failed, {},
100 1 QStringLiteral("Not authenticated"), 0});
101 }
102 12 return;
103 }
104
3/3
✓ Branch 24 → 25 taken 17 times.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 25 → 28 taken 16 times.
17 if (!m_push.probeBeforeUse("FETCH_BODY")) {
105
1/1
✓ Branch 26 → 27 taken 1 time.
1 completeUndispatched(requestId, folderPath, uid);
106 1 return;
107 }
108
3/3
✓ Branch 28 → 29 taken 16 times.
✓ Branch 29 → 30 taken 3 times.
✓ Branch 29 → 36 taken 13 times.
16 if (m_commands.hasStatefulCommandInFlight()) {
109
2/4
✓ Branch 31 → 32 taken 3 times.
✓ Branch 32 → 33 taken 3 times.
✗ Branch 132 → 133 not taken.
✗ Branch 132 → 134 not taken.
3 park(requestId, folderPath, uid, [this, requestId, folderPath, uid]() {
110 1 requestBodyInFolder(requestId, folderPath, uid);
111 1 });
112 3 return;
113 }
114
115 13 m_activeBodyRequestId = requestId;
116 13 m_activeBodyRequestFolder = folderPath;
117
1/1
✓ Branch 37 → 38 taken 13 times.
13 const qint64 acceptedBytes = configuredMaxMessageBytes();
118 13 const qint64 requestedBytes = acceptedBytes + 1;
119 13 m_activeBodyFetchLimit = acceptedBytes;
120 13 m_activeBodyFetchRequestBytes = requestedBytes;
121 13 m_activeBodyFetchUid = uid;
122 13 m_bodyFetchRetried = false;
123
124 // P90.9: reuse an already selected mailbox. One initial SELECT per
125 // folder per connection; folder switches on this connection (moves,
126 // other folders) or reconnects invalidate m_mailbox.selectedFolder and force a
127 // fresh SELECT. The mailbox-selected notification still fires so the
128 // transport trace keeps its selection phase for every request.
129
6/6
✓ Branch 38 → 39 taken 8 times.
✓ Branch 38 → 42 taken 5 times.
✓ Branch 40 → 41 taken 6 times.
✓ Branch 40 → 42 taken 2 times.
✓ Branch 43 → 44 taken 6 times.
✓ Branch 43 → 68 taken 7 times.
13 if (m_state == State::Selected && m_mailbox.selectedFolder == folderPath) {
130 6 m_bodyFetchRequiresSelect = false;
131
1/1
✓ Branch 44 → 45 taken 6 times.
6 m_deps.bodyMailboxSelected(requestId, true);
132
3/3
✓ Branch 45 → 46 taken 6 times.
✓ Branch 46 → 47 taken 6 times.
✓ Branch 47 → 48 taken 6 times.
6 m_commands.sendCommand("FETCH_BODY", buildFetchBodyCommand(uid, requestedBytes));
133
6/6
✓ Branch 51 → 52 taken 6 times.
✓ Branch 55 → 56 taken 6 times.
✓ Branch 56 → 57 taken 6 times.
✓ Branch 57 → 58 taken 6 times.
✓ Branch 66 → 53 taken 6 times.
✓ Branch 66 → 67 taken 6 times.
12 qCInfo(lcImap) << "P90.9: FETCH_BODY on selected mailbox" << folderPath
134
5/5
✓ Branch 58 → 59 taken 6 times.
✓ Branch 59 → 60 taken 6 times.
✓ Branch 60 → 61 taken 6 times.
✓ Branch 61 → 62 taken 6 times.
✓ Branch 62 → 63 taken 6 times.
6 << "UID" << uid << "limit" << acceptedBytes << "bytes";
135 6 return;
136 }
137
138 7 ImapPendingCommand select; // Bug 34: selected only on SELECT OK
139 7 select.selectFolder = folderPath;
140 7 m_mailbox.messageCount = 0;
141 7 m_mailbox.uidValidity = 0;
142 7 m_mailbox.highestModseq = 0;
143 7 m_bodyFetchRequiresSelect = true;
144
145 // Send both commands back-to-back (pipelining)
146
5/5
✓ Branch 71 → 72 taken 7 times.
✓ Branch 73 → 74 taken 7 times.
✓ Branch 74 → 75 taken 7 times.
✓ Branch 75 → 76 taken 7 times.
✓ Branch 76 → 77 taken 7 times.
14 m_commands.sendCommand("SELECT", QString("SELECT %1").arg(ImapService::quoteMailboxName(folderPath)),
147 7 std::move(select));
148
3/3
✓ Branch 82 → 83 taken 7 times.
✓ Branch 83 → 84 taken 7 times.
✓ Branch 84 → 85 taken 7 times.
7 m_commands.sendCommand("FETCH_BODY", buildFetchBodyCommand(uid, requestedBytes));
149
150
6/6
✓ Branch 88 → 89 taken 7 times.
✓ Branch 92 → 93 taken 7 times.
✓ Branch 93 → 94 taken 7 times.
✓ Branch 94 → 95 taken 7 times.
✓ Branch 103 → 90 taken 7 times.
✓ Branch 103 → 104 taken 7 times.
14 qCInfo(lcImap) << "T-205: Pipelined SELECT + FETCH_BODY for" << folderPath
151
5/5
✓ Branch 95 → 96 taken 7 times.
✓ Branch 96 → 97 taken 7 times.
✓ Branch 97 → 98 taken 7 times.
✓ Branch 98 → 99 taken 7 times.
✓ Branch 99 → 100 taken 7 times.
7 << "UID" << uid << "limit" << acceptedBytes << "bytes";
152 7 }
153
154 2 void ImapBodyFetch::invalidateBodyFetch() {
155
1/1
✓ Branch 5 → 6 taken 2 times.
4 m_commands.eraseType(QStringLiteral("FETCH_BODY"));
156 2 m_activeBodyFetchUid = -1;
157 2 m_activeBodyRequestId = 0;
158 2 m_activeBodyRequestFolder.clear();
159 2 m_activeBodyFetchLimit = 0;
160 2 m_activeBodyFetchRequestBytes = 0;
161 2 m_bodyFetchRequiresSelect = false;
162 2 m_commands.refreshCommandTimeout();
163 2 m_commands.refreshCommandDeadline();
164
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 14 not taken.
2 if (!m_commands.hasTimeoutTrackedCommandInFlight())
165 2 m_commands.resetCommandAccumulators();
166 2 }
167
168 4 void ImapBodyFetch::park(quint64 requestId, const QString &folderPath, qint64 uid,
169 std::function<void()> run) {
170
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 8 taken 3 times.
4 if (requestId == 0) {
171
1/1
✓ Branch 5 → 6 taken 1 time.
1 m_commands.enqueueSerializedCommand(std::move(run));
172 1 return;
173 }
174 3 const quint64 ticket = ++m_nextParkTicket;
175 3 m_parkedRequests.append({ticket, requestId, folderPath, uid});
176
2/2
✓ Branch 13 → 14 taken 3 times.
✓ Branch 14 → 15 taken 3 times.
3 m_commands.enqueueSerializedCommand([this, ticket, run = std::move(run)]() {
177
3/3
✓ Branch 2 → 3 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 4 → 5 taken 1 time.
1 const auto it = std::find_if(m_parkedRequests.begin(), m_parkedRequests.end(),
178 1 [ticket](const ParkedRequest &parked) { return parked.ticket == ticket; });
179
2/3
✓ Branch 5 → 6 taken 1 time.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1 time.
1 if (it == m_parkedRequests.end())
180 ✗ return; // already completed by cancelParkedRequests()
181
1/1
✓ Branch 10 → 11 taken 1 time.
1 m_parkedRequests.erase(it);
182
1/1
✓ Branch 11 → 12 taken 1 time.
1 run();
183 });
184 3 }
185
186 2482 void ImapBodyFetch::cancelParkedRequests() {
187 2482 const QList<ParkedRequest> parked = std::exchange(m_parkedRequests, {});
188
2/2
✓ Branch 11 → 7 taken 2 times.
✓ Branch 11 → 12 taken 2482 times.
2484 for (const ParkedRequest &request : parked)
189
1/1
✓ Branch 8 → 9 taken 2 times.
2 completeUndispatched(request.requestId, request.folderPath, request.uid);
190 2482 }
191
192 // S92.5.2: the connection failed before the FETCH was written.
193 3 void ImapBodyFetch::completeUndispatched(quint64 requestId, const QString &folderPath,
194 qint64 uid) {
195
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 if (requestId == 0)
196 ✗ return;
197 3 BodyResult result{requestId, folderPath, uid, BodyOutcome::Cancelled, {},
198 6 QStringLiteral("Connection lost before dispatch"), 0};
199 3 result.dispatched = false;
200
1/1
✓ Branch 9 → 10 taken 3 times.
3 m_deps.bodyRequestCompleted(result);
201 3 }
202
203 2455 void ImapBodyFetch::completeBodyRequest(BodyOutcome outcome,
204 QByteArray bytes,
205 const QString &error, qint64 maxBytes) {
206
2/2
✓ Branch 2 → 3 taken 2438 times.
✓ Branch 2 → 4 taken 17 times.
2455 if (m_activeBodyRequestId == 0)
207 2438 return;
208
209 17 BodyResult result;
210 17 result.requestId = m_activeBodyRequestId;
211 17 result.folderPath = m_activeBodyRequestFolder;
212 17 result.uid = m_activeBodyFetchUid;
213 17 result.outcome = outcome;
214 17 result.bytes = std::move(bytes);
215 17 result.error = error;
216 17 result.maxBytes = maxBytes;
217 17 m_activeBodyRequestId = 0;
218 17 m_activeBodyRequestFolder.clear();
219 #ifdef MAILJD_E2E_TESTING
220
4/4
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 13 taken 15 times.
✓ Branch 15 → 16 taken 16 times.
✓ Branch 15 → 33 taken 1 time.
19 if (m_e2eBodyCompletionUid <= 0 ||
221
3/4
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 14 not taken.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 1 time.
2 (result.uid == m_e2eBodyCompletionUid && result.folderPath == m_e2eBodyCompletionFolder)) {
222 16 m_e2eBodyCompletionUid = 0;
223 16 m_e2eBodyCompletionFolder.clear();
224 16 const int delayMs = std::exchange(m_e2eNextBodyCompletionDelayMs, 0);
225
2/2
✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 28 taken 15 times.
16 if (std::exchange(m_e2eFailNextBodyCompletion, false)) {
226 1 result.outcome = BodyOutcome::Failed;
227
1/1
✓ Branch 20 → 21 taken 1 time.
1 result.bytes.clear();
228 1 result.error = QStringLiteral("Body fetch failed");
229 }
230
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 33 taken 16 times.
16 if (delayMs > 0) {
231 ✗ QTimer::singleShot(delayMs, m_owner,
232 ✗ [this, result]() { m_deps.bodyRequestCompleted(result); });
233 ✗ return;
234 }
235 }
236 #endif
237
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 33 → 34 taken 17 times.
17 m_deps.bodyRequestCompleted(result);
238 17 }
239
240 #ifdef MAILJD_E2E_TESTING
241 1 void ImapBodyFetch::setNextBodyCompletionForE2e(int delayMs, bool fail,
242 const QString &folderPath, qint64 uid) {
243 1 m_e2eBodyCompletionFolder = folderPath;
244 1 m_e2eBodyCompletionUid = uid;
245
1/1
✓ Branch 3 → 4 taken 1 time.
1 m_e2eNextBodyCompletionDelayMs = qBound(0, delayMs, 5000);
246 1 m_e2eFailNextBodyCompletion = fail;
247 1 }
248 #endif
249
250 51 QString ImapBodyFetch::buildFetchBodyCommand(qint64 uid, qint64 maxBytes) {
251
2/2
✓ Branch 2 → 3 taken 49 times.
✓ Branch 2 → 14 taken 2 times.
51 if (maxBytes > 0) {
252 98 return QStringLiteral("UID FETCH %1 (UID BODY.PEEK[]<0.%2>)")
253
1/1
✓ Branch 7 → 8 taken 49 times.
147 .arg(uid)
254
1/1
✓ Branch 9 → 10 taken 49 times.
49 .arg(maxBytes);
255 }
256
1/1
✓ Branch 18 → 19 taken 2 times.
4 return QStringLiteral("UID FETCH %1 (UID BODY.PEEK[])").arg(uid);
257 }
258 42 void ImapBodyFetch::handleTaggedFetchBody(const TaggedResponse &response) {
259 // A UID that arrived after this connection's last mailbox sync is
260 // resolved against the old view: Dovecot reports the new EXISTS with
261 // the response but answers OK without data. The view now includes the
262 // message, so an empty OK is retried once before it counts as failed.
263
4/4
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 10 taken 38 times.
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 10 taken 1 time.
84 if (response.status == "OK" && m_activeBodyRequestId > 0 && !m_bodyFetchRetried &&
264
5/8
✓ Branch 3 → 4 taken 42 times.
✗ Branch 3 → 10 not taken.
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 10 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 33 taken 39 times.
84 m_activeBodyFetchUid > 0 && m_mailbox.selectedFolder == m_activeBodyRequestFolder) {
265 3 m_bodyFetchRetried = true;
266
6/6
✓ Branch 12 → 13 taken 3 times.
✓ Branch 16 → 17 taken 3 times.
✓ Branch 17 → 18 taken 3 times.
✓ Branch 18 → 19 taken 3 times.
✓ Branch 25 → 14 taken 3 times.
✓ Branch 25 → 26 taken 3 times.
6 qCInfo(lcImap) << "Empty body response for UID" << m_activeBodyFetchUid
267
3/3
✓ Branch 19 → 20 taken 3 times.
✓ Branch 20 → 21 taken 3 times.
✓ Branch 21 → 22 taken 3 times.
3 << "in" << m_mailbox.selectedFolder << "- fetching once more";
268
3/3
✓ Branch 26 → 27 taken 3 times.
✓ Branch 27 → 28 taken 3 times.
✓ Branch 28 → 29 taken 3 times.
3 m_commands.sendCommand("FETCH_BODY", buildFetchBodyCommand(m_activeBodyFetchUid,
269 m_activeBodyFetchRequestBytes));
270 3 return;
271 }
272
1/2
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 44 taken 39 times.
39 if (response.status != "OK") {
273 ✗ completeBodyRequest(BodyOutcome::Failed, {},
274 ✗ QStringLiteral("Body fetch failed"));
275
2/2
✓ Branch 44 → 45 taken 1 time.
✓ Branch 44 → 54 taken 38 times.
39 } else if (m_activeBodyRequestId > 0) {
276
1/1
✓ Branch 49 → 50 taken 1 time.
1 completeBodyRequest(BodyOutcome::Failed, {},
277 2 QStringLiteral("Body response was empty"));
278 }
279 39 m_activeBodyFetchUid = -1;
280 39 m_activeBodyFetchLimit = 0;
281 39 m_activeBodyFetchRequestBytes = 0;
282 39 m_bodyFetchRequiresSelect = false;
283
1/2
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 60 taken 39 times.
39 if (response.status != "OK") {
284 ✗ m_deps.errorOccurred("FETCH body failed: " + response.message);
285 }
286 // Body is emitted in handleUntagged when the data arrives
287 // Drain deferred commands (e.g. next body fetch in search mode)
288
2/2
✓ Branch 62 → 63 taken 1 time.
✓ Branch 62 → 64 taken 38 times.
39 if (!m_commands.deferredCommands().isEmpty()) {
289 1 m_commands.runNextDeferredCommand();
290 } else {
291 // No deferred commands — restart IDLE if possible
292 // (STORE handler restarts IDLE for markSeen; this covers already-seen mails)
293 38 m_push.restartPush();
294 }
295 }
296
297 2482 void ImapBodyFetch::resetActiveRequest() {
298 2482 m_activeBodyFetchUid = -1;
299 2482 m_activeBodyRequestId = 0;
300 2482 m_activeBodyRequestFolder.clear();
301 2482 m_activeBodyFetchLimit = 0;
302 2482 m_activeBodyFetchRequestBytes = 0;
303 2482 m_bodyFetchRequiresSelect = false;
304 2482 }
305