fix(email): resolve type errors in imap_client with proper type narrowing and ignores
linuztx committed
Mar 15, 2026 at 12:32 UTC
208150ad25da4b032924343819f6f23cfca56781
1 file changed
+11
-9
plugins/_email_integration/helpers/imap_client.py
+11
-9
@@ -50,7 +50,7 @@ async def connect_imap(
50
51
def _sync():
52
client = IMAPClient(server, port=port, ssl=ssl, timeout=timeout)
53
- client._imap._maxline = 100000
53
+ client._imap._maxline = 100000 # type: ignore[attr-defined]
54
client.login(username, password)
55
return client
56
@@ -85,7 +85,7 @@ async def fetch_new(
85
try:
86
return client.gmail_search("category:primary is:unread")
87
except Exception:
88
- return client.search(["UNSEEN"])
88
+ return client.search(["UNSEEN"]) # type: ignore[arg-type]
89
90
msg_ids = await loop.run_in_executor(None, _search)
91
if not msg_ids:
@@ -127,7 +127,7 @@ async def get_highest_uid(client: IMAPClient) -> int:
127
128
def _search():
129
client.select_folder("INBOX")
130
- uids = client.search(["ALL"])
130
+ uids = client.search(["ALL"]) # type: ignore[arg-type]
131
return max(uids) if uids else 0
132
133
return await loop.run_in_executor(None, _search)
@@ -152,7 +152,7 @@ async def _fetch_single(
152
if not email_data:
153
return None
154
155
- email_msg = email.message_from_bytes(email_data)
155
+ email_msg = email.message_from_bytes(email_data) # type: ignore[arg-type]
156
157
sender = _decode_header(email_msg.get("From", ""))
158
if _is_noreply(sender):
@@ -275,7 +275,7 @@ async def _parse_body(
275
if filename:
276
filename = _decode_header(filename)
277
content = part.get_payload(decode=True)
278
- if content:
278
+ if isinstance(content, bytes):
279
path = await _save_attachment(filename, content, download_folder)
280
attachments.append(path)
281
cid = part.get("Content-ID")
@@ -284,17 +284,19 @@ async def _parse_body(
284
285
elif content_type == "text/plain" and not body:
286
charset = part.get_content_charset() or "utf-8"
287
- body = part.get_payload(decode=True).decode(charset, errors="ignore")
287
+ payload = part.get_payload(decode=True)
288
+ body = payload.decode(charset, errors="ignore") if isinstance(payload, bytes) else ""
289
290
elif content_type == "text/html" and not body:
291
charset = part.get_content_charset() or "utf-8"
291
- html = part.get_payload(decode=True).decode(charset, errors="ignore")
292
+ payload = part.get_payload(decode=True)
293
+ html = payload.decode(charset, errors="ignore") if isinstance(payload, bytes) else ""
294
body = _html_to_text(html, cid_map)
295
else:
296
content_type = email_msg.get_content_type()
297
charset = email_msg.get_content_charset() or "utf-8"
298
content = email_msg.get_payload(decode=True)
297
- if content:
299
+ if isinstance(content, bytes):
300
if content_type == "text/html":
301
body = _html_to_text(content.decode(charset, errors="ignore"))
302
else:
@@ -328,7 +330,7 @@ def _html_to_text(html_content: str, cid_map: dict[str, str] | None = None) -> s
330
if cid_map:
331
soup = BeautifulSoup(html_content, "html.parser")
332
for img in soup.find_all("img"):
331
- src = img.get("src", "")
333
+ src = str(img.get("src", ""))
334
if src.startswith("cid:"):
335
cid = src[4:]
336
if cid in cid_map: