use proxy while reading gmx mails

This commit is contained in:
2026-03-28 10:07:32 +01:00
parent b224c75ad0
commit 228c0b9bbb
5 changed files with 618 additions and 17 deletions
+75 -10
View File
@@ -1,19 +1,25 @@
import datetime
import email
import logging
import os
import re
from concurrent.futures import ThreadPoolExecutor
from email.header import decode_header
from email.message import Message
from typing import Union, List
from typing import Union, List, Optional
from dotenv import load_dotenv
from imapclient import IMAPClient
from db.mongo_manager import MONGO_STORE_MANAGER
from excel_reader import read_contacts
from mail.mail_constants import DOMAIN_HOTMAIL, create_imap
from mail.imap_proxy_reader import ProxyIMAPClient, ProxyConfig, get_imap_server
from models.ReserveResultPojo import ReserveResultPojo
from models.mail_pojo import MailPojo, MailAddress
# Charger les variables d'environnement depuis .env
load_dotenv()
# 定义常量
VALIDATION_URL_SUBJECT_FR = 'Validation de votre demande de rendez-vous'
VALIDATION_URL_SUBJECT_EN = 'Please confirm your appointment request'
@@ -25,6 +31,17 @@ EMAIL_ADDRESS_REGEX = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b'
# 日期格式
DATE_FORMAT = "%d-%b-%Y"
# GMX域名列表(用于判断是否需要使用代理)
GMX_DOMAINS = (
"gmx.com", "gmx.net", "gmx.de", "gmx.at",
"gmx.fr", "gmx.us", "gmx.sg", "gmx.ch", "gmx.pt",
)
def is_gmx_account(login: str) -> bool:
"""判断邮箱是否属于GMX域名"""
return any(d in login.lower() for d in GMX_DOMAINS)
# 邮箱列表(简化为常量)
REDIRECTION_MAILS = "appointment2022@aol.com, chenpeijun@aol.com,hongjiang176@aol.com,ciyuexie@aol.com,rutger.62@aol.com,ciccidaniel@aol.com,armasgoodman@aol.com,wknd.gemerine@aol.com,rafmail1981@aol.com,tonovichivanenaki@aol.com,hetland.ari@aol.com,mateusiversen@aol.com,lacerdaraffaello@aol.com,anasida76@aol.com,liamolinari@aol.com,sen70zib@aol.com,mezeiderrick@aol.com,stanisl49avchic@aol.com,damcvrobaneuron@aol.com,suyzanna_fleona@aol.com,dxealing.dissa@aol.com,hogg.karen@aol.com,obocharovamarina@aol.com,buchholzjohann@aol.com,orn.cecchini@aol.com,percivaltorgersen@aol.com,candalgudrun@aol.com,filimonis.76@aol.com,bengann_100@aol.com,axelhanne@aol.com,tiffanylarochelle@aol.com,nicoleta.r@aol.com,eichenbaum.1963@aol.com,kotensasharev@aol.com,samognat32@aol.com,edem_headshot@aol.com,kozmakuzmich1960@aol.com,damonsvensson@aol.com,anders.riva@aol.com,caiminwei123@gmail.com,yulingguo086@gmail.com,yingxiaolu086@gmail.com,lijiazhen0035@gmail.com,fangp370@gmail.com,huangyayu10086@gmail.com,fuziyuan110@gmail.com,xinyingdu886@gmail.com,yasiaforever.1971@aol.com,lukaszfidalgo@aol.com,zaichi29@aol.com,prostotakitak.1974@aol.com,mo90nroe@aol.com,blonde.87@aol.com,dimidrol.1969@aol.com"
@@ -64,9 +81,10 @@ def find_from_mail(param) -> str:
class MailReader:
"""邮件读取器类"""
def __init__(self, login: str, password: str):
def __init__(self, login: str, password: str, proxy: Optional[ProxyConfig] = None):
self.login = login
self.password = password
self.proxy = proxy
@staticmethod
def show_folders(imap) -> List[str]:
@@ -90,7 +108,43 @@ class MailReader:
def read_emails(self, mails_messages: List[MailPojo]) -> List[MailPojo]:
"""读取邮件"""
imap = create_imap(self.login)
# ── GMX账户 → 使用代理连接(失败自动重试最多3次)──
if is_gmx_account(self.login) and self.proxy is not None:
return self._read_emails_with_proxy_retry(mails_messages)
else:
return self._read_emails_internal(create_imap(self.login), mails_messages)
def _read_emails_with_proxy_retry(
self,
mails_messages: List[MailPojo],
max_retries: int = 3,
) -> List[MailPojo]:
"""通过 ProxyIMAPClient 读取 GMX 邮件,失败时最多重试 max_retries 次。"""
imap_server = get_imap_server(self.login)
last_error: Optional[Exception] = None
for attempt in range(1, max_retries + 1):
try:
print("[GMX-Proxy] {}{} via {} (tentative {}/{})".format(
self.login, imap_server, self.proxy, attempt, max_retries))
imap = ProxyIMAPClient(
host=imap_server,
proxy=self.proxy,
use_uid=True,
ssl=True,
)
return self._read_emails_internal(imap, mails_messages)
except Exception as exc:
last_error = exc
print("[GMX-Proxy] Échec tentative {}/{} pour {} : {}".format(
attempt, max_retries, self.login, exc))
print("[GMX-Proxy] Toutes les tentatives ont échoué pour {} : {}".format(
self.login, last_error))
return []
def _read_emails_internal(self, imap, mails_messages: List[MailPojo]) -> List[MailPojo]:
"""Logique commune de lecture des emails (IMAPClient ou imaplib)."""
is_imap_client = isinstance(imap, IMAPClient)
# 登录邮箱
@@ -351,7 +405,11 @@ def need_to_check_email(mail: str, successful_items) -> bool:
return len(validated_items) == 0
def find_links_to_validate_from_mail_list(mail_list: List[MailAddress], logger) -> None:
def find_links_to_validate_from_mail_list(
mail_list: List[MailAddress],
logger,
proxy: Optional[ProxyConfig] = None,
) -> None:
"""从邮件列表中查找需要验证的链接"""
if not mail_list:
return
@@ -369,7 +427,7 @@ def find_links_to_validate_from_mail_list(mail_list: List[MailAddress], logger)
for mail in mail_list:
# 检查是否需要读取邮件
if need_to_check_email(mail.mail, successful_items):
mail_reader = MailReader(mail.mail, mail.password)
mail_reader = MailReader(mail.mail, mail.password, proxy=proxy)
future = executor.submit(mail_reader.read_emails, mails_messages)
futures.append(future)
@@ -411,8 +469,8 @@ def find_links_to_validate_from_mail_list(mail_list: List[MailAddress], logger)
if __name__ == '__main__':
# 读取联系人列表
contact_to_book_list = read_contacts(
file_name="~/Desktop/contact_list_2025-11-28.xlsx")
# file_name="~/Desktop/contact_list_all.xlsx")
file_name="~/Desktop/contact_list_2026-03-05.xlsx")
# file_name="~/Desktop/contact_list_2025-11-28.xlsx")
# file_name="~/Desktop/contact_list_2025-11-06.xlsx")
# 获取目标邮箱列表
@@ -427,7 +485,6 @@ if __name__ == '__main__':
# 设置日志记录器
logger = logging.getLogger()
# 获取已验证的链接列表
_all_links = MONGO_STORE_MANAGER.get_links_to_validate()
@@ -440,6 +497,14 @@ if __name__ == '__main__':
_to_add = False
if _to_add:
filter_mail.append(mail_pojo)
# filter_mail = [MailAddress("utatapi@gmx.net", "RSAzHAFek8s")]
# filter_mail = [MailAddress("birgitnaya@gmx.net", "XEeUF3Y1yaO")]
# 配置代理(GMX账号必须通过代理读取)
gmx_proxy = ProxyConfig(
host=os.environ.get("GMX_PROXY_HOST", ""),
port=int(os.environ.get("GMX_PROXY_PORT", "443")),
proxy_type=os.environ.get("GMX_PROXY_TYPE", "SOCKS5"),
username=os.environ.get("GMX_PROXY_USERNAME"),
password=os.environ.get("GMX_PROXY_PASSWORD"),
)
# 处理邮件
find_links_to_validate_from_mail_list(filter_mail, logger)
find_links_to_validate_from_mail_list(filter_mail, logger, proxy=gmx_proxy)