{"id":962,"date":"2025-07-28T17:50:53","date_gmt":"2025-07-28T09:50:53","guid":{"rendered":"https:\/\/keyi.eu.org\/?p=962"},"modified":"2025-07-28T17:56:23","modified_gmt":"2025-07-28T09:56:23","slug":"%e6%af%8f%e5%88%86%e9%90%98%e6%9f%a5%e8%a9%a2%e9%83%b5%e4%bb%b6%ef%bc%8c%e5%a6%82%e6%9e%9c%e6%9c%89%e4%bf%a1%ef%bc%8ctg%e9%80%9a%e7%9f%a5","status":"publish","type":"post","link":"https:\/\/keyi.eu.org\/?p=962","title":{"rendered":"\u6bcf\u5206\u9418\u67e5\u8a62\u90f5\u4ef6\uff0c\u5982\u679c\u6709\u4fe1\uff0cTG\u901a\u77e5"},"content":{"rendered":"<p><img src=\"https:\/\/keyi.eu.org\/wp-content\/uploads\/2025\/07\/blogmail_to_tg.png\" alt=\"mail to tg\" \/><br \/>1\u3001\u5f9eTelegram\u4e0a\uff0c\u627e\u5230@BotFather\uff0c\u5efa\u7acb\u901a\u77e5bot\uff0c\u4e26\u4e14\u8a18\u9304\u4e0b\u9019\u500bbot\u7684API Token\u3002<\/p>\n<p>2\u3001\u548c\u9019\u500b\u65b0\u5efa\u7684bot\u5c0d\u8a71\u4e00\u4e0b\uff0c\u9ede\u4e00\u6b21\/start\uff0c\u4ee5\u4fbf\u8b93\u5b83\u80fd\u767c\u4f86\u901a\u77e5\u6d88\u606f\u3002<\/p>\n<p>3\u3001\u5728VPS\u4e0a\uff0c\u90e8\u7f72\u8173\u672c\uff0c\u4e26\u4e14\u4ee5pm2\u4f86\u4fdd\u6301\u6301\u7e8c\u5553\u52d5\u72c0\u614b\u3002<\/p>\n<p>4\u3001\u8173\u672c\u5167\u5bb9\uff0c\u7232\u6bcf\u5206\u9418\uff0c\u4ee5IMAP\u5354\u8b70\uff0c\u767b\u9304\u90f5\u7bb1\uff0c\u4e00\u65e6\u6709\u672a\u8b80\u90f5\u4ef6\uff0c\u5247\u6a19\u8a18\u7232\u5df2\u8b80\uff0c\u4e26\u4e14\u628a\u90f5\u4ef6\u6a19\u984c\u548c\u5167\u5bb9\uff0c\u5728Telegram\u4e0a\u767c\u9001\u901a\u77e5\u3002<\/p>\n<p>\u8173\u672c\u5167\u5bb9\uff1a<\/p>\n<p>\u00a0<\/p>\n\n\n<pre class=\"wp-block-code\"><code>\nimport imaplib\nimport email\nfrom email.header import decode_header\nimport time\nimport telegram\nfrom telegram.error import TelegramError\nimport asyncio\nimport re\nimport html\n\n# IMAP \u4f3a\u670d\u5668\u914d\u7f6e\nIMAP_SERVER = \"\u90f5\u4ef6\u670d\u52d9\u5668\"\nUSERNAME = \"\u90f5\u7bb1\u8cec\u6236\u540d\"\nPASSWORD = \"\u90f5\u7bb1\u5bc6\u78bc\"\n# Telegram Bot \u914d\u7f6e\nBOT_TOKEN = \"bot\u7684API Token\"\nCHAT_ID = \"\u901a\u77e5\u7528\u6236\u7684ID\"\n\n# \u521d\u59cb\u5316 Telegram Bot\nbot = telegram.Bot(token=BOT_TOKEN)\n\nasync def send_telegram_message(message):\n    \"\"\"\u901a\u904e Telegram Bot \u767c\u9001\u6d88\u606f\"\"\"\n    try:\n        await bot.send_message(chat_id=CHAT_ID, text=message, parse_mode='HTML')\n    except TelegramError as e:\n        print(f\"\u767c\u9001 Telegram \u6d88\u606f\u5931\u6557: {e}\")\n\ndef decode_email_subject(subject):\n    \"\"\"\u89e3\u78bc\u90f5\u4ef6\u4e3b\u984c\"\"\"\n    decoded_subject = decode_header(subject)&#91;0]&#91;0]\n    if isinstance(decoded_subject, bytes):\n        try:\n            return decoded_subject.decode()\n        except:\n            return decoded_subject.decode('utf-8', errors='ignore')\n    return decoded_subject\n\ndef get_email_content(msg):\n    \"\"\"\u63d0\u53d6\u90f5\u4ef6\u5167\u5bb9\u548c\u9644\u4ef6\u4fe1\u606f\"\"\"\n    text_content = \"\"\n    attachments = &#91;]\n\n    if msg.is_multipart():\n        for part in msg.walk():\n            content_type = part.get_content_type()\n            # \u63d0\u53d6\u7d14\u6587\u672c\u5167\u5bb9\n            if content_type == 'text\/plain':\n                try:\n                    text_content = part.get_payload(decode=True).decode('utf-8', errors='ignore')\n                except:\n                    text_content = part.get_payload(decode=True).decode('latin1', errors='ignore')\n            # \u6aa2\u67e5\u9644\u4ef6\n            if part.get('Content-Disposition') is not None:\n                filename = part.get_filename()\n                if filename:\n                    decoded_filename = decode_header(filename)&#91;0]&#91;0]\n                    if isinstance(decoded_filename, bytes):\n                        try:\n                            decoded_filename = decoded_filename.decode()\n                        except:\n                            decoded_filename = decoded_filename.decode('utf-8', errors='ignore')\n                    attachments.append(decoded_filename)\n    else:\n        try:\n            text_content = msg.get_payload(decode=True).decode('utf-8', errors='ignore')\n        except:\n            text_content = msg.get_payload(decode=True).decode('latin1', errors='ignore')\n\n    # \u9650\u5236\u6587\u672c\u5167\u5bb9\u9577\u5ea6\n    if len(text_content) > 1000:\n        text_content = text_content&#91;:1000] + \"... &#91;\u5167\u5bb9\u5df2\u622a\u65b7]\"\n\n    # \u6dfb\u52a0\u9644\u4ef6\u4fe1\u606f\n    if attachments:\n        attachment_info = \"\\n&lt;b>\u9644\u4ef6:&lt;\/b> \" + \", \".join(attachments)\n    else:\n        attachment_info = \"\"\n\n    return text_content + attachment_info\n\nasync def check_email():\n    \"\"\"\u6aa2\u67e5\u65b0\u90f5\u4ef6\u4e26\u767c\u9001\u901a\u77e5\"\"\"\n    try:\n        # \u9023\u63a5\u5230 IMAP \u4f3a\u670d\u5668\n        mail = imaplib.IMAP4_SSL(IMAP_SERVER)\n        mail.login(USERNAME, PASSWORD)\n        mail.select(\"INBOX\")\n\n        # \u641c\u7d22\u672a\u8b80\u90f5\u4ef6\n        _, message_numbers = mail.search(None, 'UNSEEN')\n        \n        if not message_numbers&#91;0]:\n            print(\"\u6c92\u6709\u65b0\u90f5\u4ef6\")\n            mail.logout()\n            return\n\n        for num in message_numbers&#91;0].split():\n            # \u7372\u53d6\u90f5\u4ef6\n            _, msg_data = mail.fetch(num, \"(RFC822)\")\n            email_body = msg_data&#91;0]&#91;1]\n            msg = email.message_from_bytes(email_body)\n\n            # \u7372\u53d6\u90f5\u4ef6\u4e3b\u984c\u3001\u767c\u4ef6\u4eba\u548c\u6536\u4ef6\u4eba\n            subject = decode_email_subject(msg.get(\"Subject\", \"\u7121\u4e3b\u984c\"))\n            from_ = msg.get(\"From\", \"\u672a\u77e5\u767c\u4ef6\u4eba\")\n            to_ = msg.get(\"To\", \"\u672a\u77e5\u6536\u4ef6\u4eba\")\n            \n            # \u6e05\u7406\u4e26\u8f49\u7fa9\u767c\u4ef6\u4eba\u548c\u6536\u4ef6\u4eba\u683c\u5f0f\n            from_clean = html.escape(re.sub(r'&#91;\\n\\r]+', ' ', from_))\n            to_clean = html.escape(re.sub(r'&#91;\\n\\r]+', ' ', to_))\n            \n            # \u7372\u53d6\u90f5\u4ef6\u5167\u5bb9\u548c\u9644\u4ef6\u4fe1\u606f\n            content = get_email_content(msg)\n\n            # \u683c\u5f0f\u5316\u6d88\u606f\uff0c\u5305\u542b\u6536\u4ef6\u4eba\u4fe1\u606f\n            message = (\n                f\"&lt;b>\u65b0\u90f5\u4ef6\u901a\u77e5&lt;\/b>\\n\"\n                f\"&lt;b>\u4e3b\u984c:&lt;\/b> {html.escape(subject)}\\n\"\n                f\"&lt;b>\u767c\u4ef6\u4eba:&lt;\/b> {from_clean}\\n\"\n                f\"&lt;b>\u6536\u4ef6\u4eba:&lt;\/b> {to_clean}\\n\"\n                f\"&lt;b>\u5167\u5bb9:&lt;\/b>\\n{content}\"\n            )\n\n            # \u767c\u9001 Telegram \u901a\u77e5\n            await send_telegram_message(message)\n            print(f\"\u5df2\u767c\u9001\u901a\u77e5: {subject}\")\n\n            # \u5c07\u90f5\u4ef6\u6a19\u8a18\u70ba\u5df2\u8b80\n            mail.store(num, '+FLAGS', '\\\\Seen')\n\n        mail.logout()\n    except Exception as e:\n        print(f\"\u6aa2\u67e5\u90f5\u4ef6\u6642\u51fa\u932f: {e}\")\n\nasync def main():\n    \"\"\"\u4e3b\u5faa\u74b0\uff0c\u6bcf\u5206\u9418\u6aa2\u67e5\u4e00\u6b21\u90f5\u4ef6\"\"\"\n    while True:\n        print(\"\u6b63\u5728\u6aa2\u67e5\u65b0\u90f5\u4ef6...\")\n        await check_email()\n        await asyncio.sleep(60)  # \u7b49\u5f85 60 \u79d2\n\nif __name__ == \"__main__\":\nasyncio.run(main())<\/code><\/pre>\n<p>\u8f6c\u8f7d\u8bf7\u6ce8\u660e\uff1a<a href=\"https:\/\/keyi.eu.org\">\u5218\u592a\u76d1\u7684\u79c1\u85cf<\/a> &raquo; <a href=\"https:\/\/keyi.eu.org\/?p=962\">\u6bcf\u5206\u9418\u67e5\u8a62\u90f5\u4ef6\uff0c\u5982\u679c\u6709\u4fe1\uff0cTG\u901a\u77e5<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>1\u3001\u5f9eTelegram\u4e0a\uff0c\u627e\u5230@BotFather\uff0c\u5efa\u7acb\u901a\u77e5bot\uff0c\u4e26\u4e14\u8a18\u9304\u4e0b\u9019\u500bbot\u7684API Token\u3002 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/keyi.eu.org\/index.php?rest_route=\/wp\/v2\/posts\/962"}],"collection":[{"href":"https:\/\/keyi.eu.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/keyi.eu.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/keyi.eu.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/keyi.eu.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=962"}],"version-history":[{"count":2,"href":"https:\/\/keyi.eu.org\/index.php?rest_route=\/wp\/v2\/posts\/962\/revisions"}],"predecessor-version":[{"id":966,"href":"https:\/\/keyi.eu.org\/index.php?rest_route=\/wp\/v2\/posts\/962\/revisions\/966"}],"wp:attachment":[{"href":"https:\/\/keyi.eu.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/keyi.eu.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/keyi.eu.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}