Ошибка при попытке получить сообщения электронной почты в больших папках с использованием IMAP и Twisted

Я пишу IMAP-клиент, используя последнюю версию Twisted.

У меня проблемы с использованием двух разных способов получения UID электронной почты.

Сначала я попытался использовать метод поиска таким образом:

@inlineCallbacks
def getEmailList(self):
    for f in folder_list:
        rep = yield self.examine(f)
        uids_list = yield self.search(imap4.Query(all=True), uid=True)

Это работает, но когда я пытаюсь использовать его в больших папках (содержащих более 10.000 сообщений), команда не выполняется.

Я получил ошибку вроде:

Unhandled Error
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/policies.py", line 120, in dataReceived
    self.wrappedProtocol.dataReceived(data)
  File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/basic.py", line 571, in dataReceived
    why = self.lineReceived(line)
  File "/usr/local/lib/python2.7/dist-packages/twisted/mail/imap4.py", line 2360, in lineReceived
    self._regularDispatch(line)
  File "/usr/local/lib/python2.7/dist-packages/twisted/mail/imap4.py", line 2388, in _regularDispatch
    self.dispatchCommand(tag, rest)
--- <exception caught here> ---
  File "/usr/local/lib/python2.7/dist-packages/twisted/mail/imap4.py", line 2417, in dispatchCommand
    f(tag, rest)
  File "/usr/local/lib/python2.7/dist-packages/twisted/mail/imap4.py", line 2446, in response_UNAUTH
    self._defaultHandler(tag, rest)
  File "/usr/local/lib/python2.7/dist-packages/twisted/mail/imap4.py", line 2467, in _defaultHandler
    raise IllegalServerResponse(tag + ' ' + rest)
twisted.mail.imap4.IllegalServerResponse: 1428 111429 111430 111431 111432

Так что я делаю не так? Или я могу обработать ответ сервера лучше?

Я пробовал что-то еще для прохождения этой проблемы. Вместо того, чтобы использовать метод поиска, я попытался заменить:

uids_list = yield self.search(imap4.Query(all=True), uid=True)

от

rep = yield self.fetchUID('1:*')
uids_list = set([x['UID'] for x in rep.values()])

Это тоже работает (иногда медленнее, чем предыдущий метод), но когда я пытаюсь использовать его на imap.mail.yahoo.com, происходит сбой с этой ошибкой:

[Failure instance: Traceback (failure with no frames): <class'twisted.mail.imap4.IMAP4Exception'>: [CLIENTBUG] FETCH Bad sequence in the command]

Это странно, потому что, когда я запускаю ту же команду с помощью imaplib, я не получаю никакой ошибки, поэтому я что-то пропустил?

РЕДАКТИРОВАТЬ: Я разрешаю эту проблему. Сервер IMAP4 Yahoo, похоже, имеет довольно странную реализацию. На самом деле, если мы попросим последовательность, которая не существует в папке. Например (был мой случай), если папка пуста, и мы отправляем:

FETCH 1:* (UID)

Сбой сервера с:

BAD [CLIENTBUG] FETCH Bad sequence in the command

Поэтому, чтобы обойти эту ошибку, я просто проверяю ответ на запрос:

rep = yield self.examine(f)
if rep['EXISTS'] != 0:
    rep = yield self.fetchUID('1:*')
    uids_list = set([x['UID'] for x in rep.values()])

Спасибо заранее за любой намек или ответ,

1 ответ

Это ошибка клиента. Если вы ссылаетесь на сообщение № 1, а сервер сообщил вам, что сообщений нет, то ошибка явно ваша. То же самое применимо, если сервер сообщил вам, что существует 1000 сообщений, и вы ссылаетесь на номер 1001.

Слушать EXISTS ответы. Или переключитесь на использование UID (и прослушайте UIDNEXT коды ответов).

Другие вопросы по тегам