Repository: jgosmann/dmarc-metrics-exporter (language: python)

Issue:
Folder autocreation broken
Hello,

I tried to use the tool with Office365. The mailbox has the required folders: INBOX, Archive, Invalid.
However I got this error at startup:

```
Error during IMAP queue polling.
Traceback (most recent call last):
  File "/tmp/dmarc-metrics-exporter/dmarc_metrics_exporter/imap_queue.py", line 55, in _consume
    await client.create_if_not_exists(folder)
  File "/tmp/dmarc-metrics-exporter/dmarc_metrics_exporter/imap_queue.py", line 151, in create_if_not_exists
    await self._check("CREATE", self._client.create(mailbox_name))
  File "/tmp/dmarc-metrics-exporter/dmarc_metrics_exporter/imap_queue.py", line 102, in _check
    raise ImportError(command, res, data)
ImportError: ('CREATE', 'NO', [b'Mailbox already exists.'])
```

I tried to debug it by adding these 2 lines in [`create_if_not_exists` method](https://github.com/jgosmann/dmarc-metrics-exporter/blob/main/dmarc_metrics_exporter/imap_queue.py#L141):
```
print(mailbox_name, "--->", await self._client.list(".", mailbox_name))
print(mailbox_name, "--->", await self._client.select(mailbox_name))
```

I got:
```
INBOX ---> Response(result='OK', lines=[b'LIST completed.'])
INBOX ---> Response(result='OK', lines=[b'614 EXISTS', b'0 RECENT', b'FLAGS (\\Seen \\Answered \\Flagged \\Deleted \\Draft $MDNSent)', b'OK [PERMANENTFLAGS (\\Seen \\Answered \\Flagged \\Deleted \\Draft $MDNSent)] Permanent flags', b'OK [UNSEEN 1] Is the first unseen message', b'OK [UIDVALIDITY 14] UIDVALIDITY value', b'OK [UIDNEXT 634] The next unique identifier value', b'[READ-WRITE] SELECT completed.'])
```

The method used to check if a folder exists seems to be broken
Any idea?

Thanks
Wrong links on dmarc-metrics-exporter pyp.org module page
Hi,

The Homepage and Repository links on the pypi.org page currently point to the doveseed repository instead of this one.



Discussion / hints:

Classic copy&paste mistake, thanks for letting me know.

Fix patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index db59902..c731e68 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -21,6 +21,7 @@ repos:
   hooks:
   - id: pylint
     additional_dependencies:
+    - aioimaplib==0.9.0
     - aiohttp==3.7.3
     - dataclasses-serialization==1.3.1
     - prometheus_client==0.11
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 34eb0cc..2d27ff4 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,16 @@ All notable changes to this project will be documented in this file.
 The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_,
 and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
 
+[0.4.2] - unreleased
+--------------------
+
+Fixed
+^^^^^
+
+* Make detection of required folders more robust. Fixes issues with Office365.
+  (`#15 <https://github.com/jgosmann/dmarc-metrics-exporter/issues/15>`_,
+  `#16 <https://github.com/jgosmann/dmarc-metrics-exporter/pull/16>`_)
+
 
 [0.4.1] - 2021-11-13
 --------------------
diff --git a/dmarc_metrics_exporter/imap_queue.py b/dmarc_metrics_exporter/imap_queue.py
index b46568f..6c0bc56 100755
--- a/dmarc_metrics_exporter/imap_queue.py
+++ b/dmarc_metrics_exporter/imap_queue.py
@@ -99,7 +99,7 @@ async def __aexit__(self, exc_type, exc, traceback):
     async def _check(self, command: str, awaitable: Awaitable[Tuple[str, Any]]) -> Any:
         res, data = await asyncio.wait_for(awaitable, self.timeout_seconds)
         if res not in ("OK", b"OK"):
-            raise ImportError(command, res, data)
+            raise ImapServerError(command, res, data)
         return data
 
     async def select(self, folder: str = "INBOX") -> int:
@@ -139,12 +139,7 @@ async def fetch(
             pass
 
     async def create_if_not_exists(self, mailbox_name: str):
-        mailboxes = [
-            line
-            for line in await self._check("LIST", self._client.list(".", mailbox_name))
-            if line != b"LIST completed."
-        ]
-        if len(mailboxes) == 0:
+        if (await self._client.select(mailbox_name)).result != "OK":
             await self._check("CREATE", self._client.create(mailbox_name))
 
     async def uid_move(self, uid: int, destination: str):


Test patch:
diff --git a/dmarc_metrics_exporter/tests/test_imap_queue.py b/dmarc_metrics_exporter/tests/test_imap_queue.py
index 49bb1d7..c6b1ef4 100644
--- a/dmarc_metrics_exporter/tests/test_imap_queue.py
+++ b/dmarc_metrics_exporter/tests/test_imap_queue.py
@@ -3,7 +3,7 @@
 
 import pytest
 
-from dmarc_metrics_exporter.imap_queue import ImapClient, ImapQueue
+from dmarc_metrics_exporter.imap_queue import ImapClient, ImapQueue, ImapServerError
 
 from .conftest import send_email, try_until_success, verify_email_delivered
 
@@ -139,3 +139,13 @@ async def handler(queue_msg: EmailMessage, is_done=is_done):
     finally:
         if queue is not None:
             await queue.stop_consumer()
+
+
+@pytest.mark.asyncio
+async def test_create_if_not_exists(greenmail):
+    async with ImapClient(greenmail.imap) as client:
+        await client.create_if_not_exists("MyRandomDir")
+
+        assert (await client.select("MyRandomDir")) == 0
+        with pytest.raises(ImapServerError):
+            await client.select("MyRandomDirNotExist")