From 469451d5dd0a9871f7a6cde9988bab01f83e7459 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jun 2020 19:50:39 +0200 Subject: [PATCH] rework imap structure logging --- python/src/deltachat/direct_imap.py | 64 +++++++++++++++++++---------- python/src/deltachat/testplugin.py | 14 +++++-- python/tests/test_account.py | 13 ++++++ 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/python/src/deltachat/direct_imap.py b/python/src/deltachat/direct_imap.py index d4edc56f7..2da485fd4 100644 --- a/python/src/deltachat/direct_imap.py +++ b/python/src/deltachat/direct_imap.py @@ -1,6 +1,6 @@ +import sys import imaplib import pathlib -from . import Account def db_folder_attr(name): @@ -40,7 +40,6 @@ class ImapConn: if status != "OK": raise ConnectionError("Could not select {}: status={} message={}".format( foldername, status, messages)) - print("selected", foldername, messages) self.foldername = foldername try: msg_count = int(messages[0]) @@ -57,14 +56,30 @@ class ImapConn: foldername = self.account.get_config(config_name) return self.select_folder(foldername) + def list_folders(self): + res = self.connection.list() + # XXX this parsing is hairy, maybe use imapclient library + # instead of imaplib? + if res[0] != "OK": + raise ConnectionError(str(res)) + + folders = [] + for entry in res[1]: + entry = entry.decode() + i = entry.find('"') + assert entry[i + 2] == '"' + folder_name = entry[i + 3:].strip() + folders.append(folder_name) + return folders + def mark_all_read(self): -# result, data = self.connection.uid('search', None, "(UNSEEN)") + # result, data = self.connection.uid('search', None, "(UNSEEN)") result, data = self.connection.search(None, 'UnSeen') try: mails_uid = data[0].split() print("New mails") -# self.connection.store(data[0].replace(' ',','),'+FLAGS','\Seen') + # self.connection.store(data[0].replace(' ',','),'+FLAGS','\Seen') for e_id in mails_uid: self.connection.store(e_id, '+FLAGS', '\\Seen') print("marked:", e_id) @@ -75,7 +90,7 @@ class ImapConn: return False def get_unread_cnt(self): -# result, data = self.connection.uid('search', None, "(UNSEEN)") + # result, data = self.connection.uid('search', None, "(UNSEEN)") result, data = self.connection.search(None, 'UnSeen') try: mails_uid = data[0].split() @@ -91,24 +106,33 @@ class ImapConn: except IndexError: return 0 + def dump_imap_structures(self, dir, file=None): + if file is None: + file = sys.stdout + ac = self.account + acinfo = ac.logid + "-" + ac.get_config("addr") -def print_imap_structure(database, dir="."): - print_imap_structure_ac(Account(database), dir) + def log(*args, **kwargs): + kwargs["file"] = file + print(*args, **kwargs) + log("================= ACCOUNT", acinfo, "=================") + cursor = 0 + for name, val in ac.get_info().items(): + entry = "{}={}".format(name.upper(), val) + if cursor + len(entry) > 80: + log("") + cursor = 0 + log(entry, end=" ") + cursor += len(entry) + 1 + log("") -def print_imap_structure_ac(ac, dir="."): - acinfo = ac.logid + "-" + ac.get_config("addr") - print("================= ACCOUNT", acinfo, "=================") - print("----------------- CONFIG: -----------------") - print(ac.get_info()) - - for imapfolder in [INBOX, MVBOX, SENT, MVBOX_FALLBBACK]: - try: - imap = make_direct_imap(ac, imapfolder) - c = imap.connection + for imapfolder in self.list_folders(): + self.select_folder(imapfolder) + c = self.connection typ, data = c.search(None, 'ALL') c._get_tagged_response - print("-----------------", imapfolder, "-----------------") + log("-----------------", imapfolder, "-----------------") for num in data[0].split(): typ, data = c.fetch(num, '(RFC822)') body = data[0][1] @@ -120,6 +144,4 @@ def print_imap_structure_ac(ac, dir="."): path.mkdir(parents=True, exist_ok=True) file = path.joinpath(str(info).replace("b'", "").replace("'", "").replace("\\", "")) file.write_bytes(body) - print("Message", info, "saved as", file) - except Exception: - pass + log("Message", info, "saved as", file) diff --git a/python/src/deltachat/testplugin.py b/python/src/deltachat/testplugin.py index b8d4e15ac..0a08496a3 100644 --- a/python/src/deltachat/testplugin.py +++ b/python/src/deltachat/testplugin.py @@ -1,6 +1,7 @@ from __future__ import print_function import os import sys +import io import subprocess import queue import threading @@ -12,7 +13,7 @@ import tempfile import pytest import requests -from . import Account, const, direct_imap +from . import Account, const from .capi import lib from .events import FFIEventLogger, FFIEventTracker from _pytest._code import Source @@ -380,12 +381,19 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data): self._finalizers.append(bot.kill) return bot + def dump_imap_structures(self, file): + for ac in self._accounts: + conn = self.new_imap_conn(ac) + conn.dump_imap_structures(tmpdir, file=file) + am = AccountMaker() request.addfinalizer(am.finalize) yield am if request.node.rep_call.failed: - for ac in am._accounts: - direct_imap.print_imap_structure_ac(ac, tmpdir) + file = io.StringIO() + am.dump_imap_structures(file=file) + s = file.getvalue() + request.node.add_report_section("call", "imap-server-state", s) class BotProcess: diff --git a/python/tests/test_account.py b/python/tests/test_account.py index 35772fea6..1ca6a15b3 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -1,5 +1,6 @@ from __future__ import print_function import pytest +import io import os import queue import time @@ -1738,6 +1739,18 @@ class TestOnlineConfigureFails: class TestDirectImap: + def test_basic_imap(self, acfactory): + ac1, ac2 = acfactory.get_two_online_accounts() + imap1 = acfactory.new_imap_conn(ac1) + res = imap1.list_folders() + for folder_name in res: + imap1.select_folder(folder_name) + + file = io.StringIO() + acfactory.dump_imap_structures(file=file) + out = file.getvalue().lower() + assert "arch" in out + @pytest.mark.ignored @pytest.mark.parametrize('i', range(30)) def test_mark_read_on_server(self, acfactory, lp, i):