Anatomy of a zombie email: when iso-8859-1 and RFC violations destroy deliverability
Back to blog

Anatomy of a zombie email: when iso-8859-1 and RFC violations destroy deliverability

9/4/2026 · 5 min · Email

Anyone operating mail transfer agents and reviewing incoming edge filter logs knows that stable email communication requires strict adherence to RFC standards. In an ideal modern internet environment, UTF-8 governs global message payloads. In day-to-day operations, however, I frequently capture malformed headers and legacy character encodings produced by obsolete systems that refuse to die.

Recently, I isolated a batch of messages generated by an automated corporate billing workflow. The sender was baffled: monthly financial reports were failing to reach clients, silently vanishing in transit, or landing straight into junk folders.

Inspecting the raw message headers immediately exposed the root cause: a textbook combination of RFC violations and legacy encoding that turned the message into a "zombie email" in the eyes of modern antispam engines like SpamAssassin and SPFBL.

Below is the forensic analysis of these structural errors alongside tested code snippets to fix the problem both in application logic and on receiving mail servers.


The analyzed raw header snippet#

To ensure complete confidentiality, all internal domains and mailbox names have been anonymized while keeping the exact captured syntax intact:

From: sender@domain.com
To: recipient@company.com
Cc: manager@company.com; auditor@company.com
Subject: Relatorio de Faturamento - Marco
Content-Type: text/plain; charset=ISO-8859-1

[Message body with raw ISO-8859-1 accents]

At first glance, it looks like an ordinary business notification. However, to a receiving Mail Transfer Agent (MTA) parser, this header contains three major protocol violations.


Technical breakdown of RFC violations#

1. Critical absence of the Message-ID header#

The message omitted an identification header. Under RFC 5322 (Internet Message Format), section 3.6.4, every internet message should include a globally unique identifier (formally categorized as SHOULD, though in practice modern MTAs and security gateways treat it as mandatory):

message-id = "Message-ID:" msg-id CRLF

The Message-ID is critical for:

When custom automation opens a raw SMTP socket without injecting a Message-ID (expecting downstream relays to generate it), receiving antispam filters penalize the message heavily (such as SpamAssassin's MISSING_MID rule). On hardened enterprise mail gateways, messages lacking this header are rejected with a 550 error or quarantined immediately.


2. Unencoded subject with raw iso-8859-1 (RFC 2047 violation)#

In the captured header, accented characters were written using raw ISO-8859-1 (Latin-1) bytes.

The core SMTP specification mandates that message headers contain strictly 7-bit US-ASCII characters. To support internationalization and multilingual headers, RFC 2047 defined the MIME Encoded-Word syntax:

$$\text{=?charset?encoding?encoded-text?=}$$

To send an accented string like "Relatório de Faturamento - Março" validly in UTF-8 with Base64 encoding (B), the header must appear as:

Subject: =?UTF-8?B?UmVsYXTDs3JpbyBkZSBGYXR1cmFtZW50byAtIE1hcsOnbw==?=

When custom scripts emit unencoded Latin-1 bytes directly into the stream, recipient email clients fail to decode the character sequence, creating mojibake artifacts like ç or � and triggering spam scoring rules that penalize malformed headers.


3. Invalid recipient delimiter in the Cc header (semicolon vs. comma)#

In the analyzed header, carbon-copy recipients were formatted with semicolons:

Cc: manager@company.com; auditor@company.com

Under RFC 5322 syntax rules, address lists in To, Cc, and Bcc headers must be strictly comma-delimited (,):

Cc: manager@company.com, auditor@company.com

The semicolon delimiter is a legacy artifact of older desktop email software like Microsoft Outlook. Outlook accepts semicolons in user input fields and replaces them with commas before dispatching over the wire.

When developers copy this desktop UX habit into automated backend notification scripts, receiving MTA parsers fail. The server attempts to parse the semicolon as part of the mailbox local-part, fails address validation, and drops the secondary recipients.


Why iso-8859-1 still haunts server infrastructure#

With UTF-8 ubiquitous across modern computing, why does Latin-1 still appear in production logs? In practice, two issues account for nearly all occurrences:

  1. Legacy ERP systems: Old invoicing systems, batch notification daemons, and internal monitoring scripts deployed over a decade ago. As long as core functions work, organizations rarely audit raw email dispatch mechanisms.
  2. Operating system locale fallback: Modern scripts running on servers whose system or database locale is set to ISO-8859-1. When sending functions are invoked without explicit charset=utf-8 and RFC 2047 headers, runtimes fall back to the host machine's legacy regional table.

Mainstream email clients (Thunderbird, Gmail, Outlook Web) never generate these malformed structures. Almost all instances trace back to unmaintained in-house automation.


Application-layer remediation (PHP)#

To resolve this issue at the source, here is a clean PHP implementation ensuring strict compliance with RFC 5322 and RFC 2047:

<?php
declare(strict_types=1);

$to = 'recipient@company.com';
$ccList = [
    'manager@company.com',
    'auditor@company.com'
];

// 1. Fix: Delimit multiple recipients strictly with COMMAS
$ccHeader = implode(', ', $ccList);

// 2. Fix: Encode Subject according to RFC 2047 (UTF-8 Base64)
$rawSubject = 'Relatório de Faturamento - Março';
$encodedSubject = '=?UTF-8?B?' . base64_encode($rawSubject) . '?=';

// 3. Fix: Generate unique Message-ID and specify explicit UTF-8 charset
$messageId = sprintf('<%s.%s@domain.com>', bin2hex(random_bytes(16)), time());

$headers = [
    'From' => 'sender@domain.com',
    'Cc' => $ccHeader,
    'MIME-Version' => '1.0',
    'Content-Type' => 'text/plain; charset=UTF-8',
    'Content-Transfer-Encoding' => '8bit',
    'Message-ID' => $messageId,
    'X-Mailer' => 'PHP/' . phpversion()
];

// Format header array into standard MIME key-value string
$headersString = '';
foreach ($headers as $key => $value) {
    $headersString .= "{$key}: {$value}\r\n";
}

$body = "Hello,\r\n\r\nPlease find attached the financial report for March.\r\n";

// Dispatch RFC-compliant email
mail($to, $encodedSubject, $body, $headersString);

With these fixes:


Destination filtering with Postfix#

If you manage destination mail servers and need to quarantine or inspect zombie emails before delivering them to users, Postfix provides the header_checks directive.

In /etc/postfix/header_checks, add regular expressions to catch malformed headers:

# Flag or reject messages using semicolons in the Cc header
/^Cc:.*;/ WARN Malformed Cc header using semicolon delimiter (RFC 5322 violation)

# Quarantine or warn on messages lacking a Message-ID
!/^Message-ID:/ WARN Inbound message missing mandatory Message-ID header

When using PCRE or regex tables (header_checks = pcre:/etc/postfix/header_checks), indexing with postmap is not required. Simply reload the service:

sudo systemctl reload postfix

Auditing outgoing email to ensure maximum deliverability#

Before assuming an IP address is blacklisted, inspect raw message headers:

  1. Examine raw headers: In your email client, open View Original or View Message Source.
  2. Verify the Message-ID: Confirm that <id@yourdomain> exists and matches your sender domain.
  3. Check Subject encoding: Accented characters must be wrapped in =?UTF-8?B?...?= or =?UTF-8?Q?...?= syntax.
  4. Inspect address delimiters: Never use semicolons in To, Cc, or Bcc headers.

Ensuring your applications produce RFC-compliant email headers is the most reliable way to protect domain reputation and keep legitimate business notifications out of junk folders.

Was this article helpful?

Leave a quick reaction to help prioritize future technical guides:

CC BY-NC

This post is licensed under CC BY-NC.

Comments

Join the discussion below.

0 comments