Site icon Mailtrap

Developer’s Tutorial: How to Create, Manage, and Send Email From A Python Contact Form

This is a graphic representation of Python contact form for an article that covers the topic in detail.

This tutorial guides you through the essentials of building a Python contact form, collecting user data, and integrating email functionalities. 

I’ll be using Mailtrap for SMTP and API-based email sending. And I’ll show you how to test emails to ensure they land in the recipients’ inboxes, not the spam folder. 

By the end, you’ll gain practical insights into making a simple contact form functional and secure using backend validation and verification.

How to set up your Python environment?

As this tutorial is geared toward junior devs, I’ll briefly cover the Python setup, necessary libraries, and the virtual environment setup for MacOS, Linux, and Windows users. 

But if you already have all that, feel free to jump to the “how to create a contact form” section

Step 1:Python installation

At the time of writing, the stable Python version was 3.12.3. I’d generally recommend using Python 3.8xy or higher for optimal compatibility with the necessary libraries. 

Here’s the installation for different operating systems. 

Windows:

  1. Download the Python installer from the official Python website.
  2. Run the installer. Check the box that says “Add Python 3.x to PATH” before clicking “Install Now.”

MacOS:

  1. Install Python using Homebrew (a package manager for macOS). If you don’t have Homebrew installed, paste the following command in your terminal to do it:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. Once Homebrew is installed, you can install Python by running:
brew install python

Linux: 

  1. Most Linux distributions come with Python pre-installed. You can check if Python is installed and its version by running:
python3 --version
  1. If it’s not installed, you can install it via your distribution’s package manager. For example, on Ubuntu:
sudo apt update
sudo apt install python3

Step 2: Set up a virtual environment 

You should be using a virtual environment because it allows you to manage separate dependencies for each project you’re working on. Here’s how to do it:

  1. Install the virtualenv package if it’s not already installed:
pip install virtualenv
  1. Create a new virtual environment in your project directory:
virtualenv venv
  1. Activate the virtual environment:
.\venv\Scripts\activate
source venv/bin/activate

Once your virtual environment is activated, you’ll notice the environment name (venv) appears at the beginning of your terminal prompt indicating that you are working inside the virtual environment.

Also, depending on how you decide to handle form data and sending emails, you may need specific libraries like flask for a lightweight web server, or requests for handling HTTP requests if using APIs. You can install Python libraries using pip, for example:

pip install flask
pip install requests

How to create a Python contact form?

Here, I’ll show you a method to create a Python contact form that can be embedded in your contact page, for example. 

The basic form below collects user input. It includes user name, email, message fields, and the submit button. For the given example, I’ll be saving the form in the HTML file called contact_form.html

Note: For simplicity, I didn’t include CSS styles, div class, etc. But you can add any style, emailfield widget, or other custom elements as you deem fit. 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact Form</title>
</head>
<body>
    <h1>Contact Us</h1>
    <form action="/submit_form.py" method="post">
        <label for="name">Name:</label><br>
        <input type="text" id="name" name="name" required><br>
        <label for="email">Email:</label><br>
        <input type="email" id="email" name="email" required><br>
        <label for="message">Message:</label><br>
        <textarea id="message" name="message" required></textarea><br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

As for the next steps, we already blogged on how to create a Django contact form, so feel free to check it out. 

How to collect data from a Python contact form?

Secure web form data handling protects against common security issues like SQL injection, XSS (Cross-Site Scripting), etc. In this section, I’ll show you how to safely receive and handle POST requests in Python, focusing on preventing common security vulnerabilities.

To handle POST requests securely, I’ll use a basic Python server-side framework Flask. It helps bootstrap the web development process because it simplifies receiving and processing web form data. 

Below is a simple Flask application setup to handle a POST request. 

Just a reminder on how to install Flask, if you haven’t already done it. 

pip install Flask

Then, move on to create a new Python file, app.py, and write the following code:

from flask import Flask, request, render_template_string

app = Flask(__name__)

@app.route('/')
def form():
    return '''
        <form action="/submit" method="post">
            <label for="name">Name:</label><br>
            <input type="text" id="name" name="name" required><br>
            <label for="email">Email:</label><br>
            <input type="email" id="email" name="email" required><br>
            <label for="message">Message:</label><br>
            <textarea id="message" name="message" required></textarea><br>
            <input type="submit" value="Submit">
        </form>
    '''

@app.route('/submit', methods=['POST'])
def submit():
    # Use the request object to access the form data
    name = request.form['name']
    email = request.form['email']
    message = request.form['message']

    # Escape the input to prevent XSS
    safe_name = html.escape(name)
    safe_email = html.escape(email)
    safe_message = html.escape(message)

    return render_template_string('''
        <h1>Thank You!</h1>
        <p>Your name: {{name}}</p>
        <p>Your email: {{email}}</p>
        <p>Your message: {{message}}</p>
    ''', name=safe_name, email=safe_email, message=safe_message)

if __name__ == '__main__':
    app.run(debug=True)

Quick breakdown:

Pro Tip: If you’re using Django framework, the following py files are helpful. 

How to validate and verify data from a contact form?

I’ll be implementing basic validation in Python using Flask since the framework offers a straightforward methodology. It helps validate email addresses, prevents erroneous data processing, and malicious data. 

If you need more details on validating email addresses in Python, click the link here ◀️. 

Now, assuming you got Flask installed, I’ll continue using the app.py file where I previously set up the form submission. Here’s an example:

from flask import Flask, request, render_template_string, redirect, url_for
import re

app = Flask(__name__)

@app.route('/')
def form():
    return '''
        <form action="/submit" method="post">
            <label for="name">Name:</label><br>
            <input type="text" id="name" name="name" required><br>
            <label for="email">Email:</label><br>
            <input type="email" id="email" name="email" required><br>
            <label for="message">Message:</label><br>
            <textarea id="message" name="message" required></textarea><br>
            <input type="submit" value="Submit">
        </form>
    '''

@app.route('/submit', methods=['POST'])
def submit():
    name = request.form['name']
    email = request.form['email']
    message = request.form['message']

    # Validate the form data
    if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
        return "Invalid email, please go back and enter a valid email."

    if not name.strip():
        return "Name is required, please go back and fill out the name field."

    if not message.strip():
        return "Message is required, please go back and fill out the message field."

    return render_template_string('''
        <h1>Thank You!</h1>
        <p>Your name: {{name}}</p>
        <p>Your email: {{email}}</p>
        <p>Your message: {{message}}</p>
    ''', name=name, email=email, message=message)

if __name__ == '__main__':
    app.run(debug=True)

Quick breakdown:

Now, I’d like to point out some examples of best practices that could further secure the form data. 

Sanitizing inputs to prevent XSS attacks 

I’ll enhance the previous Flask application by adding sanitization to the input handling process using Flask’s Markup utilities and the escape function. 

This function converts special characters in the input (such as <, >, & ,',"), which have meaning in HTML, into their safe HTML entity equivalents.

from flask import Flask, request, render_template_string, escape

app = Flask(__name__)

@app.route('/')
def form():
    return '''
        <form action="/submit" method="post">
            <label for="name">Name:</label><br>
            <input type="text" id="name" name="name" required><br>
            <label for="email">Email:</label><br>
            <input type="email" id="email" name="email" required><br>
            <label for="message">Message:</label><br>
            <textarea id="message" name="message" required></textarea><br>
            <input type="submit" value="Submit">
        </form>
    '''

@app.route('/submit', methods=['POST'])
def submit():
    # Get form data
    name = request.form['name']
    email = request.form['email']
    message = request.form['message']

    # Sanitize inputs to prevent XSS
    safe_name = escape(name)
    safe_email = escape(email)
    safe_message = escape(message)

    # Continue processing or storing data
    return render_template_string('''
        <h1>Thank You!</h1>
        <p>Your name: {{ name }}</p>
        <p>Your email: {{ email }}</p>
        <p>Your message: {{ message }}</p>
    ''', name=safe_name, email=safe_email, message=safe_message)

if __name__ == '__main__':
    app.run(debug=True)

Quick breakdown:

Send an email from a Python contact form using SMTP

I’ll be using Mailtrap Email Sending SMTP, a part of Mailtrap Email Delivery Platform. It gives developers an infrastructure with high deliverability rates by default and by design. 

If you’re not a Maltrap user, you can sign up here. Afterward, add and verify your domain (we provide you with all the necessary DNS records). Then, you can move to SMTP/API Settings, choose your preferred stream, Transactional or Bulk, and get the SMTP credentials. 

Note: You can send Transactional and Bulk emails within the same Email Sending Plan, with no extra charges. 

That out of the way, I’ll move to show you how to set up Python step by step. 

Step 1: Install the necessary libraries 

Make sure you have the email library to compose emails, in addition to smtplib for sending them. Usually, email is included in Python’s standard library.

pip install smtplib

(Note: smtplib is part of the standard library, so you don’t need to install it. But you can run the given command to make sure your environment is correctly set up.)

Step 2: SMTP configuration

Extract the SMTP settings from your Mailtrap account. You can find a sample configuration under SMTP/API Settings tab (as shown in the image above). 

Step 3: Create a script to send the email

Here, I’ll give you a basic example of a Python email-sending script. 

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# Mailtrap credentials and server configuration
smtp_server = 'live.smtp.mailtrap.io'
smtp_port = 587
smtp_username = 'api'
smtp_password = 'your_mailtrap_password'

# Email content setup
sender_email = "from@example.com"
receiver_email = "to@example.com"
subject = "Python Contact Form Test"
body = "This is a test email from the Python contact form."

# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# Add body to email
message.attach(MIMEText(body, "plain"))

# Connect to Mailtrap server and send email
try:
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.login(smtp_username, smtp_password)
        server.sendmail(sender_email, receiver_email, message.as_string())
    print("Email sent successfully!")
except Exception as e:
    print(f"Failed to send email: {e}")

Quick breakdown:

Send an email from a Python contact form using API

Mailrap Email Delivery Platform has its official Python SDK , and I’ll be using that to show you how to send via API. 

The code below is a slimmed-down version adapted to the contact form needs. But if you need a more comprehensive integration with attachments, and maybe multiple recipients, refer to the SDK GitHub documentation linked above ⬆️.  

Start by installing Mailtrap’s Python SDK. 

pip install mailtrap 

Set up a basic email including HTML template along with plain text as a fallback.

import mailtrap as mt

# Create the email with HTML and plain text content
mail = mt.Mail(
    sender=mt.Address(email="mailtrap@example.com", name="Mailtrap Test"),
    to=[mt.Address(email="your@email.com", name="Your name")],
    cc=[mt.Address(email="cc@email.com", name="Copy to")],
    bcc=[mt.Address(email="bcc@email.com", name="Hidden Recipient")],
    subject="You are awesome!",
    text="Congrats for sending test email with Mailtrap!",
    html="""
    <!doctype html>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      </head>
      <body style="font-family: sans-serif;">
        <div style="display: block; margin: auto; max-width: 600px;" class="main">
          <h1 style="font-size: 18px; font-weight: bold; margin-top: 20px">
            Congrats for sending test email with Mailtrap!
          </h1>
          <p>Inspect it using the tabs you see above and learn how this email can be improved.</p>
          <p>Now send your email using our fake SMTP server and integration of your choice!</p>
          <p>Good luck! Hope it works.</p>
        </div>
      </body>
    </html>
    """,
    headers={"X-MT-Header": "Custom header"},
    custom_variables={"year": 2023},
)

# Set up and send the email using Mailtrap's API
client = mt.MailtrapClient(token="your-api-key")
client.send(mail)

Quick breakdown:

Further reading:

How to test your emails before sending?

The quick answer is that you run your emails through a sandbox environment to ensure they look and perform as expected. At the same time, you should check if your emails are likely to trigger spam filters, or not. 

The solution I’ll be using here is Mailtrap Email Testing (also part of Mailtrap Email Delivery Platform). It’s a sandbox that captures outgoing emails (from staging and dev environments) and allows you to inspect them in a web browser without sending them to actual recipients. 

This is useful for developers to verify and debug email functionality in applications. And, unlike production sending, the sandbox doesn’t require you to add and verify a domain. 

Below, I’ll cover the SMTP and API methodology. 

SMTP

The SMTP setup is pretty straightforward, and I’ll walk you through the process. Of course, I’m assuming that you’re already a Mailtrap user, if not click here to sign up

So, launch Mailtrap, navigate to Email Testing, choose My Inbox, and hit “Show Credentials” under the SMTP Settings tab. 

After you integrate the SMTP settings, go to the Integrations drop-down, and choose one of the available options for Python. 

The most basic method is sendmail(), but you also have ready-to-use integrations for Django or Flask. 

Proceed to send the test email in Shell (run the given integration), and you’ll get the response in your inbox, almost instantly. 

API

First, you’ll need to establish the connection with Mailtrap Email Testing API using the http.client.HTTPSConnection. The endpoint itself is sandbox.api.mailtrap.io

Next, you can define the email content, recipients, sender, text, etc. as a JSON payload. 

Finally, make a POST request to the Mailtrap Email Testing API using the ready-made payload along with the necessary headers. 

To stress, you’ll need an Email Testing API token to authorize the request. Access the API token under the Settings > API Tokens

Here’s a full example of email testing via API:

import http.client
import json

def test_send_email():
    conn = http.client.HTTPSConnection("sandbox.api.mailtrap.io")
   
    payload = {
        "to": [{"email": "john_doe@example.com", "name": "John Doe"}],
        "cc": [{"email": "jane_doe@example.com", "name": "Jane Doe"}],
        "bcc": [{"email": "james_doe@example.com", "name": "Jim Doe"}],
        "from": {"email": "sales@example.com", "name": "Example Sales Team"},
        "attachments": [
            {
                "content": "base64_encoded_content_here",
                "filename": "index.html",
                "type": "text/html",
                "disposition": "attachment"
            }
        ],
        "custom_variables": {"user_id": "45982", "batch_id": "PSJ-12"},
        "headers": {"X-Message-Source": "dev.mydomain.com"},
        "subject": "Your Example Order Confirmation",
        "text": "Congratulations on your order no. 1234",
        "category": "API Test"
    }

    headers = {
        'Content-Type': "application/json",
        'Accept': "application/json",
        'Api-Token': "your_api_token_here"  # Replace with your real API token
    }

    # Convert the payload to a JSON string
    json_payload = json.dumps(payload)

    # Make the POST request
    conn.request("POST", "/api/send/inbox_id", json_payload, headers)  # Replace 'inbox_id' with your real inbox ID

    # Get the response
    response = conn.getresponse()
    data = response.read()

    print(data.decode("utf-8"))

if __name__ == "__main__":
    test_send_email()

If you need other details, or more information, feel free to refer to our official API docs. Also, you can check our full tutorial on testing emails in Python

Wrapping up

I hope this tutorial helped you master creating and managing a Python contact form. So, you’re well-equipped to enhance user engagement on your website. 

Continue exploring and refining your skills, and remember that every form you build increases your capability to interact meaningfully with your users.

Exit mobile version