From 1d1d72e737e8192c23273cc0ccaec98cc51bba25 Mon Sep 17 00:00:00 2001 From: agatha Date: Sat, 14 Mar 2026 15:32:31 -0400 Subject: [PATCH] feat: add SMTP notifier plugin --- .../plugins/builtin/notifiers/smtp.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/proxy_pool/plugins/builtin/notifiers/smtp.py diff --git a/src/proxy_pool/plugins/builtin/notifiers/smtp.py b/src/proxy_pool/plugins/builtin/notifiers/smtp.py new file mode 100644 index 0000000..b71639c --- /dev/null +++ b/src/proxy_pool/plugins/builtin/notifiers/smtp.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +from email.message import EmailMessage + +import aiosmtplib + +from proxy_pool.config import Settings +from proxy_pool.plugins.protocols import Event + + +class SmtpNotifier: + name = "smtp" + subscribes_to = [ + "proxy.pool_low", + "source.failed", + "credits.low_balance", + "credits.exhausted", + ] + + def __init__( + self, + host: str, + port: int, + user: str, + password: str, + to_address: str, + ) -> None: + self._host = host + self._port = port + self._user = user + self._password = password + self._to = to_address + + async def notify(self, event: Event) -> None: + msg = EmailMessage() + msg["Subject"] = f"[ProxyPool] {event.type}" + msg["From"] = self._user + msg["To"] = self._to + msg.set_content(self._format_body(event)) + + await aiosmtplib.send( + msg, + hostname=self._host, + port=self._port, + username=self._user, + password=self._password, + use_tls=True, + ) + + async def health_check(self) -> bool: + try: + client = aiosmtplib.SMTP( + hostname=self._host, + port=self._port, + ) + await client.connect() + await client.quit() + except Exception: + return False + else: + return True + + @staticmethod + def _format_body(event: Event) -> str: + lines = [ + f"Event: {event.type}", + f"Time: {event.timestamp.isoformat()}", + "", + ] + for key, value in event.payload.items(): + lines.append(f" {key}: {value}") + return "\n".join(lines) + + +def create_plugin(settings: Settings) -> SmtpNotifier | None: + notify = settings.notification + if not notify.smtp_host or not notify.smtp_user: + return None + + return SmtpNotifier( + host=notify.smtp_host, + port=notify.smtp_port, + user=notify.smtp_user, + password=notify.smtp_password or "", + to_address=notify.alert_email or notify.smtp_user, + )