Step 1: Install aiosmtpd library
pip install aiosmtpd
Step 2: The Modern Fake SMTP Server Script (aioserver.py)
import asyncio
from aiosmtpd.controller import Controller
from aiosmtpd.smtp import SMTP
# --- Define the Handler Class ---
# This class defines what happens when the server receives a message.
class DebuggingHandler:
"""
A modern asynchronous handler that processes and prints received emails.
"""
async def handle_DATA(self, server, session, envelope):
"""
Called when the server receives the full email data.
"""
print("\n=======================================================")
print(" !!! EMAIL SUCCESSFULLY RECEIVED by FAKE SERVER !!! ")
print("=======================================================")
print(f" - Client connected from: {session.peer}")
print(f" - MAIL FROM: {envelope.mail_from}")
print(f" - RCPT TO: {envelope.rcpt_tos}")
print("--- MESSAGE CONTENT START ---")
# 'envelope.content' contains the raw email message bytes.
# We decode it for display.
print(envelope.content.decode('utf8', errors='replace'))
print("--- MESSAGE CONTENT END ---")
print("=======================================================\n")
# Returning '250 OK' tells the client the message was accepted
return '250 OK'
# --- Startup Code ---
SERVER_IP = 'localhost'
SERVER_PORT = 1025
async def run_server():
"""
Starts the asynchronous SMTP server.
"""
handler = DebuggingHandler()
# The Controller handles starting and stopping the asyncio event loop.
controller = Controller(handler, hostname=SERVER_IP, port=SERVER_PORT)
# Start the server (it runs in the background)
controller.start()
print("Starting modern fake SMTP server...")
print(f"Listening on {SERVER_IP}:{SERVER_PORT}...")
print("Leave this window open.")
print("Press Ctrl+C to stop the server and exit.")
# Keep the main thread alive so the server can run
while True:
await asyncio.sleep(1)
if __name__ == "__main__":
try:
# Start the asyncio event loop
asyncio.run(run_server())
except KeyboardInterrupt:
print("\nModern fake server stopped.")
Step 3: The Client Script (client_script.py)
import smtplib
from email.mime.text import MIMEText
# Use the same IP and PORT as your fake_server.py
FAKE_SERVER_IP = 'localhost'
FAKE_SERVER_PORT = 1025
# --- Email Details ---
SENDER_EMAIL = 'my_modern_test_address@fake.com'
RECIPIENT_EMAIL = 'recipient_for_learning@test.org'
EMAIL_SUBJECT = 'Modern Test Email from Python smtplib'
EMAIL_BODY = (
"This message confirms my smtplib script is working against the modern aiosmtpd server.\n"
"No real email account was used!"
)
# --- Construct the Message ---
# MIMEText is used to properly format the email content and headers.
message = MIMEText(EMAIL_BODY, 'plain', 'utf-8')
message['Subject'] = EMAIL_SUBJECT
message['From'] = SENDER_EMAIL
message['To'] = RECIPIENT_EMAIL
# --- Send the Email using smtplib ---
try:
print(f"Attempting to connect to modern fake server at {FAKE_SERVER_IP}:{FAKE_SERVER_PORT}...")
# We use smtplib.SMTP for the simple, local connection
with smtplib.SMTP(FAKE_SERVER_IP, FAKE_SERVER_PORT) as server:
# Send the message data
server.send_message(message)
print("\n--- SUCCESS ---")
print("The email was successfully handed off to the modern fake server.")
print("Check your 'aioserver.py' terminal window for the full message content!")
except Exception as e:
print("\n--- ERROR ---")
print(f"An error occurred: {e}")
print("Ensure 'aioserver.py' is running in a separate terminal window and you ran 'pip install aiosmtpd'.")
Instructions:
Save the new server script as
aioserver.py.Save the client script as
client_script.py.Run the server in one terminal:
python aioserver.pyRun the client in a second terminal:
python client_script.py
Another script
fake_smtp.py
import asyncio
from aiosmtpd.controller import Controller
class DebugHandler:
async def handle_DATA(self, server, session, envelope):
print("\n===== NEW EMAIL RECEIVED =====")
print(f"From: {envelope.mail_from}")
print(f"To: {envelope.rcpt_tos}")
print("----- MESSAGE BODY -----")
print(envelope.content.decode("utf-8", errors="replace"))
print("===== END EMAIL =====\n")
return "250 Message accepted for delivery"
async def main():
handler = DebugHandler()
controller = Controller(handler, hostname="localhost", port=1025)
controller.start()
print("Fake SMTP server running on localhost:1025")
try:
await asyncio.Future() # Run the event loop forever
except KeyboardInterrupt:
controller.stop()
if __name__ == "__main__":
asyncio.run(main())
test_client.py
import smtplib
from email.mime.text import MIMEText
msg = MIMEText("Hello! This is a test email to the fake SMTP server.")
msg["Subject"] = "Test Email"
msg["From"] = "me@example.com"
msg["To"] = "you@example.com"
with smtplib.SMTP("localhost", 1025) as server:
server.send_message(msg)
print("Email sent!")
- Fake server doesn't support it
- Fake server doesn't require auth
-
localhost:1025
# No TLS, no login (fake server doesn't support it)
# connection.starttls() <-- remove
# connection.login(user=my_email, password=password) <-- remove
Note: This is AI generated and its only purpose is to help me and maybe someone else will find this useful as well.
Top comments (0)