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);
|
const int lineEnd = buffer.indexOf("\r\n", pos);
|
||||||
if (lineEnd < 0) break;
|
if (lineEnd < 0) break;
|
||||||
const QByteArray line = buffer.mid(pos, lineEnd - pos);
|
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('{');
|
const int open = line.lastIndexOf('{');
|
||||||
QByteArray literalSize = open >= 0 && line.endsWith('}')
|
QByteArray literalSize = open >= 0 && line.endsWith('}')
|
||||||
? line.mid(open + 1, line.size() - open - 2) : QByteArray();
|
? 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;
|
if (buffer.mid(pos, 2) == QByteArrayLiteral("\r\n")) pos += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (line.startsWith(tagBytes + QByteArrayLiteral(" "))) {
|
|
||||||
complete = true;
|
|
||||||
loop.quit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pos = lineEnd + 2;
|
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);
|
m_readyReadConnection = connect(m_socket, &QSslSocket::readyRead, this, &ImapConnection::onReadyRead);
|
||||||
|
|
||||||
response = buffer;
|
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;
|
if (timedOut || !complete) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,7 +369,8 @@ QVector<MailItem> ImapSynchronizer::fetchMailItems(const QString& folderId, qint
|
|||||||
QString fetchCommand = QString("UID FETCH %1 (BODY.PEEK[] FLAGS INTERNALDATE)")
|
QString fetchCommand = QString("UID FETCH %1 (BODY.PEEK[] FLAGS INTERNALDATE)")
|
||||||
.arg(batchList);
|
.arg(batchList);
|
||||||
QByteArray fetchResponse;
|
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)"
|
qWarning() << "FETCH failed for batch" << i << "(" << batch.size() << "UIDs)"
|
||||||
<< "- first UID:" << batch.first() << "last UID:" << batch.last()
|
<< "- first UID:" << batch.first() << "last UID:" << batch.last()
|
||||||
<< "- response:" << QString::fromUtf8(fetchResponse).left(200);
|
<< "- response:" << QString::fromUtf8(fetchResponse).left(200);
|
||||||
@@ -377,7 +378,7 @@ QVector<MailItem> ImapSynchronizer::fetchMailItems(const QString& folderId, qint
|
|||||||
for (qint64 uid : batch) {
|
for (qint64 uid : batch) {
|
||||||
QString singleFetchCmd = QString("UID FETCH %1 (BODY.PEEK[] FLAGS INTERNALDATE)").arg(uid);
|
QString singleFetchCmd = QString("UID FETCH %1 (BODY.PEEK[] FLAGS INTERNALDATE)").arg(uid);
|
||||||
QByteArray singleResponse;
|
QByteArray singleResponse;
|
||||||
if (conn.sendCommandWaitBytes(singleFetchCmd, singleResponse, 30000)) {
|
if (conn.sendCommandWaitBytes(singleFetchCmd, singleResponse, 120000)) {
|
||||||
QVector<MailItem> singleItems = parseFetchResponseBytes(singleResponse);
|
QVector<MailItem> singleItems = parseFetchResponseBytes(singleResponse);
|
||||||
for (MailItem& item : singleItems) {
|
for (MailItem& item : singleItems) {
|
||||||
item.setFolderId(fid);
|
item.setFolderId(fid);
|
||||||
|
|||||||
Reference in New Issue
Block a user