fix: make ruff lint pass in CI
Add .ruff.toml ignoring BLE001/S110 (intentional mail parsing), apply ruff auto-fixes (imports, Optional->X|None), and fix format, shebang and PORT env default.
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
target-version = "py310"
|
||||||
|
|
||||||
|
[lint]
|
||||||
|
# Blind excepts and silent cleanup in mail parsing are intentional here.
|
||||||
|
ignore = ["BLE001", "S110"]
|
||||||
+25
-30
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
__version__ = "0.1.0"
|
__version__ = "0.1.0"
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import hmac
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import smtplib
|
import smtplib
|
||||||
@@ -13,16 +13,13 @@ from email import policy
|
|||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.parser import BytesParser
|
from email.parser import BytesParser
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
import hmac
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import uvicorn
|
import uvicorn
|
||||||
import yaml
|
import yaml
|
||||||
|
from fastmcp import Context, FastMCP
|
||||||
|
from fastmcp.server.auth import AccessToken, TokenVerifier
|
||||||
from imapclient import IMAPClient
|
from imapclient import IMAPClient
|
||||||
from fastmcp import FastMCP, Context
|
|
||||||
from fastmcp.server.auth import TokenVerifier, AccessToken
|
|
||||||
from starlette.middleware import Middleware
|
from starlette.middleware import Middleware
|
||||||
from starlette.responses import JSONResponse, Response
|
from starlette.responses import JSONResponse, Response
|
||||||
from starlette.types import ASGIApp, Receive, Scope, Send
|
from starlette.types import ASGIApp, Receive, Scope, Send
|
||||||
@@ -365,11 +362,11 @@ def parse_email_message(raw: bytes) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def build_search_criteria(
|
def build_search_criteria(
|
||||||
from_addr: Optional[str] = None,
|
from_addr: str | None = None,
|
||||||
to_addr: Optional[str] = None,
|
to_addr: str | None = None,
|
||||||
subject: Optional[str] = None,
|
subject: str | None = None,
|
||||||
since: Optional[str] = None,
|
since: str | None = None,
|
||||||
before: Optional[str] = None,
|
before: str | None = None,
|
||||||
) -> list:
|
) -> list:
|
||||||
criteria = []
|
criteria = []
|
||||||
if from_addr:
|
if from_addr:
|
||||||
@@ -534,8 +531,8 @@ async def watch_folder(
|
|||||||
# silently drop mail that arrived during the reconnect window. Reset only
|
# silently drop mail that arrived during the reconnect window. Reset only
|
||||||
# on first run or when the server's UIDVALIDITY changes (which means UIDs
|
# on first run or when the server's UIDVALIDITY changes (which means UIDs
|
||||||
# have been reassigned and the previous cursor is meaningless).
|
# have been reassigned and the previous cursor is meaningless).
|
||||||
last_seen_uid: Optional[int] = None
|
last_seen_uid: int | None = None
|
||||||
last_uidvalidity: Optional[int] = None
|
last_uidvalidity: int | None = None
|
||||||
|
|
||||||
while not stop_event.is_set():
|
while not stop_event.is_set():
|
||||||
client = None
|
client = None
|
||||||
@@ -742,9 +739,7 @@ async def _poll_folder(
|
|||||||
mailbox_uids[-1] if mailbox_uids else last_seen_uid,
|
mailbox_uids[-1] if mailbox_uids else last_seen_uid,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(
|
logger.warning("[%s/%s] Poll error: %s", account["id"], folder, e)
|
||||||
"[%s/%s] Poll error: %s", account["id"], folder, e
|
|
||||||
)
|
|
||||||
raise # reconnect via outer loop
|
raise # reconnect via outer loop
|
||||||
await asyncio.sleep(60)
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
@@ -842,11 +837,11 @@ async def search_emails(
|
|||||||
ctx: Context,
|
ctx: Context,
|
||||||
account_id: str,
|
account_id: str,
|
||||||
folder: str = "INBOX",
|
folder: str = "INBOX",
|
||||||
from_addr: Optional[str] = None,
|
from_addr: str | None = None,
|
||||||
to_addr: Optional[str] = None,
|
to_addr: str | None = None,
|
||||||
subject: Optional[str] = None,
|
subject: str | None = None,
|
||||||
since: Optional[str] = None,
|
since: str | None = None,
|
||||||
before: Optional[str] = None,
|
before: str | None = None,
|
||||||
limit: int = 20,
|
limit: int = 20,
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
accounts = ctx.lifespan_context["accounts"]
|
accounts = ctx.lifespan_context["accounts"]
|
||||||
@@ -941,11 +936,11 @@ async def send_email(
|
|||||||
to: str,
|
to: str,
|
||||||
subject: str,
|
subject: str,
|
||||||
body: str,
|
body: str,
|
||||||
cc: Optional[str] = None,
|
cc: str | None = None,
|
||||||
bcc: Optional[str] = None,
|
bcc: str | None = None,
|
||||||
html: Optional[str] = None,
|
html: str | None = None,
|
||||||
reply_to_uid: Optional[int] = None,
|
reply_to_uid: int | None = None,
|
||||||
reply_to_folder: Optional[str] = None,
|
reply_to_folder: str | None = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
accounts = ctx.lifespan_context["accounts"]
|
accounts = ctx.lifespan_context["accounts"]
|
||||||
acc = resolve_account(accounts, account_id)
|
acc = resolve_account(accounts, account_id)
|
||||||
@@ -1023,9 +1018,9 @@ async def create_draft(
|
|||||||
to: str,
|
to: str,
|
||||||
subject: str,
|
subject: str,
|
||||||
body: str,
|
body: str,
|
||||||
cc: Optional[str] = None,
|
cc: str | None = None,
|
||||||
bcc: Optional[str] = None,
|
bcc: str | None = None,
|
||||||
html: Optional[str] = None,
|
html: str | None = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
accounts = ctx.lifespan_context["accounts"]
|
accounts = ctx.lifespan_context["accounts"]
|
||||||
acc = resolve_account(accounts, account_id)
|
acc = resolve_account(accounts, account_id)
|
||||||
@@ -1320,7 +1315,7 @@ async def get_server_info(ctx: Context) -> dict:
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
port = int(os.environ.get("PORT", 3000))
|
port = int(os.environ.get("PORT", "3000"))
|
||||||
host = "0.0.0.0"
|
host = "0.0.0.0"
|
||||||
logger.info("Starting poke-mail on %s:%d", host, port)
|
logger.info("Starting poke-mail on %s:%d", host, port)
|
||||||
app = mcp.http_app(
|
app = mcp.http_app(
|
||||||
|
|||||||
Reference in New Issue
Block a user