家庭服務器IPV6搭建無限郵箱系統指南

qq郵箱操作
// 郵箱配置信息
// 注意:使用QQ郵箱需要先開啟IMAP服務并獲取授權碼
// 設置方法:登錄QQ郵箱 -> 設置 -> 賬戶 -> 開啟IMAP/SMTP服務 -> 生成授權碼

服務器操作
fetchmail 同步QQ郵箱
nginx搭建web顯示本地同步過來的郵箱

ssh端瀏覽郵箱
通過python腳本實現其他用戶登錄可瀏覽郵件

騰訊云
dns轉給cloudflare

cloudflare
信件全局轉發到QQ
AAAA解析到物理機IPV6

演示站點 fengche.site
博客 xoxome.online

下面是ssh端服務器腳本

#!/usr/bin/env python3
# -*- coding: utf-8 -*-import os
import sys
import email
import email.header
import email.utils
import datetime
import subprocess
import tempfile# 郵件目錄
MAIL_DIR = "/home/y/Maildir/INBOX/new/new"def clear_screen():"""清屏"""os.system("clear")def decode_header(header):"""解碼郵件頭部信息"""if not header:return "未知"decoded_header = email.header.decode_header(header)result = ""for text, charset in decoded_header:if isinstance(text, bytes):try:if charset:result += text.decode(charset)else:result += text.decode("utf-8", "replace")except:result += text.decode("utf-8", "replace")else:result += textreturn resultdef get_email_info(mail_file):"""獲取郵件信息"""with open(mail_file, "rb") as f:msg = email.message_from_binary_file(f)from_addr = decode_header(msg.get("From", "未知"))to_addr = decode_header(msg.get("To", "未知"))subject = decode_header(msg.get("Subject", "未知"))date_str = msg.get("Date", "")try:date = email.utils.parsedate_to_datetime(date_str)date_formatted = date.strftime("%Y-%m-%d %H:%M:%S")except:date_formatted = date_strreturn {"from": from_addr,"to": to_addr,"subject": subject,"date": date_formatted}def html_to_text(html_content):"""將HTML轉換為可讀文本"""# 使用臨時文件保存HTML內容with tempfile.NamedTemporaryFile(suffix='.html', delete=False) as f:f.write(html_content.encode('utf-8'))temp_filename = f.nametry:# 嘗試使用w3m將HTML轉換為文本 try:result = subprocess.run(['w3m', '-dump', temp_filename], capture_output=True, text=True, check=True)text = result.stdoutexcept (subprocess.SubprocessError, FileNotFoundError):# 如果w3m不可用,嘗試使用lynxtry:result = subprocess.run(['lynx', '-dump', '-force_html', temp_filename],capture_output=True, text=True, check=True)text = result.stdoutexcept (subprocess.SubprocessError, FileNotFoundError):# 如果lynx也不可用,使用簡單的HTML標簽移除text = html_content# 移除常見HTML標簽tags_to_remove = ['<html>', '</html>', '<body>', '</body>', '<head>', '</head>','<script>', '</script>', '<style>', '</style>']for tag in tags_to_remove:text = text.replace(tag, '')# 將<br>和<p>替換為換行符text = text.replace('<br>', '\n').replace('<p>', '\n').replace('</p>', '\n')# 移除其他HTML標簽in_tag = Falseresult = ""for char in text:if char == '<':in_tag = Trueelif char == '>':in_tag = Falseelif not in_tag:result += chartext = resultreturn textfinally:# 清理臨時文件try:os.unlink(temp_filename)except:passdef extract_email_content(mail_file):"""提取郵件內容"""with open(mail_file, "rb") as f:msg = email.message_from_binary_file(f)content = ""html_content = ""if msg.is_multipart():for part in msg.walk():content_type = part.get_content_type()content_disposition = part.get("Content-Disposition", "")# 忽略附件if "attachment" in content_disposition:continue# 獲取文本內容if content_type == "text/plain" and not content:payload = part.get_payload(decode=True)if payload:charset = part.get_content_charset()try:if charset:content += payload.decode(charset)else:content += payload.decode("utf-8", "replace")except:content += payload.decode("utf-8", "replace")# 獲取HTML內容elif content_type == "text/html" and not html_content:payload = part.get_payload(decode=True)if payload:charset = part.get_content_charset()try:if charset:html_content += payload.decode(charset)else:html_content += payload.decode("utf-8", "replace")except:html_content += payload.decode("utf-8", "replace")else:# 非多部分郵件content_type = msg.get_content_type()payload = msg.get_payload(decode=True)if payload:charset = msg.get_content_charset()try:decoded = payload.decode(charset if charset else "utf-8", "replace")if content_type == "text/plain":content = decodedelif content_type == "text/html":html_content = decodedexcept:content = payload.decode("utf-8", "replace")# 如果有HTML內容但沒有純文本內容,轉換HTML為文本if html_content and not content:content = html_to_text(html_content)# 如果沒有任何內容if not content and not html_content:content = "【無法解析的郵件內容】"return content, html_contentdef list_emails():"""列出郵件"""clear_screen()print("歡迎使用郵件查看系統")print("=======================")print()if not os.path.isdir(MAIL_DIR):print("郵件目錄不存在: " + MAIL_DIR)input("按Enter鍵退出...")sys.exit(1)mail_files = []try:# 獲取所有郵件文件,按修改時間排序mail_files = sorted([f for f in os.listdir(MAIL_DIR) if os.path.isfile(os.path.join(MAIL_DIR, f))],key=lambda x: os.path.getmtime(os.path.join(MAIL_DIR, x)),reverse=True)except Exception as e:print("讀取郵件目錄出錯: " + str(e))input("按Enter鍵退出...")sys.exit(1)if not mail_files:print("沒有新郵件")print("按Enter鍵同步郵件,按q退出:")choice = input().strip()if choice.lower() != "q":sync_mail()return list_emails()  # 重新加載郵件列表else:sys.exit(0)print("找到 " + str(len(mail_files)) + " 封新郵件:")print()# 顯示最多5封郵件displayed_files = []for i, mail_file in enumerate(mail_files[:5]):full_path = os.path.join(MAIL_DIR, mail_file)try:info = get_email_info(full_path)displayed_files.append(mail_file)print(str(i+1) + ") " + mail_file)print("   從: " + info["from"])print("   主題: " + info["subject"])print("   日期: " + info["date"])print()except Exception as e:print("讀取郵件 " + mail_file + " 出錯: " + str(e))print()return displayed_filesdef sync_mail():"""同步郵件"""clear_screen()print("正在使用y用戶權限同步郵件...")try:# 使用sudo以y用戶身份運行fetchmailresult = subprocess.run(['sudo', '-u', 'y', 'fetchmail', '-v'], capture_output=True, text=True)output = result.stdouterror = result.stderrif output:print(output)if error:print()print()# 檢查是否成功同步了新郵件if "reading message" in (output or "") or "messages" in (output or ""):print("成功同步了新郵件!")else:print("沒有新郵件或同步失敗。")except Exception as e:print("同步郵件出錯: " + str(e))print()input("按Enter鍵繼續...")def view_email(mail_file):"""查看郵件內容"""clear_screen()full_path = os.path.join(MAIL_DIR, mail_file)try:# 獲取郵件信息info = get_email_info(full_path)print("郵件: " + mail_file)print("=======================")print("從: " + info["from"])print("收件人: " + info["to"])print("主題: " + info["subject"])print("日期: " + info["date"])print("=======================")print()# 提取郵件內容text_content, html_content = extract_email_content(full_path)if html_content:print("郵件內容 (轉換自HTML):")print("=======================")print(text_content)print("=======================")print()print("選項: 1) 返回郵件列表 2) 查看原始HTML 3) 同步郵件 [1-3]:")view_choice = input().strip()if view_choice == "2":# 使用臨時文件顯示HTMLwith tempfile.NamedTemporaryFile(suffix='.html', delete=False) as f:f.write(html_content.encode('utf-8'))temp_filename = f.nametry:# 嘗試使用不同的HTML查看器browsers = [['w3m', temp_filename],['lynx', temp_filename],['less', temp_filename]]for browser in browsers:try:subprocess.run(browser)breakexcept (subprocess.SubprocessError, FileNotFoundError):continuefinally:os.unlink(temp_filename)elif view_choice == "3":sync_mail()else:print("郵件內容:")print("=======================")print(text_content)print("=======================")print()print("選項: 1) 返回郵件列表 2) 同步郵件 [1-2]:")view_choice = input().strip()if view_choice == "2":sync_mail()return Trueexcept Exception as e:print("查看郵件出錯: " + str(e))print()input("按Enter鍵返回...")return Falsedef main():"""主函數"""while True:displayed_files = list_emails()print("輸入郵件編號查看內容,按Enter查看最新郵件,按s同步郵件,按q退出:")choice = input().strip()if choice.lower() == "q":print("謝謝使用,再見!")breakelif choice.lower() == "s":sync_mail()continuemail_to_view = Noneif not choice or choice == "1":# 查看最新郵件if displayed_files:mail_to_view = displayed_files[0]elif choice.isdigit():# 查看選定郵件idx = int(choice) - 1if 0 <= idx < len(displayed_files):mail_to_view = displayed_files[idx]else:print("無效選擇!")input("按Enter鍵繼續...")continueelse:print("無效選擇!")input("按Enter鍵繼續...")continueif mail_to_view:view_email(mail_to_view)if __name__ == "__main__":# 檢查并安裝必要的HTML渲染工具try:for pkg in ['w3m', 'lynx']:try:subprocess.run(['which', pkg], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)breakexcept:passexcept:passtry:main()except KeyboardInterrupt:print("\n程序已退出")sys.exit(0)except Exception as e:print("程序發生錯誤: " + str(e))input("按Enter鍵退出...")sys.exit(1)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81074.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81074.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81074.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Tauri v1 與 v2 配置對比

本文檔對比 Tauri v1 和 v2 版本的配置結構和內容差異&#xff0c;幫助開發者了解版本變更并進行遷移。 配置結構變化 v1 配置結構 {"package": { ... },"tauri": { "allowlist": { ... },"bundle": { ... },"security":…

對js的Date二次封裝,繼承了原Date的所有方法,增加了自己擴展的方法,可以實現任意時間往前往后推算多少小時、多少天、多少周、多少月;

封裝js時間工具 概述 該方法繼承了 js 中 Date的所有方法&#xff1b;同時擴展了一部分自用方法&#xff1a; 1、任意時間 往前推多少小時&#xff0c;天&#xff0c;月&#xff0c;周&#xff1b;參數1、2必填&#xff0c;參數3可選beforeDate(num,formatter,dateVal); befo…

TimeDistill:通過跨架構蒸餾的MLP高效長期時間序列預測

原文地址&#xff1a;https://arxiv.org/abs/2502.15016 發表會議&#xff1a;暫定&#xff08;但是Star很高&#xff09; 代碼地址&#xff1a;無 作者&#xff1a;Juntong Ni &#xff08;倪浚桐&#xff09;, Zewen Liu &#xff08;劉澤文&#xff09;, Shiyu Wang&…

DeepSeek最新大模型發布-DeepSeek-Prover-V2-671B

2025 年 4 月 30 日&#xff0c;DeepSeek 開源了新模型 DeepSeek-Prover-V2-671B&#xff0c;該模型聚焦數學定理證明任務&#xff0c;基于混合專家架構&#xff0c;使用 Lean 4 框架進行形式化推理訓練&#xff0c;參數規模達 6710 億&#xff0c;結合強化學習與大規模合成數據…

如何用AI生成假期旅行照?

以下是2025年最新AI生成假期旅行照片的實用工具推薦及使用指南&#xff0c;結合工具特點、研發背景和適用場景進行綜合解析&#xff1a; 一、主流AI旅行照片生成工具推薦與對比 1. 搜狐簡單AI&#xff08;國內工具&#xff09; ? 特點&#xff1a; ? 一鍵優化與背景替換&…

ElaticSearch

ElaticSearch: 全文搜索 超級強&#xff0c;比如模糊查詢、關鍵詞高亮等 海量數據 高效查詢&#xff0c;比傳統關系數據庫快得多&#xff08;尤其是搜索&#xff09; 靈活的數據結構&#xff08;Schema靈活&#xff0c;可以動態字段&#xff09; 分布式高可用&#xff0c;天…

Android開發,實現一個簡約又好看的登錄頁

文章目錄 1. 編寫布局文件2.設計要點說明3. 效果圖4. 關于作者其它項目視頻教程介紹 1. 編寫布局文件 編寫activity.login.xml 布局文件 <?xml version"1.0" encoding"utf-8"?> <androidx.appcompat.widget.LinearLayoutCompat xmlns:android…

機器學習:【拋擲硬幣的貝葉斯后驗概率】

首先,拋硬幣的問題通常涉及先驗概率、似然函數和后驗概率。假設用戶可能想通過觀察一系列的正面(H)和反面(T)來更新硬幣的偏差概率。例如,先驗可能假設硬幣是均勻的,但隨著觀察到更多數據,用貝葉斯定理計算后驗分布。 通常,硬幣的偏差可以用Beta分布作為先驗,因為它…

Echarts 問題:自定義的 legend 點擊后消失,格式化 legend 的隱藏文本樣式

文章目錄 問題分析實現步驟代碼解釋問題 如下圖所示,在自定義的 legend 點擊后會消失 分析 我把隱藏的圖例字體顏色設為灰色,可以借助 legend.formatter 和 legend.textStyle 結合 option.series 的 show 屬性來達成。以下是具體的實現步驟和示例代碼: <!DOCTYPE ht…

光譜相機如何提升目標檢測與識別精度

光譜相機&#xff08;多光譜/高光譜&#xff09;通過捕捉目標在多個波段的光譜特征&#xff0c;能夠揭示傳統RGB相機無法感知的材質、化學成分及物理特性差異。以下是提升其目標檢測與識別精度的核心方法&#xff1a; ?1. 硬件優化&#xff1a;提升數據質量? ?(1) 光譜分辨…

springboot項目配置nacos,指定使用環境

遇到這樣一個問題&#xff0c;在開發、測試、生成環境之間切換的問題。 大多數的操作是通過修改spring.profiles.active來確定指向使用的環境配置文件&#xff0c;對應項目中需要增加對應的配置文件。 但是現在幾乎所有公司都會有代碼管理不管是SVN、git&#xff0c;這樣就會涉…

AI代碼審查的落地實施方案 - Java架構師面試實戰

AI代碼審查的落地實施方案 - Java架構師面試實戰 本文通過模擬一位擁有十年Java研發經驗的資深架構師馬架構與面試官之間的對話&#xff0c;深入探討了AI代碼審查的落地實施方案。 第一輪提問 面試官&#xff1a; 馬架構&#xff0c;請介紹一下您對AI代碼審查的理解。 馬架…

TDengine 訂閱不到數據問題排查

簡介 TDengine 在實際生產應用中&#xff0c;經常會遇到訂閱程序訂閱不到數據的問題&#xff0c;總結大部分都為使用不當或狀態不正確等問題&#xff0c;需手工解決。 查看服務端狀態 通過 sql 命令查看有問題的 topic 和consumer_group 組訂閱是否正常。 select * from inf…

二、UI自動化測試02--元素定位方法

目錄 一、定位?組元素?法二、XPath 定位?法1. 路徑策略1.1 路徑值獲取?法 2. 利?元素屬性策略利?元素屬性策略的注意事項 3. 屬性和邏輯結合4. 層級和屬性結合策略5. XPath 延伸?法 三、CSS 定位?法1. CSS 策略: id選擇器/class選擇器/元素選擇器/屬性選擇器2. 屬性選擇…

HotSpot的算法細節

可達性分析算法 以一系列“GC Roots”根對象作為起始節點集&#xff0c;從這些節點開始&#xff0c;根據引用關系向下搜索&#xff0c;搜索過程所走過的路徑稱為“引用鏈”&#xff08;Reference Chain&#xff09;&#xff0c;如果某個對象到GC Roots間沒有任何引用鏈相連&am…

Transformer數學推導——Q27 證明時序注意力(Temporal Attention)在視頻模型中的幀間依賴建模

該問題歸類到Transformer架構問題集——注意力機制——跨模態與多模態。請參考LLM數學推導——Transformer架構問題集。 在視頻理解任務中&#xff0c;捕捉幀與幀之間的時間依賴關系&#xff08;如動作的連貫性、物體的運動軌跡&#xff09;是核心挑戰。時序注意力&#xff08…

服務器和數據庫哪一個更重要

在當今數字化的時代&#xff0c;服務器和數據庫都是構建和運行各種應用系統的關鍵組成部分&#xff0c;要說哪一個更重要&#xff0c;其實很難簡單地給出定論。 服務器就像是一個強大的引擎&#xff0c;為應用程序提供了穩定的運行環境和高效的計算能力。它負責接收和處理來自…

【Android】四大組件之Service

目錄 一、什么是Service 二、啟停 Service 三、綁定 Service 四、前臺服務 五、遠程服務擴展 六、服務保活 七、服務啟動方法混用 你可以把Service想象成一個“后臺默默打工的工人”。它沒有UI界面&#xff0c;默默地在后臺干活&#xff0c;比如播放音樂、下載文件、處理…

pytest 技術總結

目錄 一 pytest的安裝&#xff1a; 二 pytest有三種啟動方式&#xff1a; 三 用例規則&#xff1a; 四 配置框架&#xff1a; 一 pytest的安裝&#xff1a; pip install pytest # 安裝 pip install pytest -U # 升級到最新版 二 pytest有三種啟動方式&#xff1a; 1…