try to use proxy for gmx mail

This commit is contained in:
2026-03-28 23:25:07 +01:00
parent b7f12bcbc8
commit 9802848c5f
9 changed files with 647 additions and 205 deletions
-140
View File
@@ -1,140 +0,0 @@
import datetime
import email
import imaplib
import uuid
from concurrent.futures import ThreadPoolExecutor
from email.header import decode_header
from email.message import Message
from builtins import list
from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.logs.AppLogging import init_logger
from src.mail.mail_constants import DOMAIN_163, DOMAIN_YAHOO, DOMAIN_SINA, IMAP_SERVER_163, YAHOO_IMAP_SERVER, \
IMAP_SERVER_SINA, AOL_IMAP_SERVER, create_imap
from src.pojo.accepted_appointment_pojo import AcceptedAppointmentPojo
from src.pojo.mail.mail_pojo import MailPojo
INVOICE_SUBJECT_fr = 'Votre facture'
INVOICE_SUBJECT_EN = 'Your invoice'
VALIDATION_URL_REGEX = """https:\/\/rendezvousparis.hermes.com\/client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"""
HERMES_INVOICE_EMAIL = "no-reply@hermes.com"
date_format = "%d-%b-%Y" # DD-Mon-YYYY e.g., 3-Mar-2014
class InvoiceGetter():
def __init__(self, login, password):
self.login = login
self.password = password
@staticmethod
def show_folders(imap):
for i in imap.list()[1]:
l = i.decode().split(' "/" ')
print(l[0] + " = " + l[1])
def read_emails(self, mails_messages: list) -> list:
imap = create_imap(self.login)
# authenticate
type, dat = imap.login(self.login, self.password)
mail_list = []
print("read mails from {}".format(self.login))
# self.show_folders(imap)
# total number of emails
# get mails from inbox
# (\Archive \HasNoChildren) = "Archive"
# (\Junk \HasNoChildren) = "Bulk"
# (\Drafts \HasNoChildren) = "Draft"
# (\HasNoChildren) = "Inbox"
# (\Sent \HasNoChildren) = "Sent"
# (\Trash \HasNoChildren) = "Trash"
mail_list.extend(self._get_messages_from_folder(imap, subject=INVOICE_SUBJECT_fr))
mail_list.extend(self._get_messages_from_folder(imap, subject=INVOICE_SUBJECT_EN))
# mail_list.extend(self._get_messages_from_folder(imap, folder="Bulk"))
# close the connection and logout
imap.close()
imap.logout()
mails_messages.extend(mail_list)
return mail_list
def _get_messages_from_folder(self, imap, subject, folder="INBOX") -> list:
imap.select(folder)
mail_messages = []
typ, data = imap.search(None, '(SUBJECT "{}" SINCE "{}")'.format(subject, datetime.datetime.today().strftime(
date_format)))
for i in data[0].split():
# fetch the email message by ID
res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)")
body = ''
for response in msg:
if isinstance(response, tuple):
# parse a bytes email into a message object
msg = email.message_from_bytes(response[1])
# decode the email subject
subject, subject_encoded = decode_header(msg["Subject"])[0]
received_date = msg["Date"]
if isinstance(subject, bytes):
# if it's a bytes, decode to str
subject = subject.decode(subject_encoded)
# decode email sender
from_address, subject_encoded = decode_header(msg.get("From"))[0]
if isinstance(from_address, bytes):
from_address = from_address.decode(subject_encoded)
print("From:", from_address)
print("Subject:", subject)
# if the email message is multipart
if msg.is_multipart():
# iterate over email parts
for part in msg.walk():
try:
# get the email body
payloads = part.get_payload()
if isinstance(payloads, list):
for payload in payloads:
if isinstance(payload, Message):
if payload.get_content_type() == 'text/html':
body = body + payload.get_payload(decode=True).decode("iso-8859-1")
elif payload.get_content_type() == 'application/pdf':
# save to pdf
open("./" + self.login + str(uuid.uuid4()) + '.pdf', 'wb').write(
payload.get_payload(decode=True))
# print(body)
except Exception as Error:
print(Error)
else:
body = msg.get_payload(decode=True).decode()
print(body)
if INVOICE_SUBJECT_fr in subject or INVOICE_SUBJECT_EN in subject:
mail = MailPojo(subject=subject, body=body, from_address=from_address)
mail_messages.append(mail)
return mail_messages
def get_invoices():
# get email address
mail_list = MONGO_STORE_MANAGER.get_destination_emails()
mail_list_to_check = []
# yesterday = str(datetime.date.today() - datetime.timedelta(days=2))
yesterday = str(datetime.date.today())
collection = MONGO_STORE_MANAGER.get_accepted_items_for_one_day(yesterday)
for valid_appointment in collection:
accepted_pojo = AcceptedAppointmentPojo.from_reserve(valid_appointment)
for mail in mail_list:
if mail.mail == accepted_pojo.email:
mail_list_to_check.append(mail)
# mail_list = [mail_address1]
mails_messages = []
with ThreadPoolExecutor(max_workers=20) as executor:
for mail in mail_list_to_check:
# check whether we need to read mail
mail_reader = InvoiceGetter(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages)
# check whether the url has already been clicked
if __name__ == '__main__':
init_logger()
get_invoices()
+534
View File
@@ -0,0 +1,534 @@
"""
imap_proxy_reader.py
====================
Lire des emails via IMAPClient en passant par un proxy SOCKS5/SOCKS4/HTTP.
Fonctionnement :
- ProxyIMAP4_TLS : sous-classe de imaplib.IMAP4 qui ouvre la socket
à travers un proxy SOCKS via PySocks.
- ProxyIMAPClient : sous-classe de IMAPClient qui injecte ProxyIMAP4_TLS
au lieu de la connexion directe habituelle.
Dépendances :
pip install imapclient PySocks
"""
import datetime
import email
import imaplib
import io
import logging
import os
import re
import ssl
import socket
from dataclasses import dataclass, field
from email.message import Message
from typing import List, Optional, Tuple
import socks
from dotenv import load_dotenv
from imapclient import IMAPClient
load_dotenv()
# ──────────────────────────────────────────────────────────────
# Constantes
# ──────────────────────────────────────────────────────────────
VALIDATION_URL_SUBJECT_FR = "Validation de votre demande de rendez-vous"
VALIDATION_URL_SUBJECT_EN = "Please confirm your appointment request"
VALIDATION_URL_REGEX = (
r"https:\/\/rendezvousparis\.hermes\.com"
r"\/client\/register\/[A-Z0-9]+\/validate\.code=[A-Z0-9]+"
)
DATE_FORMAT = "%d-%b-%Y"
# Correspondance domaine → serveur IMAP (identique à mail_constants.py)
IMAP_SERVER_MAP: List[Tuple[str, str]] = [
("163.com", "imap.163.com"),
("yahoo.com", "imap.mail.yahoo.com"),
("firemail.de", "imap.firemail.de"),
("gmail.com", "imap.gmail.com"),
("sina.com", "imap.sina.com"),
("hotmail.com", "outlook.office365.com"),
("outlook.com", "outlook.office365.com"),
("rambler.ru", "imap.rambler.ru"),
("btvm.ne.jp", "imap.btvm.ne.jp"),
("mars.dti.ne.jp", "imap.cm.dream.jp"),
("aurora.dti.ne.jp", "imap.cm.dream.jp"),
("naver.com", "imap.naver.com"),
("onet.pl", "imap.poczta.onet.pl"),
("gazeta.pl", "imap.gazeta.pl"),
("tim.it", "imap.tim.it"),
("alice.it", "in.alice.it"),
("gmx.com", "imap.gmx.com"),
("gmx.fr", "imap.gmx.com"),
("gmx.us", "imap.gmx.com"),
("gmx.ch", "imap.gmx.com"),
("gmx.pt", "imap.gmx.com"),
("gmx.sg", "imap.gmx.com"),
("gmx.net", "imap.gmx.net"),
("gmx.de", "imap.gmx.net"),
("gmx.at", "imap.gmx.at"),
("web.de", "imap.web.de"),
("inbox.lv", "mail.inbox.lv"),
("pissmail.com", "mail.pissmail.com"),
("incel.email", "mail.pissmail.com"),
("shitposting.expert","mail.pissmail.com"),
("hatesje.ws", "mail.pissmail.com"),
("child.pizza", "mail.pissmail.com"),
("genocide.fun", "mail.pissmail.com"),
("dmc.chat", "mail.pissmail.com"),
("aol.com", "imap.aol.com"), # fallback AOL
]
PROXY_TYPE_MAP = {
"SOCKS5": socks.SOCKS5,
"SOCKS4": socks.SOCKS4,
"HTTP": socks.HTTP,
}
logger = logging.getLogger(__name__)
# ──────────────────────────────────────────────────────────────
# Modèles de données
# ──────────────────────────────────────────────────────────────
@dataclass
class ProxyConfig:
"""Configuration du proxy."""
host: str
port: int
proxy_type: str = "SOCKS5" # "SOCKS5" | "SOCKS4" | "HTTP"
username: Optional[str] = None
password: Optional[str] = None
@property
def socks_type(self) -> int:
t = self.proxy_type.upper()
if t not in PROXY_TYPE_MAP:
raise ValueError(f"proxy_type invalide : {self.proxy_type!r}. "
f"Valeurs autorisées : {list(PROXY_TYPE_MAP)}")
return PROXY_TYPE_MAP[t]
def __repr__(self) -> str:
auth = f"{self.username}:***@" if self.username else ""
return f"{self.proxy_type}://{auth}{self.host}:{self.port}"
@dataclass
class MailAccount:
"""Compte email à lire."""
login: str
password: str
@dataclass
class MailResult:
"""Résultat d'une lecture d'email."""
account: str
subject: str
from_address: str
to_address: str
body: str
validation_urls: List[str] = field(default_factory=list)
# ──────────────────────────────────────────────────────────────
# Connexion IMAP via proxy (bas niveau)
# ──────────────────────────────────────────────────────────────
class ProxyIMAP4_TLS(imaplib.IMAP4):
"""
Variante TLS de imaplib.IMAP4 qui route la connexion
à travers un proxy SOCKS5/SOCKS4/HTTP grâce à PySocks.
"""
def __init__(
self,
host: str,
port: int,
ssl_context: Optional[ssl.SSLContext],
proxy: ProxyConfig,
timeout: Optional[float] = None,
):
self._ssl_context = ssl_context
self._proxy = proxy
self._timeout = timeout
# imaplib.IMAP4.__init__ appelle self.open()
imaplib.IMAP4.__init__(self, host, port)
self.file: io.BufferedReader
def open(self, host: str = "", port: int = 993, timeout: Optional[float] = None) -> None:
self.host = host
self.port = port
effective_timeout = timeout if timeout is not None else self._timeout
# ── Créer la socket SOCKS ────────────────────────────
sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
sock.set_proxy(
proxy_type=self._proxy.socks_type,
addr=self._proxy.host,
port=self._proxy.port,
username=self._proxy.username,
password=self._proxy.password,
)
if effective_timeout:
sock.settimeout(effective_timeout)
sock.connect((host, port))
# ── Envelopper avec SSL/TLS ──────────────────────────
ctx = self._ssl_context or ssl.create_default_context()
self.sock = ctx.wrap_socket(sock, server_hostname=host)
self.file = self.sock.makefile("rb")
# ── Méthodes requises par imaplib.IMAP4 ─────────────────
def read(self, size: int) -> bytes:
return self.file.read(size) # type: ignore[return-value]
def readline(self) -> bytes:
return self.file.readline() # type: ignore[return-value]
def send(self, data) -> None:
self.sock.sendall(data)
def shutdown(self) -> None:
imaplib.IMAP4.shutdown(self)
# ──────────────────────────────────────────────────────────────
# IMAPClient avec proxy
# ──────────────────────────────────────────────────────────────
class ProxyIMAPClient(IMAPClient):
"""
Sous-classe d'IMAPClient qui utilise un proxy SOCKS/HTTP.
Usage :
proxy = ProxyConfig(host="127.0.0.1", port=1080, proxy_type="SOCKS5")
client = ProxyIMAPClient("imap.gmail.com", proxy=proxy, use_uid=True)
client.login("user@gmail.com", "password")
"""
def __init__(self, host: str, proxy: ProxyConfig, **kwargs):
self._proxy = proxy
super().__init__(host, **kwargs)
def _create_IMAP4(self):
"""Remplace la méthode d'IMAPClient pour injecter ProxyIMAP4_TLS."""
if self.ssl:
return ProxyIMAP4_TLS(
host=self.host,
port=self.port,
ssl_context=self.ssl_context,
proxy=self._proxy,
timeout=getattr(self._timeout, "connect", None),
)
# Connexion non-SSL à travers le proxy (rare, mais supporté)
# On monkey-patch juste la connexion TCP
raise NotImplementedError(
"Connexion IMAP non-SSL via proxy non implémentée. "
"Utilisez ssl=True (port 993)."
)
# ──────────────────────────────────────────────────────────────
# Fonctions utilitaires
# ──────────────────────────────────────────────────────────────
def get_imap_server(login: str) -> str:
"""Retourne le serveur IMAP correspondant au domaine du login."""
login_lower = login.lower()
for domain, server in IMAP_SERVER_MAP:
if domain in login_lower:
return server
return "imap.aol.com" # fallback
def extract_body(email_message: Message) -> str:
"""Extrait le corps HTML ou texte d'un email."""
body = ""
for part in email_message.walk():
content_type = part.get_content_type()
try:
if content_type == "text/html":
payload = part.get_payload(decode=True)
if payload:
body += payload.decode("utf-8", errors="ignore")
elif content_type == "text/plain":
payload = part.get_payload()
if payload:
body += str(payload)
except Exception as exc:
logger.warning("Erreur extraction body : %s", exc)
return body
def find_validation_urls(text: str) -> List[str]:
"""Recherche toutes les URLs de validation Hermes dans un texte."""
return re.findall(VALIDATION_URL_REGEX, text)
# ──────────────────────────────────────────────────────────────
# Lecteur principal
# ──────────────────────────────────────────────────────────────
class ProxyMailReader:
"""
Lit les emails d'un compte via IMAPClient en passant par un proxy.
Paramètres
----------
account : MailAccount
Identifiants du compte email.
proxy : ProxyConfig
Configuration du proxy.
timeout : float, optional
Timeout de connexion en secondes (défaut : 30 s).
"""
def __init__(
self,
account: MailAccount,
proxy: ProxyConfig,
timeout: float = 30.0,
):
self.account = account
self.proxy = proxy
self.timeout = timeout
# ── Connexion ────────────────────────────────────────────
def _connect(self) -> ProxyIMAPClient:
imap_server = get_imap_server(self.account.login)
logger.info(
"[%s] Connexion via %s%s:993",
self.account.login, self.proxy, imap_server,
)
client = ProxyIMAPClient(
host=imap_server,
proxy=self.proxy,
use_uid=True,
ssl=True,
timeout=self.timeout,
)
client.login(self.account.login, self.account.password)
logger.info("[%s] Connecté.", self.account.login)
return client
# ── Lecture des dossiers ─────────────────────────────────
def _list_folders(self, client: ProxyIMAPClient) -> List[str]:
return [info[-1] for info in client.list_folders()]
# ── Lecture des messages ─────────────────────────────────
def _read_folder(
self,
client: ProxyIMAPClient,
folder: str,
since: Optional[datetime.datetime] = None,
) -> List[MailResult]:
results: List[MailResult] = []
since = since or datetime.datetime.today()
try:
client.select_folder(folder, readonly=True)
except Exception as exc:
logger.warning("[%s] Impossible d'ouvrir '%s' : %s",
self.account.login, folder, exc)
return results
try:
uids = client.search(["SINCE", since])
except Exception as exc:
logger.warning("[%s] Recherche échouée dans '%s' : %s",
self.account.login, folder, exc)
return results
if not uids:
return results
logger.info("[%s] %d message(s) dans '%s'",
self.account.login, len(uids), folder)
for uid, msg_data in client.fetch(uids, "RFC822").items():
try:
raw = msg_data.get(b"RFC822") or msg_data.get("RFC822")
if raw is None:
continue
em = email.message_from_bytes(raw)
subject = em.get("Subject", "")
from_addr = em.get("From", "")
to_addr = em.get("To", self.account.login)
# Filtrer : on ne garde que les emails de validation Hermes
is_validation = (
VALIDATION_URL_SUBJECT_FR in subject
or VALIDATION_URL_SUBJECT_EN in subject
or "no-reply@hermes.com" in from_addr.lower()
)
if not is_validation:
continue
body = extract_body(em)
urls = find_validation_urls(body)
result = MailResult(
account=self.account.login,
subject=subject,
from_address=from_addr,
to_address=to_addr,
body=body,
validation_urls=urls,
)
results.append(result)
logger.info(
"[%s] Email de validation trouvé (uid=%s) — URLs : %s",
self.account.login, uid, urls or "aucune",
)
except Exception as exc:
logger.warning(
"[%s] Erreur traitement uid=%s : %s",
self.account.login, uid, exc,
)
return results
# ── Point d'entrée public ────────────────────────────────
def read(
self,
since: Optional[datetime.datetime] = None,
skip_folders: Optional[List[str]] = None,
) -> List[MailResult]:
"""
Se connecte au serveur IMAP via le proxy et retourne la liste
des emails de validation trouvés depuis `since` (aujourd'hui par défaut).
Paramètres
----------
since : datetime, optional — date de début de recherche
skip_folders : list[str], optional — dossiers à ignorer
(défaut : ["Sent", "Drafts", "Trash", "Junk", "Spam"])
"""
if skip_folders is None:
skip_folders = ["Sent", "Drafts", "Trash", "Junk", "Spam"]
all_results: List[MailResult] = []
client = self._connect()
try:
folders = self._list_folders(client)
logger.info("[%s] Dossiers : %s", self.account.login, folders)
for folder in folders:
if folder in skip_folders:
logger.debug("[%s] Dossier ignoré : %s",
self.account.login, folder)
continue
all_results.extend(self._read_folder(client, folder, since))
finally:
try:
client.logout()
except Exception:
pass
return all_results
# ──────────────────────────────────────────────────────────────
# Lecture parallèle de plusieurs comptes
# ──────────────────────────────────────────────────────────────
from concurrent.futures import ThreadPoolExecutor, as_completed
def read_multiple_accounts(
accounts: List[MailAccount],
proxy: ProxyConfig,
since: Optional[datetime.datetime] = None,
max_workers: int = 10,
timeout: float = 30.0,
) -> List[MailResult]:
"""
Lit plusieurs comptes email en parallèle via le même proxy.
Retourne la liste consolidée de tous les MailResult trouvés.
"""
all_results: List[MailResult] = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
future_map = {
executor.submit(
ProxyMailReader(acc, proxy, timeout).read, since
): acc.login
for acc in accounts
}
for future in as_completed(future_map):
login = future_map[future]
try:
results = future.result()
logger.info("[%s] %d email(s) de validation récupéré(s).",
login, len(results))
all_results.extend(results)
except Exception as exc:
logger.error("[%s] Erreur : %s", login, exc)
return all_results
# ──────────────────────────────────────────────────────────────
# Point d'entrée — exemple d'utilisation
# ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)-8s %(message)s",
datefmt="%H:%M:%S",
)
# ── 1. Configurer le proxy ───────────────────────────────
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"),
)
# ── 2. Définir les comptes à lire ────────────────────────
accounts = [
MailAccount(login="birgitnaya@gmx.net", password="XEeUF3Y1yaO"),
# MailAccount(login="user@gmail.com", password="apppassword"),
# MailAccount(login="user@outlook.com", password="password"),
]
# ── 3. Lancer la lecture ─────────────────────────────────
results = read_multiple_accounts(
accounts=accounts,
proxy=proxy,
since=datetime.datetime.today(),
max_workers=5,
timeout=30.0,
)
# ── 4. Afficher les résultats ────────────────────────────
print(f"\n{'='*60}")
print(f" {len(results)} email(s) de validation trouvé(s)")
print(f"{'='*60}\n")
for r in results:
print(f" Compte : {r.account}")
print(f" De : {r.from_address}")
print(f" Sujet : {r.subject}")
print(f" URLs : {r.validation_urls or 'aucune'}")
print(f" {'-'*56}")
+2 -2
View File
@@ -126,5 +126,5 @@ def check_mails():
if __name__ == '__main__': if __name__ == '__main__':
# remove_invalid_email() remove_invalid_email()
check_mails() # check_mails()
+19 -9
View File
@@ -11,7 +11,9 @@ from imapclient import IMAPClient
from src.db.mirgration.migration_tools import migre_accepted_appointment from src.db.mirgration.migration_tools import migre_accepted_appointment
from src.db.mongo_manager import MONGO_STORE_MANAGER from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.mail.mail_constants import create_imap, show_folders from src.mail.mail_constants import create_imap, show_folders, is_gmx_address
from src.mail.mail_reader import get_gmx_proxy_config
from src.mail.imap_proxy_reader import ProxyMailReader, MailAccount, ProxyConfig
from src.notification.AcceptedResultPojo import get_accepted_result_from from src.notification.AcceptedResultPojo import get_accepted_result_from
from src.notification.mailer import Mailer from src.notification.mailer import Mailer
from src.pojo.ResultEnum import ResultEnum from src.pojo.ResultEnum import ResultEnum
@@ -26,6 +28,17 @@ date_format = "%d-%b-%Y" # DD-Mon-YYYY e.g., 3-Mar-2014
FRENCH_CONFIRMED_MESSAGE = "Nous aurons le plaisir de vous accueillir" FRENCH_CONFIRMED_MESSAGE = "Nous aurons le plaisir de vous accueillir"
def read_gmx_proxy_confirmation_emails(mail, mails_messages: list, proxy_config: ProxyConfig) -> None:
account = MailAccount(login=mail.mail, password=mail.password)
results = ProxyMailReader(account, proxy_config).read(since=datetime.datetime.today())
for result in results:
mail_pojo = MailPojo(subject=result.subject, body=result.body, from_address=result.from_address)
mail_pojo.mail_address = mail.mail
mail_pojo.to_address = result.to_address or mail.mail
mail_pojo.isImapClient = True
mails_messages.append(mail_pojo)
class MailConfirmationReader(): class MailConfirmationReader():
def __init__(self, login, password): def __init__(self, login, password):
self.login = login self.login = login
@@ -154,7 +167,7 @@ def accept_appointment_found(accepted_result_list: list):
for user in _all_register_account: for user in _all_register_account:
if user.mail == result.email: if user.mail == result.email:
result.account_password = user.password result.account_password = user.password
mailer.send_email(result, to_all=True) mailer.send_email(result, to_all=False)
MONGO_STORE_MANAGER.update_reserve_result(reserve.id, ResultEnum.ACCEPTED, reserve.message) MONGO_STORE_MANAGER.update_reserve_result(reserve.id, ResultEnum.ACCEPTED, reserve.message)
# sginal.send_result(result) # sginal.send_result(result)
@@ -181,13 +194,15 @@ def find_confirmation_contacts_for_today():
def find_confirmation_contacts_mail_list(mail_list): def find_confirmation_contacts_mail_list(mail_list):
# mail_list = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
mail_list.append(MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")) mail_list.append(MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@"))
mails_messages = [] mails_messages = []
gmx_proxy_config = get_gmx_proxy_config()
# read all the emails # read all the emails
with ThreadPoolExecutor(max_workers=200) as executor: with ThreadPoolExecutor(max_workers=200) as executor:
for mail in mail_list: for mail in mail_list:
# if DOMAIN_HOTMAIL not in mail.mail: if is_gmx_address(mail.mail) and gmx_proxy_config is not None:
executor.submit(read_gmx_proxy_confirmation_emails, mail, mails_messages, gmx_proxy_config)
else:
mail_reader = MailConfirmationReader(mail.mail, mail.password) mail_reader = MailConfirmationReader(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages) executor.submit(mail_reader.read_emails, mails_messages)
accepted_appointment_list = [] accepted_appointment_list = []
@@ -229,11 +244,6 @@ def read_mails_and_find_confirmation_contacts(all_mails=False):
else: else:
mail_list = find_confirmation_contacts_for_today() mail_list = find_confirmation_contacts_for_today()
return find_confirmation_contacts_mail_list(mail_list) return find_confirmation_contacts_mail_list(mail_list)
# mail_list.reverse()
# excel_reader = ExcelHelper()
# mail_list =excel_reader.read_email_pojo(file_name="/Users/lpan/Desktop/hotmail_list.xlsx")
# mail_address3 = MailAddress(mail="taibenchragu1978@onet.pl", password="2J)kyfNgyOZ")
# mail_list = [mail_address3]
# init_logger() # init_logger()
+17
View File
@@ -27,6 +27,23 @@ DOMAIN_NAVER = "naver.com"
DOMAIN_INBOX_LV = "inbox.lv" DOMAIN_INBOX_LV = "inbox.lv"
DOMAIN_GMX_DE = "gmx.de" DOMAIN_GMX_DE = "gmx.de"
GMX_DOMAINS = {
DOMAIN_GMX,
DOMAIN_GMX_NET,
DOMAIN_GMX_AT,
DOMAIN_GMX_FR,
DOMAIN_GMX_US,
DOMAIN_GMX_SG,
DOMAIN_GMX_CH,
DOMAIN_GMX_PT,
DOMAIN_GMX_DE,
}
def is_gmx_address(login: str) -> bool:
return any(domain in login for domain in GMX_DOMAINS)
DOMAIN_PISS_MAIL = "pissmail.com" DOMAIN_PISS_MAIL = "pissmail.com"
DOMAIN_INCEL_EMAIL = "incel.email" DOMAIN_INCEL_EMAIL = "incel.email"
DOMAIN_SHITPOSTING_EXPERT = "shitposting.expert" DOMAIN_SHITPOSTING_EXPERT = "shitposting.expert"
+35 -1
View File
@@ -1,6 +1,8 @@
import datetime import datetime
import email import email
import re import re
import os
from typing import Optional
from builtins import list from builtins import list
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from datetime import time from datetime import time
@@ -11,7 +13,8 @@ from imapclient import IMAPClient
from src.db.mongo_manager import MONGO_STORE_MANAGER from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.logs.AppLogging import init_logger from src.logs.AppLogging import init_logger
from src.mail.mail_constants import create_imap, show_folders from src.mail.mail_constants import create_imap, show_folders, is_gmx_address
from src.mail.imap_proxy_reader import ProxyMailReader, ProxyConfig, MailAccount
from src.pojo.mail.mail_pojo import MailPojo from src.pojo.mail.mail_pojo import MailPojo
from src.utils.timeutiles import is_time_between from src.utils.timeutiles import is_time_between
@@ -51,6 +54,33 @@ def find_from_mail(param):
return from_address.strip(" ").strip(">").strip("<") return from_address.strip(" ").strip(">").strip("<")
def get_gmx_proxy_config() -> Optional[ProxyConfig]:
host = os.environ.get("GMX_PROXY_HOST", "")
if not host:
return None
try:
port = int(os.environ.get("GMX_PROXY_PORT", "443"))
except ValueError:
port = 443
return ProxyConfig(
host=host,
port=port,
proxy_type=os.environ.get("GMX_PROXY_TYPE", "SOCKS5"),
username=os.environ.get("GMX_PROXY_USERNAME"),
password=os.environ.get("GMX_PROXY_PASSWORD"),
)
def read_gmx_proxy_emails(mail, mails_messages: list, proxy_config: ProxyConfig) -> None:
account = MailAccount(login=mail.mail, password=mail.password)
results = ProxyMailReader(account, proxy_config).read(since=datetime.datetime.today())
for result in results:
mail_pojo = MailPojo(subject=result.subject, body=result.body, from_address=result.from_address)
mail_pojo.mail_address = mail.mail
mail_pojo.to_address = result.to_address or mail.mail
mails_messages.append(mail_pojo)
class MailReader(): class MailReader():
def __init__(self, login, password): def __init__(self, login, password):
self.login = login self.login = login
@@ -241,6 +271,7 @@ def read_mails():
if is_time_between(time(7, 30), time(23, 30)): if is_time_between(time(7, 30), time(23, 30)):
# get email address # get email address
mail_list = MONGO_STORE_MANAGER.get_destination_emails() mail_list = MONGO_STORE_MANAGER.get_destination_emails()
gmx_proxy_config = get_gmx_proxy_config()
# excel_reader = ExcelHelper() # excel_reader = ExcelHelper()
# mail_list = excel_reader.read_email_pojo(file_name="/Users/panlei/Downloads/hotmail_list.xlsx") # mail_list = excel_reader.read_email_pojo(file_name="/Users/panlei/Downloads/hotmail_list.xlsx")
# mail_address1 = MailAddress(mail="casandrakaamv@onet.pl", password="8F0o0APeAp0z") # mail_address1 = MailAddress(mail="casandrakaamv@onet.pl", password="8F0o0APeAp0z")
@@ -251,6 +282,9 @@ def read_mails():
for mail in mail_list: for mail in mail_list:
# check whether we need to read mail # check whether we need to read mail
if need_to_check_email(mail.mail, successful_items): if need_to_check_email(mail.mail, successful_items):
if is_gmx_address(mail.mail) and gmx_proxy_config is not None:
executor.submit(read_gmx_proxy_emails, mail, mails_messages, gmx_proxy_config)
else:
mail_reader = MailReader(mail.mail, mail.password) mail_reader = MailReader(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages) executor.submit(mail_reader.read_emails, mails_messages)
# get ip_country info # get ip_country info
+12 -35
View File
@@ -11,8 +11,8 @@ from imapclient import IMAPClient
from src.db.mongo_manager import MONGO_STORE_MANAGER from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.logs.AppLogging import init_logger from src.logs.AppLogging import init_logger
from src.mail.mail_constants import DOMAIN_HOTMAIL, create_imap from src.mail.mail_constants import DOMAIN_HOTMAIL, create_imap, is_gmx_address
from src.mail.mail_reader import need_to_valid_url from src.mail.mail_reader import need_to_valid_url, get_gmx_proxy_config, read_gmx_proxy_emails
from src.pojo.mail.mail_pojo import MailPojo from src.pojo.mail.mail_pojo import MailPojo
from src.utils.excel_reader import read_contacts from src.utils.excel_reader import read_contacts
from src.utils.timeutiles import is_time_between from src.utils.timeutiles import is_time_between
@@ -262,6 +262,7 @@ def read_all_mails(contact_to_book_list=None):
if contact_to_book_list is None: if contact_to_book_list is None:
contact_to_book_list = MONGO_STORE_MANAGER.get_all_contact_to_book_list() contact_to_book_list = MONGO_STORE_MANAGER.get_all_contact_to_book_list()
mail_list = MONGO_STORE_MANAGER.get_destination_emails() mail_list = MONGO_STORE_MANAGER.get_destination_emails()
gmx_proxy_config = get_gmx_proxy_config()
mail_list_to_check = [] mail_list_to_check = []
for contact in contact_to_book_list: for contact in contact_to_book_list:
for mail in mail_list: for mail in mail_list:
@@ -273,6 +274,9 @@ def read_all_mails(contact_to_book_list=None):
for mail in mail_list_to_check: for mail in mail_list_to_check:
# check whether we need to read mail # check whether we need to read mail
if need_to_check_email(mail.mail, successful_items): if need_to_check_email(mail.mail, successful_items):
if is_gmx_address(mail.mail) and gmx_proxy_config is not None:
executor.submit(read_gmx_proxy_emails, mail, mails_messages, gmx_proxy_config)
else:
mail_reader = MailReader(mail.mail, mail.password) mail_reader = MailReader(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages) executor.submit(mail_reader.read_emails, mails_messages)
# 在读邮件时候,可能会有其他的约会提交或者约会的链接确认,所以需要刷新一下成功的列表 # 在读邮件时候,可能会有其他的约会提交或者约会的链接确认,所以需要刷新一下成功的列表
@@ -300,56 +304,29 @@ if __name__ == '__main__':
contact_to_book_list = read_contacts( contact_to_book_list = read_contacts(
# file_name="/Users/lpan/Desktop/contact_list_2025-01-16_yahoo_100.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-01-16_yahoo_100.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-15.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-03-15.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-24.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-15.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-21.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-20.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-14.xlsx")
# file_name="/Users/lpan/Desktop/contact_aol_200_2025-01-15.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-18.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-17.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-19.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-15.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-01-25.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-13.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-12.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-11.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-04.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-10.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-09.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-06.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-07.xlsx")
# file_name="/Users/lpan/Desktop/extracted_yahoo_contacts_129_24_03_win.xlsx") # file_name="/Users/lpan/Desktop/extracted_yahoo_contacts_129_24_03_win.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-04-02.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-04-02.xlsx")
# file_name="/Users/lpan/Desktop/extracted_aol_contacts_292_24_03_mac.xlsx") # file_name="/Users/lpan/Desktop/extracted_aol_contacts_292_24_03_mac.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_197_24_03.xlsx")x # file_name="/Users/lpan/Desktop/real_name_contacts_197_24_03.xlsx")x
# file_name="/Users/lpan/Desktop/contact_list_2025-03-29.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-03-29.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-31.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_21.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_10.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_14.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_19.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_22.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_2_win.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-29.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-03-29.xlsx")
# file_name="/Users/lpan/Desktop/17_18_04_to_test_win.xlsx") # file_name="/Users/lpan/Desktop/17_18_04_to_test_win.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_200_aol_win.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_200_aol_win.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_200_aol_mac.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_200_aol_mac.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_500_27_03_25_fixed_mac.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_500_27_03_25_fixed_mac.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-28_mac.xlsx") # file_name="/Users/panlei/Desktop/contact_list_2025-04-08.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-27_mac.xlsx") # file_name="/Users/panlei/Desktop/contact_list_2025-04-10.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-27_win.xlsx") # file_name="/Users/panlei/Desktop/contact_list_2024-10-02.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_1.xlsx") file_name="/Users/panlei/Desktop/contact_list_2025-08-18_no_ms.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_all_12.xlsx") # file_name="/Users/panlei/Desktop/real_name_contacts_200_gmx_ch_8_04_mac.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-04-05.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-04-05.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_400_aol_mac.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_400_aol_mac.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-04-07.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-04-07.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-04-05.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-04-05.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_100_gmx_ch_05_04_mac.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_100_gmx_ch_05_04_mac.xlsx")
file_name="/Users/lpan/Desktop/real_name_contacts_292_win.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_292_win.xlsx")
# file_name="/Users/lpan/Desktop/real_name_contacts_400_mac_04_04.xlsx") # file_name="/Users/lpan/Desktop/real_name_contacts_400_mac_04_04.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-04-01.xlsx") # file_name="/Users/lpan/Desktop/contact_list_2025-04-01.xlsx")
# file_name="/Users/lpan/Desktop/contact_list_2025-03-08_aol_400.xlsx")
read_all_mails(contact_to_book_list=contact_to_book_list) read_all_mails(contact_to_book_list=contact_to_book_list)
# read_all_mails() # read_all_mails()
+7 -7
View File
@@ -1,18 +1,18 @@
from mrz.generator.td1 import TD1CodeGenerator from mrz.generator.td1 import TD1CodeGenerator
first_name = "eryan" first_name = "kele"
last_name = "dai" last_name = "mi"
document_number = "XKJ0WSK30" document_number = "XKJ0WSK30"
birth_day = "951211" birth_day = "991125"
# sex = "F" sex = "F"
sex = "M" # sex = "M"
# optinal_data = "MFMLMANK<<<<A9" #14位 # optinal_data = "MFMLMANK<<<<A9" #14位
nationality = "CHN" nationality = "CHN"
country_code = "FRA" country_code = "FRA"
# optinal_data = "<E10805074" # 14位 # optinal_data = "<E10805074" # 14位
optinal_data = "<967343145" #总共11位,最前面那位为空,所以加< optinal_data = "<570873213" #总共11位,最前面那位为空,所以加<
document_prefix = "IR" document_prefix = "IR"
expire_date = "260815" expire_date = "290818"
if optinal_data is not None: if optinal_data is not None:
code = TD1CodeGenerator(document_prefix, country_code, document_number, birth_day, sex, expire_date, nationality, code = TD1CodeGenerator(document_prefix, country_code, document_number, birth_day, sex, expire_date, nationality,
last_name, first_name, optional_data1=optinal_data) last_name, first_name, optional_data1=optinal_data)
+10
View File
@@ -0,0 +1,10 @@
import math
def sanitize_excel_value(value):
if value is None:
return ""
if isinstance(value, float) and (math.isnan(value) or math.isinf(value)):
return ""
return value