class EmailForwardingHandler
SMTP message handler class that processes incoming email messages and forwards them using an EmailHandler instance while tracking server statistics.
/tf/active/vicechatdev/email-forwarder/src/forwarder/smtp_server.py
24 - 63
moderate
Purpose
EmailForwardingHandler serves as an SMTP protocol handler for the aiosmtpd library. It implements the necessary callback methods (handle_RCPT and handle_DATA) to receive and process incoming SMTP messages. The class maintains server statistics including connection counts and message counts, and delegates actual email processing to an EmailHandler instance. It's designed to be used with aiosmtpd.controller.Controller to create an SMTP server that receives emails and forwards them to configured destinations.
Source Code
class EmailForwardingHandler:
"""Handler for incoming SMTP messages."""
def __init__(self):
"""Initialize the handler."""
self.email_handler = EmailHandler()
self.server_stats = {
'connections': 0,
'messages_received': 0,
'start_time': None
}
async def handle_RCPT(self, server, session, envelope, address, rcpt_options):
"""Handle RCPT TO command."""
logger.debug(f"RCPT TO: {address}")
if not envelope.rcpt_tos:
envelope.rcpt_tos = []
envelope.rcpt_tos.append(address)
return '250 OK'
async def handle_DATA(self, server, session, envelope):
"""Handle email message data."""
try:
self.server_stats['messages_received'] += 1
logger.info(f"Received email from {envelope.mail_from} to {envelope.rcpt_tos}")
# Process the email in a separate thread to avoid blocking
success = self.email_handler.process_email(envelope, envelope.content)
if success:
logger.info("Email forwarded successfully")
return '250 Message accepted for delivery'
else:
logger.error("Failed to forward email")
return '451 Temporary failure in forwarding'
except Exception as e:
logger.error(f"Error handling email data: {e}")
return '451 Temporary failure'
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
- | - |
Parameter Details
__init__: The constructor takes no parameters. It initializes an EmailHandler instance for processing emails and sets up a server_stats dictionary to track connections, messages received, and start time.
Return Value
Instantiation returns an EmailForwardingHandler object. The handle_RCPT method returns a string SMTP response code ('250 OK'). The handle_DATA method returns string SMTP response codes: '250 Message accepted for delivery' on success, '451 Temporary failure in forwarding' on forwarding failure, or '451 Temporary failure' on exception.
Class Interface
Methods
__init__(self) -> None
Purpose: Initialize the EmailForwardingHandler with an EmailHandler instance and empty server statistics
Returns: None
async handle_RCPT(self, server, session, envelope, address, rcpt_options) -> str
Purpose: Handle the SMTP RCPT TO command by adding recipient addresses to the envelope
Parameters:
server: The aiosmtpd server instancesession: The SMTP session object containing connection informationenvelope: The email envelope object that accumulates message metadataaddress: The recipient email address from the RCPT TO commandrcpt_options: Additional RCPT command options from the SMTP protocol
Returns: SMTP response code string '250 OK' indicating successful recipient acceptance
async handle_DATA(self, server, session, envelope) -> str
Purpose: Handle the SMTP DATA command by processing the complete email message and forwarding it
Parameters:
server: The aiosmtpd server instancesession: The SMTP session object containing connection informationenvelope: The email envelope object containing mail_from, rcpt_tos, and content (message data)
Returns: SMTP response code string: '250 Message accepted for delivery' on success, '451 Temporary failure in forwarding' if forwarding fails, or '451 Temporary failure' on exception
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
email_handler |
EmailHandler | Instance of EmailHandler used to process and forward incoming email messages | instance |
server_stats |
dict | Dictionary tracking server statistics with keys: 'connections' (int), 'messages_received' (int), and 'start_time' (float or None) | instance |
Dependencies
asynciologgingaiosmtpdemailtypingemail_handlerconfigsysosforwardersignal
Required Imports
import asyncio
import logging
from aiosmtpd.controller import Controller
from email.message import EmailMessage
from typing import Optional
from email_handler import EmailHandler
from config import settings
import sys
import os
from forwarder.email_handler import EmailHandler
import signal
Usage Example
import asyncio
import logging
from aiosmtpd.controller import Controller
from email_handler import EmailHandler
from config import settings
# Setup logging
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
# Instantiate the handler
handler = EmailForwardingHandler()
# Initialize server stats
handler.server_stats['start_time'] = asyncio.get_event_loop().time()
# Use with aiosmtpd Controller
controller = Controller(handler, hostname='localhost', port=8025)
controller.start()
# The handler will now process incoming SMTP messages
# handle_RCPT is called for each recipient
# handle_DATA is called when message data is received
# Access statistics
print(f"Messages received: {handler.server_stats['messages_received']}")
print(f"Connections: {handler.server_stats['connections']}")
# Stop the controller when done
controller.stop()
Best Practices
- This class is designed to be used with aiosmtpd.controller.Controller as the handler parameter
- The server_stats['start_time'] should be set after instantiation to track server uptime
- Methods handle_RCPT and handle_DATA are async and should not be called directly; they are invoked by the aiosmtpd framework
- The class maintains state through server_stats, so a single instance should be used per SMTP server
- Error handling returns temporary failure codes (451) to allow clients to retry
- The email_handler.process_email call is synchronous and may block; consider running in executor for production use
- Ensure logger is configured at module level before instantiating this class
- The envelope object is provided by aiosmtpd and contains mail_from, rcpt_tos, and content attributes
- Server statistics are incremented automatically; access them via the server_stats attribute
- The class does not implement connection tracking; increment server_stats['connections'] externally if needed
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class EmailHandler 75.8% similar
-
class SMTPServer 73.9% similar
-
class TestEmailHandler 59.0% similar
-
function main_v9 56.3% similar
-
class TestSmtpServer 56.2% similar