diff --git a/app/ftp_processor.py b/app/ftp_processor.py index e4be213..3424f55 100644 --- a/app/ftp_processor.py +++ b/app/ftp_processor.py @@ -197,9 +197,19 @@ class _PlainFtpAdapter(_FtpAdapter): # SFTP (paramiko) # --------------------------------------------------------------------------- +SFTP_CONNECT_TIMEOUT = 15 # seconds +SFTP_BANNER_TIMEOUT = 15 +SFTP_AUTH_TIMEOUT = 30 + + class _SftpAdapter(_FtpAdapter): def __init__(self, server: str, port: int, username: str, password: str): - self.transport = paramiko.Transport((server, port)) + # Build socket with timeout to prevent hangs on unreachable hosts + import socket as _socket + sock = _socket.create_connection((server, port), timeout=SFTP_CONNECT_TIMEOUT) + self.transport = paramiko.Transport(sock) + self.transport.banner_timeout = SFTP_BANNER_TIMEOUT + self.transport.auth_timeout = SFTP_AUTH_TIMEOUT self.transport.connect(username=username, password=password) self.sftp = paramiko.SFTPClient.from_transport(self.transport) diff --git a/app/mail_processor.py b/app/mail_processor.py index 5aa55a3..7338e73 100644 --- a/app/mail_processor.py +++ b/app/mail_processor.py @@ -40,14 +40,18 @@ def _connect_imap(settings: dict) -> imaplib.IMAP4_SSL | imaplib.IMAP4: if use_ssl: ctx = ssl.create_default_context() - conn = imaplib.IMAP4_SSL(server, port, ssl_context=ctx) + conn = imaplib.IMAP4_SSL(server, port, ssl_context=ctx, timeout=IMAP_TIMEOUT) else: - conn = imaplib.IMAP4(server, port) + conn = imaplib.IMAP4(server, port, timeout=IMAP_TIMEOUT) conn.login(settings["imap_username"], settings["imap_password"]) return conn +SMTP_TIMEOUT = 30 # seconds - prevents hangs when SMTP server is unreachable +IMAP_TIMEOUT = 30 # seconds + + def _connect_smtp(settings: dict) -> smtplib.SMTP | smtplib.SMTP_SSL: server = settings["smtp_server"] port = int(settings.get("smtp_port", 587)) @@ -55,9 +59,9 @@ def _connect_smtp(settings: dict) -> smtplib.SMTP | smtplib.SMTP_SSL: if mode == "ssl": ctx = ssl.create_default_context() - conn = smtplib.SMTP_SSL(server, port, context=ctx) + conn = smtplib.SMTP_SSL(server, port, context=ctx, timeout=SMTP_TIMEOUT) else: - conn = smtplib.SMTP(server, port) + conn = smtplib.SMTP(server, port, timeout=SMTP_TIMEOUT) if mode == "starttls": ctx = ssl.create_default_context() conn.starttls(context=ctx)