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