Understanding Multiple FROM Addresses in SMTP: Legitimate Use Cases and Security Implications


2 views

The SMTP protocol, as defined in RFC 5322 and related standards, technically allows for multiple From: addresses in email headers (distinct from the envelope sender). This feature exists primarily for:

  • Mailing list implementations where messages originate from multiple contributors
  • Forwarding scenarios where the original sender needs to be preserved
  • Specialized notification systems with multiple origin points

While rare, some valid implementations exist:

From: "Support Team" <support@example.com>,
      "Billing Department" <billing@example.com>

This format might appear in:

  • Collaborative customer support systems
  • Multi-department automated notifications
  • Certain legacy mailing list managers

Most modern email systems treat multiple From: headers as suspicious because:

  1. It's a common spam/phishing technique to obfuscate origin
  2. Few legitimate senders actually need this functionality
  3. It complicates authentication (SPF/DKIM/DMARC checks)

Here's how you might detect and handle such messages in Python:

import email
from email.header import decode_header

def has_multiple_from(raw_email):
    msg = email.message_from_string(raw_email)
    from_headers = msg.get_all('From', [])
    
    # Count distinct addresses
    addresses = set()
    for header in from_headers:
        for part in decode_header(header):
            if isinstance(part[0], bytes):
                text = part[0].decode(part[1] or 'utf-8')
            else:
                text = part[0]
            addresses.update(re.findall(r'[\w\.-]+@[\w\.-]+', text))
    
    return len(addresses) > 1

When building email processing systems:

  • Consider multiple From: headers as high-risk indicators
  • Prefer envelope sender (Return-Path) for authentication
  • Log such messages for analysis rather than silently discarding
  • Provide clear bounce messages when rejecting

The feature originates from early SMTP implementations (1980s) when:

  • Email routing was simpler and more trusted
  • Collaborative editing workflows were envisioned differently
  • Security considerations were less prominent

While working on an email parsing library recently, I stumbled upon an obscure SMTP behavior that made me pause - the protocol actually allows multiple From: headers in message bodies (not to be confused with envelope senders). This seems counterintuitive in today's security-conscious email ecosystem.

Received: from mail.example.com (EHLO mail.example.com)
From: admin@example.com
From: support@example.com
Date: Wed, 15 Mar 2023 09:45:12 +0000
Subject: Multiple FROM test

Digging through RFC 5322 and its predecessors reveals this wasn't always an edge case. In early email systems:

  • Mail forwarding services needed to preserve original sender information
  • Mailing list managers would add administrative addresses while keeping original FROM
  • Some gateway systems merged messages from multiple sources

Here's how a mailing list might have used it in the 1990s:

From: original-sender@domain.com
From: list-owner@listserver.com
Sender: list-bounces@listserver.com

Today, this feature is overwhelmingly used for malicious purposes:

  • Phishing attacks obscuring true sender identity
  • Spam messages attempting to bypass filters
  • Email spoofing combined with display name deception

Most modern MTAs and libraries handle this automatically. For example, Python's email parser:

import email
from email.policy import default

msg = email.message_from_file(open('email.eml'), policy=default)
from_addresses = msg.get_all('from', [])  # Returns list of all FROM headers

For developers working with email processing:

  1. Validation: Treat multiple FROM headers as potential security risk
  2. Parsing: Always use get_all() methods when processing headers
  3. Filtering: Consider rejecting or flagging messages with this characteristic

Here's a practical filter example in Node.js:

function validateEmailHeaders(email) {
  const fromHeaders = email.headers.get('from');
  if (Array.isArray(fromHeaders) && fromHeaders.length > 1) {
    throw new Error('Multiple FROM headers detected');
  }
  // Continue processing...
}

A 2021 study of phishing campaigns found:

Campaign Type Multiple FROM Usage
CEO Fraud 17%
Credential Phishing 23%
Malware Distribution 9%

The security team at Acme Corp shared their filtering approach:

# Postfix header_checks rule
/^From:.*\nFrom:/ REJECT Multiple FROM headers detected

For systems that must maintain strict RFC compatibility:

  • Log all instances for security analysis
  • Implement scoring systems rather than binary rejection
  • Consider adding X-Headers to note the anomaly

Example scoring implementation:

def score_email(msg):
    score = 0
    if len(msg.get_all('from', [])) > 1:
        score += 5  # Medium risk
    if 'sender' not in msg:
        score += 3  # No Sender header increases risk
    return score