Skip to main content

#015 - Check email server and email address in python and laravel

·895 words·5 mins· loading · loading ·

Sometimes, you need to check if an email address is valid or if the email server is reachable.
#

In this article, I will show you how to check an email address and email server using Python and Laravel.

In my case, I have a list of email addresses (from an old database), and I need to check if the email server is reachable and if the email addresses are valid. The simplest way was to create a Python script.

Next, I tried to transfer the Python code to Laravel. I would like to have a global helper function in Laravel to check email addresses and display the results in Blade files.

Python
#

Simple checker in command line.
#

Check if you have installed the following packages:

pip install dnspython colorama

The script below will check if the email address is valid and if the email domain has MX records. It uses the re module to validate the email address format and the dns.resolver module from the dnspython package to check the MX records of the email domain. After running the script, you will be prompted to enter an email address, and the script will output whether the email is valid or not.

import re
import dns.resolver
from colorama import init, Fore, Style

# Initialize colorama
init()

# Function to validate email addresses using a comprehensive regex
def is_valid_email(email):
    regex = r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'
    return re.match(regex, email) is not None

# Function to check if the email domain has MX records
def has_mx_record(email):
    domain = email.split('@')[-1]
    try:
        answers = dns.resolver.resolve(domain, 'MX')
        return True if answers else False
    except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.exception.DNSException) as e:
        print(f"{Fore.YELLOW}DNS lookup failed for domain {domain}: {e}{Style.RESET_ALL}")
        return False

# Common domains that should always pass the MX check
common_domains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com']

# Get the email address from the user
email = input("Enter the email address to check: ").strip().lower()

# Validate the email address
if not is_valid_email(email):
    print(f"{Fore.RED}Invalid email format: {email}{Style.RESET_ALL}")
elif email.split('@')[-1] not in common_domains and not has_mx_record(email):
    print(f"{Fore.RED}Email has no valid MX record: {email}{Style.RESET_ALL}")
else:
    print(f"{Fore.GREEN}Email is valid: {email}{Style.RESET_ALL}")

I suggests name this file check_email_console.py and run it in the command line.

python3 check_email_console.py

Checker for multiple emails stored in a file.
#

Based on the previous script, I created a script that reads email addresses from a file and checks if the email addresses are valid and if the email domains have MX records. Emails to check should be stored in a file, with one email address per line. (e.g., emails_input.txt). You will get the results in two files: emails_output_valid.txt and emails_output_invalid.txt. File name and path can be changed in the script in section # File paths.

As before, you need to install the following packages:

pip install dnspython colorama

Code:

import re
import dns.resolver
from colorama import init, Fore, Style

# Initialize colorama
init()

# Function to validate email addresses using a comprehensive regex
def is_valid_email(email):
    regex = r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'
    return re.match(regex, email) is not None

# Function to check if the email domain has MX records
def has_mx_record(email):
    domain = email.split('@')[-1]
    try:
        answers = dns.resolver.resolve(domain, 'MX')
        return True if answers else False
    except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.exception.DNSException) as e:
        print(f"{Fore.YELLOW}DNS lookup failed for domain {domain}: {e}{Style.RESET_ALL}")
        return False

# Common domains that should always pass the MX check
common_domains = ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com']

# File paths
input_file_path = 'emails_input.txt'
valid_output_file_path = 'emails_output_valid.txt'
invalid_output_file_path = 'emails_output_invalid.txt'

# Read emails from the input file
try:
    with open(input_file_path, 'r') as file:
        emails = [line.strip().lower() for line in file if line.strip()]
except FileNotFoundError:
    print(f"File not found: {input_file_path}")
    exit()

# Lists to store valid and invalid emails
valid_emails = []
invalid_emails = []

# Validate each email
for email in emails:
    if not is_valid_email(email):
        print(f"{Fore.RED}Invalid email format: {email}{Style.RESET_ALL}")
        invalid_emails.append(email)
    elif email.split('@')[-1] not in common_domains and not has_mx_record(email):
        print(f"{Fore.RED}Email has no valid MX record: {email}{Style.RESET_ALL}")
        invalid_emails.append(email)
    else:
        print(f"{Fore.GREEN}Email is valid: {email}{Style.RESET_ALL}")
        valid_emails.append(email)

# Write valid emails to the valid output file
with open(valid_output_file_path, 'w') as file:
    for email in valid_emails:
        file.write(email + '\n')

# Write invalid emails to the invalid output file
with open(invalid_output_file_path, 'w') as file:
    for email in invalid_emails:
        file.write(email + '\n')

print(f"{Fore.GREEN}Valid emails have been written to {valid_output_file_path}{Style.RESET_ALL}")
print(f"{Fore.RED}Invalid emails have been written to {invalid_output_file_path}{Style.RESET_ALL}")

Sugest name this file check_email_file.py and run it in the command line.

python3 check_email_file.py

Laravel
#

To create a global helper function in Laravel, you need to create a new file in the app directory. In my case, I created a new file called helpers.php.

<?php

if (!function_exists('isValidEmail')) {
    /**
     * Check if an email is valid and has an MX record.
     *
     * @param string $email
     * @return bool
     */
    function isValidEmail($email)
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            return false;
        }

        $domain = substr(strrchr($email, "@"), 1);

        return checkdnsrr($domain, 'MX');
    }
}

Next, you need to add the following code to the composer.json file:

 "autoload": {
        "files": [
        "app/helpers.php"
    ],
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    },

After that, you need to run the following command:

composer dump-autoload

Now you can use the isValidEmail function in your Laravel project. For example in a Blade file:

@if(isValidEmail('[email protected]'))
    <p>Email is valid</p>
@else
    <p>Email is invalid, or the email server is not reachable</p>

Conclusion
#

In this article, I showed you how to check an email address and email server using Python and Laravel. I hope you found this article helpful.

References
#