Of course! Here is a comprehensive guide on how to create a Python mail sender, covering everything from simple scripts to more advanced, secure, and user-friendly applications.

We'll start with the most basic approach using Python's built-in libraries and then build up to a more robust solution using the popular smtplib and email libraries.
Part 1: The Simple & Direct Approach (Using smtplib)
This method is great for sending simple, text-only emails quickly.
Prerequisites: You need an SMTP Server
To send an email, you need an SMTP server. The most common way to get this is by using a free email provider like Gmail.
Important Note on Gmail Security: Google now blocks "less secure app" access by default. You need to either:

-
Use an App Password: This is the recommended method. It's a 16-digit password that gives an app permission to access your Gmail account.
- Go to your Google Account: https://myaccount.google.com/
- Go to Security.
- Make sure 2-Step Verification is ON. You cannot create an App Password without it.
- Under "Signing in to Google," click on App Passwords.
- Select "Mail" for the app and "Other (Custom name)" for the device, and name it "Python Mailer".
- Google will generate a 16-character password. Copy this password immediately. You won't be able to see it again.
-
Allow Less Secure Apps (Not Recommended): You can temporarily enable this, but it's less secure.
- Go to: https://myaccount.google.com/lesssecureapps
- Turn "Allow less secure apps" ON.
The Basic Code
This script sends an email from your Gmail account to another address.
import smtplib
from email.mime.text import MIMEText
# --- Configuration ---
# Use your Gmail address and the App Password you generated
sender_email = "your_email@gmail.com"
sender_password = "your_16_character_app_password" # IMPORTANT: Use the App Password here
receiver_email = "recipient_email@example.com"
subject = "Hello from Python!"
body = "This is a test email sent using Python's smtplib library."
# --- Create the Email Message ---
# The email needs to be formatted correctly
# We use MIMEText for the body of the email
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = sender_email
msg['To'] = receiver_email
# --- Send the Email ---
try:
# Connect to Gmail's SMTP server using SSL
# The port for SSL is 465
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp_server:
smtp_server.login(sender_email, sender_password)
smtp_server.sendmail(sender_email, receiver_email, msg.as_string())
print("Email sent successfully!")
except Exception as e:
print(f"Failed to send email. Error: {e}")
To run this script:

- Replace
"your_email@gmail.com","your_16_character_app_password", and"recipient_email@example.com"with your actual details. - Save the code as a
.pyfile (e.g.,send_email.py). - Run it from your terminal:
python send_email.py
Part 2: Sending More Advanced Emails (HTML & Attachments)
To send emails with HTML formatting or attachments, we need to use the email library more extensively.
Sending an HTML Email
HTML emails allow you to use styling, links, and images.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# --- Configuration ---
sender_email = "your_email@gmail.com"
sender_password = "your_16_character_app_password"
receiver_email = "recipient_email@example.com"
subject = "A Beautiful HTML Email"
# --- Create the HTML Body ---
html_body = """
<html>
<body>
<h1 style="color:blue;">This is an HTML Email!</h1>
<p>This paragraph has some <b>bold</b> and <i>italic</i> text.</p>
<p>Here is a link to <a href="https://www.python.org">Python's website</a>.</p>
</body>
</html>
"""
# --- Create the Multipart Message Container ---
# This allows us to combine different parts (like HTML and plain text)
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = sender_email
msg['To'] = receiver_email
# Attach the HTML and a plain text version (for clients that can't display HTML)
part1 = MIMEText("This is the plain text fallback.", 'plain')
part2 = MIMEText(html_body, 'html')
msg.attach(part1)
msg.attach(part2)
# --- Send the Email ---
try:
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp_server:
smtp_server.login(sender_email, sender_password)
smtp_server.sendmail(sender_email, receiver_email, msg.as_string())
print("HTML Email sent successfully!")
except Exception as e:
print(f"Failed to send email. Error: {e}")
Sending an Email with an Attachment
To attach a file, you need to encode it in base64.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os
# --- Configuration ---
sender_email = "your_email@gmail.com"
sender_password = "your_16_character_app_password"
receiver_email = "recipient_email@example.com"
subject = "Email with Attachment"
# --- File to Attach ---
# Make sure this file exists in the same directory as your script
filename = "my_document.pdf"
# --- Create the Message Container ---
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = sender_email
msg['To'] = receiver_email
# Attach the body (plain text)
body = "Please find the attached document."
msg.attach(MIMEText(body, 'plain'))
# --- Attach the File ---
# Open the file in binary mode
with open(filename, "rb") as attachment:
# Create a MIMEBase object and set the filename
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode the file in Base64
encoders.encode_base64(part)
# Add header to the attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",
)
# Attach the file part to the main message
msg.attach(part)
# --- Send the Email ---
try:
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp_server:
smtp_server.login(sender_email, sender_password)
smtp_server.sendmail(sender_email, receiver_email, msg.as_string())
print(f"Email with attachment '{filename}' sent successfully!")
except Exception as e:
print(f"Failed to send email. Error: {e}")
Part 3: Creating a Reusable Mail Sender Class
For cleaner and more reusable code, it's a great practice to encapsulate the logic in a class. This also makes it easy to switch between different providers (like Outlook or Yahoo) just by changing a few parameters.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os
class MailSender:
"""
A class to send emails using SMTP.
Supports plain text, HTML, and file attachments.
"""
def __init__(self, smtp_server, smtp_port, sender_email, sender_password):
"""
Initializes the MailSender with SMTP server details.
"""
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.sender_email = sender_email
self.sender_password = sender_password
def send_email(self, receiver_email, subject, body, is_html=False, attachments=None):
"""
Sends an email.
:param receiver_email: The recipient's email address.
:param subject: The subject of the email.
:param body: The body content of the email.
:param is_html: Boolean, True if body is HTML, False for plain text.
:param attachments: A list of file paths to attach.
"""
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = self.sender_email
msg['To'] = receiver_email
# Attach the body
msg.attach(MIMEText(body, 'html' if is_html else 'plain'))
# Attach files
if attachments:
for file_path in attachments:
if not os.path.exists(file_path):
print(f"Warning: Attachment file not found at {file_path}")
continue
with open(file_path, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename= {os.path.basename(file_path)}",
)
msg.attach(part)
try:
# Use SMTP_SSL for a secure connection
with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server:
server.login(self.sender_email, self.sender_password)
server.sendmail(self.sender_email, receiver_email, msg.as_string())
print(f"Email sent successfully to {receiver_email}!")
return True
except Exception as e:
print(f"Failed to send email. Error: {e}")
return False
# --- How to use the MailSender class ---
# 1. Create an instance for Gmail
gmail_sender = MailSender(
smtp_server="smtp.gmail.com",
smtp_port=465,
sender_email="your_email@gmail.com",
sender_password="your_16_character_app_password"
)
# 2. Define email details
receiver = "recipient_email@example.com"
subject = "Test from our new MailSender Class"
html_body = """
<h2>Testing the MailSender Class</h2>
<p>This email was sent using a <b>reusable Python class</b>.</p>
<p>It supports HTML and attachments!</p>
"""
# 3. Send the email
# You can provide a list of file paths to attach
# attachments = ["my_document.pdf", "image.png"]
gmail_sender.send_email(
receiver_email=receiver,
subject=subject,
body=html_body,
is_html=True,
# attachments=["my_document.pdf"] # Uncomment to test attachments
)
Summary of Key Concepts
| Concept | Description | Library/Method |
|---|---|---|
| SMTP Server | The server that handles sending your email. | smtplib.SMTP_SSL() |
| SSL Port | A secure port for the SMTP connection. | 465 (for Gmail) |
| Authentication | Logging in to your email account. | smtp_server.login() |
| MIME Type | A standard for formatting different types of content in an email. | email.mime.text.MIMEText |
| Multipart Message | A container that can hold different parts of an email (e.g., text, HTML, attachment). | email.mime.multipart.MIMEMultipart |
| Attachment | A file attached to the email, must be base64 encoded. | email.mime.base.MIMEBase + encoders.encode_base64() |
| App Password | A special password for apps to access your Google Account securely. | Google Account Settings |
