From bf1c6688a82df5f6261a36cae51ad4832c4769bf Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Sat, 21 Sep 2024 06:05:13 +0500 Subject: [PATCH] enable logs --- relay.py | 58 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/relay.py b/relay.py index 2ebe104..a207cf2 100644 --- a/relay.py +++ b/relay.py @@ -1,5 +1,6 @@ import os import asyncio +import logging from aiosmtpd.controller import Controller from email.parser import BytesParser from email.policy import default @@ -7,11 +8,17 @@ import telegram import re import httpx +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + # Configuration TELEGRAM_API_KEY = os.getenv('TELEGRAM_API_KEY') DEFAULT_CHAT_ID = os.getenv('TELEGRAM_CHAT_ID') # Fallback chat ID NTFY_TOKEN = os.getenv('NTFY_TOKEN') NTFY_URL = os.getenv('NTFY_URL') +TELEGRAM_DOMAIN = os.getenv('TELEGRAM_DOMAIN', 'telegram.local') +NTFY_DOMAIN = os.getenv('NTFY_DOMAIN', 'ntfy.local') # SMTP configuration SMTP_HOST = '0.0.0.0' # Listen on all interfaces @@ -19,10 +26,12 @@ SMTP_PORT = 2525 # Alternative SMTP port class SMTPHandler: async def handle_RCPT(self, server, session, envelope, address, rcpt_options): + logger.info(f"Received RCPT command for address: {address}") envelope.rcpt_tos.append(address) return '250 OK' async def handle_DATA(self, server, session, envelope): + logger.info("Handling DATA command") parser = BytesParser(policy=default) message = parser.parsebytes(envelope.content) @@ -30,36 +39,58 @@ class SMTPHandler: body = message.get_body(preferencelist=('plain', 'html')).get_content() full_message = f"Subject: {subject}\n\n{body}" + logger.info(f"Parsed email - Subject: {subject}") + logger.debug(f"Email body: {body[:100]}...") # Log first 100 chars of body + # Extract destination from the recipient email address destination, service = self.extract_destination(envelope.rcpt_tos[0]) + logger.info(f"Extracted destination: {destination}, service: {service}") + if service == 'telegram': await self.send_telegram(destination, full_message) elif service == 'ntfy': await self.send_ntfy(destination, subject, body) else: - print(f"Invalid service: {service}. Message not sent.") + logger.error(f"Invalid service: {service}. Message not sent.") return '250 Message accepted for delivery' def extract_destination(self, email): - match = re.match(r'(.+)@(telegram|ntfy)$', email) - if match: - return match.group(1), match.group(2) - print(f"Invalid email format: {email}. Using default Telegram chat ID.") + logger.info(f"Extracting destination from email: {email}") + telegram_pattern = rf'^(.+)@{re.escape(TELEGRAM_DOMAIN)}$' + ntfy_pattern = rf'^(.+)@{re.escape(NTFY_DOMAIN)}$' + + telegram_match = re.match(telegram_pattern, email) + if telegram_match: + logger.info(f"Matched Telegram pattern: {telegram_match.group(1)}") + return telegram_match.group(1), 'telegram' + + ntfy_match = re.match(ntfy_pattern, email) + if ntfy_match: + logger.info(f"Matched ntfy pattern: {ntfy_match.group(1)}") + return ntfy_match.group(1), 'ntfy' + + logger.warning(f"Invalid email format: {email}. Using default Telegram chat ID.") return DEFAULT_CHAT_ID, 'telegram' async def send_telegram(self, chat_id, message): + logger.info(f"Sending message to Telegram chat ID: {chat_id}") bot = telegram.Bot(TELEGRAM_API_KEY) try: await bot.send_message(chat_id=chat_id, text=message) - print(f"Message sent to Telegram chat ID: {chat_id}") + logger.info(f"Message sent successfully to Telegram chat ID: {chat_id}") except telegram.error.BadRequest as e: - print(f"Failed to send message to Telegram chat ID: {chat_id}. Error: {str(e)}") - print("Attempting to send to default Telegram chat ID.") - await bot.send_message(chat_id=DEFAULT_CHAT_ID, text=message) + logger.error(f"Failed to send message to Telegram chat ID: {chat_id}. Error: {str(e)}") + logger.info("Attempting to send to default Telegram chat ID.") + try: + await bot.send_message(chat_id=DEFAULT_CHAT_ID, text=message) + logger.info(f"Message sent successfully to default Telegram chat ID: {DEFAULT_CHAT_ID}") + except telegram.error.BadRequest as e: + logger.error(f"Failed to send message to default Telegram chat ID. Error: {str(e)}") async def send_ntfy(self, topic, subject, body): + logger.info(f"Sending message to ntfy topic: {topic}") headers = { "Authorization": f"Bearer {NTFY_TOKEN}", "Title": subject, @@ -69,16 +100,19 @@ class SMTPHandler: try: response = await client.post(f"{NTFY_URL}/{topic}", content=body, headers=headers) response.raise_for_status() - print(f"Message sent to ntfy topic: {topic}") + logger.info(f"Message sent successfully to ntfy topic: {topic}") except httpx.HTTPStatusError as e: - print(f"Failed to send message to ntfy topic: {topic}. Error: {str(e)}") + logger.error(f"Failed to send message to ntfy topic: {topic}. Error: {str(e)}") async def start_smtp_server(): controller = Controller(SMTPHandler(), hostname=SMTP_HOST, port=SMTP_PORT) controller.start() if __name__ == '__main__': + logger.info(f"Starting SMTP server on {SMTP_HOST}:{SMTP_PORT}") + logger.info(f"Telegram domain: {TELEGRAM_DOMAIN}") + logger.info(f"ntfy domain: {NTFY_DOMAIN}") loop = asyncio.get_event_loop() loop.create_task(start_smtp_server()) - print(f"SMTP server started on {SMTP_HOST}:{SMTP_PORT}") + logger.info("SMTP server started. Waiting for incoming messages...") loop.run_forever()