diff --git a/outlook_web/repositories/accounts.py b/outlook_web/repositories/accounts.py index 2a78cfc..2a8cc54 100644 --- a/outlook_web/repositories/accounts.py +++ b/outlook_web/repositories/accounts.py @@ -408,9 +408,12 @@ def get_telegram_push_accounts() -> List[Dict]: """返回所有 telegram_push_enabled=1 且非 disabled 状态的账号。""" db = get_db() rows = db.execute( - """SELECT id, email, provider, refresh_token, imap_host, imap_port, - imap_password, telegram_last_checked_at - FROM accounts - WHERE telegram_push_enabled = 1 AND status != 'disabled'""" + """SELECT a.id, a.email, a.provider, a.client_id, a.refresh_token, + a.imap_host, a.imap_port, a.imap_password, + a.telegram_last_checked_at, a.group_id, + g.proxy_url + FROM accounts a + LEFT JOIN groups g ON a.group_id = g.id + WHERE a.telegram_push_enabled = 1 AND a.status != 'disabled'""" ).fetchall() return [dict(r) for r in rows] diff --git a/outlook_web/services/scheduler.py b/outlook_web/services/scheduler.py index 2bcde66..962f77b 100644 --- a/outlook_web/services/scheduler.py +++ b/outlook_web/services/scheduler.py @@ -92,6 +92,7 @@ def _configure_telegram_push_job(scheduler, app) -> None: coalesce=True, misfire_grace_time=interval, ) + print(f"✓ Telegram 推送 Job 已配置(轮询间隔:{interval} 秒)") def configure_scheduler_jobs(scheduler, app, test_refresh_token) -> None: diff --git a/outlook_web/services/telegram_push.py b/outlook_web/services/telegram_push.py index 8163ae7..ef8fd6c 100644 --- a/outlook_web/services/telegram_push.py +++ b/outlook_web/services/telegram_push.py @@ -205,12 +205,14 @@ def _fetch_new_emails_imap(account: dict, since: str) -> List[dict]: def _fetch_new_emails_graph(account: dict, since: str) -> List[dict]: """通过 Microsoft Graph API 获取 received_at > since 的邮件,最多返回 50 封。""" from outlook_web.security.crypto import decrypt_data - from outlook_web.services.graph import get_access_token + from outlook_web.services.graph import build_proxies, get_access_token_graph + client_id = account.get("client_id", "") refresh_token_raw = account.get("refresh_token", "") refresh_token = decrypt_data(refresh_token_raw) if refresh_token_raw else "" + proxy_url = account.get("proxy_url", "") or "" - access_token = get_access_token(refresh_token) + access_token = get_access_token_graph(client_id, refresh_token, proxy_url) if not access_token: return [] @@ -223,10 +225,11 @@ def _fetch_new_emails_graph(account: dict, since: str) -> List[dict]: "$orderby": "receivedDateTime asc", } headers = {"Authorization": f"Bearer {access_token}"} + proxies = build_proxies(proxy_url) results: List[dict] = [] try: - resp = requests.get(url, headers=headers, params=params, timeout=15) + resp = requests.get(url, headers=headers, params=params, timeout=15, proxies=proxies) if not resp.ok: return [] data = resp.json() @@ -258,6 +261,11 @@ def _fetch_new_emails_graph(account: dict, since: str) -> List[dict]: def run_telegram_push_job(app) -> None: """主入口:轮询 → 推送 → 更新游标。由调度器调用。""" + import time + + t0 = time.monotonic() + logger.info("[telegram_push] job started") + with app.app_context(): from outlook_web.repositories.accounts import ( get_telegram_push_accounts, @@ -271,10 +279,12 @@ def run_telegram_push_job(app) -> None: chat_id = get_setting("telegram_chat_id", "") if not bot_token or not chat_id: + logger.info("[telegram_push] job skipped: no bot_token or chat_id") return accounts = get_telegram_push_accounts() if not accounts: + logger.info("[telegram_push] job skipped: no push-enabled accounts") return job_start_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S") @@ -309,3 +319,6 @@ def run_telegram_push_job(app) -> None: finally: update_telegram_cursor(account["id"], job_start_time) + + elapsed = time.monotonic() - t0 + logger.info("[telegram_push] job finished: sent=%d elapsed=%.1fs", sent_count, elapsed) diff --git a/static/js/main.js b/static/js/main.js index 2b325dd..84a1ab1 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -989,11 +989,15 @@ ${details} document.getElementById('pollingCount').value = data.settings.polling_count || '5'; // 加载 Telegram 推送设置 - document.getElementById('telegramBotToken').value = data.telegram_bot_token || ''; - document.getElementById('telegramChatId').value = data.telegram_chat_id || ''; - document.getElementById('telegramPollInterval').value = data.telegram_poll_interval || '600'; + const tgToken = document.getElementById('telegramBotToken'); + const tgChat = document.getElementById('telegramChatId'); + const tgPoll = document.getElementById('telegramPollInterval'); + if (tgToken) tgToken.value = data.telegram_bot_token || ''; + if (tgChat) tgChat.value = data.telegram_chat_id || ''; + if (tgPoll) tgPoll.value = data.telegram_poll_interval || '600'; } } catch (error) { + console.error('loadSettings error:', error); showToast('加载设置失败', 'error'); } } @@ -1126,9 +1130,12 @@ ${details} settings.polling_count = pCount; // Telegram 推送配置 - const tgBotToken = document.getElementById('telegramBotToken').value.trim(); - const tgChatId = document.getElementById('telegramChatId').value.trim(); - const tgPollInterval = parseInt(document.getElementById('telegramPollInterval').value); + const tgBotTokenEl = document.getElementById('telegramBotToken'); + const tgChatIdEl = document.getElementById('telegramChatId'); + const tgPollIntervalEl = document.getElementById('telegramPollInterval'); + const tgBotToken = tgBotTokenEl ? tgBotTokenEl.value.trim() : ''; + const tgChatId = tgChatIdEl ? tgChatIdEl.value.trim() : ''; + const tgPollInterval = tgPollIntervalEl ? parseInt(tgPollIntervalEl.value) : NaN; if (tgBotToken) { settings.telegram_bot_token = tgBotToken;