fix: IMAP FETCH timeout and tagged response detection
- sendCommandWaitBytes(): check for tagged response (OK/NO/BAD) BEFORE parsing literals - Fixed detection of 'A0001 OK ...' responses that were being missed - Added debug logging on failure for easier troubleshooting - Increased FETCH timeout from 30s to 120s for large emails with attachments - Applied same 120s timeout to single UID fallback fetches
This commit is contained in:
@@ -168,6 +168,18 @@ bool ImapConnection::sendCommandWaitBytes(const QString &command, QByteArray &re
|
||||
const int lineEnd = buffer.indexOf("\r\n", pos);
|
||||
if (lineEnd < 0) break;
|
||||
const QByteArray line = buffer.mid(pos, lineEnd - pos);
|
||||
|
||||
// Check for tagged response FIRST (before literal parsing)
|
||||
// Tagged responses: "A0001 OK ...", "A0001 NO ...", "A0001 BAD ..."
|
||||
if (line.startsWith(tagBytes + QByteArrayLiteral(" OK ")) ||
|
||||
line.startsWith(tagBytes + QByteArrayLiteral(" NO ")) ||
|
||||
line.startsWith(tagBytes + QByteArrayLiteral(" BAD ")) ||
|
||||
line.startsWith(tagBytes + QByteArrayLiteral(" "))) {
|
||||
complete = true;
|
||||
loop.quit();
|
||||
break;
|
||||
}
|
||||
|
||||
const int open = line.lastIndexOf('{');
|
||||
QByteArray literalSize = open >= 0 && line.endsWith('}')
|
||||
? line.mid(open + 1, line.size() - open - 2) : QByteArray();
|
||||
@@ -183,11 +195,6 @@ bool ImapConnection::sendCommandWaitBytes(const QString &command, QByteArray &re
|
||||
if (buffer.mid(pos, 2) == QByteArrayLiteral("\r\n")) pos += 2;
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(tagBytes + QByteArrayLiteral(" "))) {
|
||||
complete = true;
|
||||
loop.quit();
|
||||
break;
|
||||
}
|
||||
pos = lineEnd + 2;
|
||||
}
|
||||
};
|
||||
@@ -212,6 +219,15 @@ bool ImapConnection::sendCommandWaitBytes(const QString &command, QByteArray &re
|
||||
m_readyReadConnection = connect(m_socket, &QSslSocket::readyRead, this, &ImapConnection::onReadyRead);
|
||||
|
||||
response = buffer;
|
||||
|
||||
// Debug: log if failed
|
||||
if (timedOut || !complete) {
|
||||
qWarning() << "IMAP command failed:" << command.left(100)
|
||||
<< "- timedOut:" << timedOut
|
||||
<< "- complete:" << complete
|
||||
<< "- response size:" << buffer.size()
|
||||
<< "- last 200 chars:" << QString::fromUtf8(buffer.right(200));
|
||||
}
|
||||
if (timedOut || !complete) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -369,7 +369,8 @@ QVector<MailItem> ImapSynchronizer::fetchMailItems(const QString& folderId, qint
|
||||
QString fetchCommand = QString("UID FETCH %1 (BODY.PEEK[] FLAGS INTERNALDATE)")
|
||||
.arg(batchList);
|
||||
QByteArray fetchResponse;
|
||||
if (!conn.sendCommandWaitBytes(fetchCommand, fetchResponse, 30000)) {
|
||||
// Increase timeout to 120s for large emails with attachments
|
||||
if (!conn.sendCommandWaitBytes(fetchCommand, fetchResponse, 120000)) {
|
||||
qWarning() << "FETCH failed for batch" << i << "(" << batch.size() << "UIDs)"
|
||||
<< "- first UID:" << batch.first() << "last UID:" << batch.last()
|
||||
<< "- response:" << QString::fromUtf8(fetchResponse).left(200);
|
||||
@@ -377,7 +378,7 @@ QVector<MailItem> ImapSynchronizer::fetchMailItems(const QString& folderId, qint
|
||||
for (qint64 uid : batch) {
|
||||
QString singleFetchCmd = QString("UID FETCH %1 (BODY.PEEK[] FLAGS INTERNALDATE)").arg(uid);
|
||||
QByteArray singleResponse;
|
||||
if (conn.sendCommandWaitBytes(singleFetchCmd, singleResponse, 30000)) {
|
||||
if (conn.sendCommandWaitBytes(singleFetchCmd, singleResponse, 120000)) {
|
||||
QVector<MailItem> singleItems = parseFetchResponseBytes(singleResponse);
|
||||
for (MailItem& item : singleItems) {
|
||||
item.setFolderId(fid);
|
||||
|
||||
Reference in New Issue
Block a user