← All posts

Email Privacy: What's Actually in the Headers Your App Sends

A
Admin
·

Every email your app sends carries metadata in its headers. Most of it is innocuous — routing information, timestamps, message IDs. But some headers leak information you probably didn't intend to share: internal server hostnames, private IP addresses, software versions, and even deployment timestamps.

What's in a Typical Email Header

Here's a real (sanitized) header dump from a transactional email sent by a Node.js application through a standard SMTP relay:

Received: from app-server-prod-01.internal.company.com (10.0.3.47)
  by smtp-relay.company.com with ESMTP id abc123;
  Thu, 01 May 2026 09:15:32 +0000
Received: from smtp-relay.company.com (203.0.113.55)
  by mx.gmail.com with ESMTPS id xyz789;
  Thu, 01 May 2026 09:15:33 +0000
From: noreply@company.com
To: user@example.com
Subject: Your password has been reset
Message-ID: <1714554932.447.app-server-prod-01@company.com>
X-Mailer: Nodemailer/6.9.13
X-Originating-IP: 10.0.3.47
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="----=_Part_447"

Count the information disclosures in those 14 lines.

Headers That Leak Sensitive Information

Received Chain

The Received headers form a chain showing every server the email passed through. They routinely expose:

  • Internal hostnames: app-server-prod-01.internal.company.com reveals your naming convention and infrastructure layout.
  • Private IP addresses: 10.0.3.47 tells an attacker which RFC 1918 subnet your application servers live on.
  • Server software: Some Received headers include the MTA software and version (e.g., Postfix 3.7.1).

Message-ID

The Message-ID header is required for email delivery, but its format can leak information:

  • <1714554932.447.app-server-prod-01@company.com> — the Unix timestamp reveals exactly when the message was generated, the counter (447) suggests message volume, and the hostname is embedded in the ID.

Generate opaque Message-IDs instead: <uuid@company.com> reveals only your domain (which is already in the From header).

X-Mailer and User-Agent

X-Mailer: Nodemailer/6.9.13 tells an attacker exactly which email library and version you use. If that version has known vulnerabilities, you've made their job easier.

Fix: Most email libraries let you suppress or override this header. In Nodemailer: { xMailer: false }.

X-Originating-IP

Some SMTP servers add this header automatically. It contains the IP address of the machine that submitted the email — which for transactional email is your application server. If that's a private IP, it leaks your internal network topology.

Return-Path

The Return-Path is set from the SMTP envelope sender. If your bounce handling uses a different domain than your From address, this can reveal internal infrastructure domains (e.g., bounces.internal-mail-system.company.com).

What to Remove vs What to Keep

You can't strip everything — some headers are required for email delivery and authentication:

HeaderRequired?Action
FromYesKeep — required by RFC 5322
ToYesKeep
SubjectYesKeep
Message-IDYesKeep — but generate opaque IDs
DateYesKeep
DKIM-SignatureFor deliverabilityKeep — required for authentication
ReceivedAdded by MTAsCan't control (added in transit)
X-MailerNoRemove or suppress
X-Originating-IPNoRemove
User-AgentNoRemove

How to Audit Your Headers

Send a test email through your application and inspect every header. Don't send to a real inbox — use an SMTP testing sandbox so the email never leaves your control.

MailHog's headers inspector shows every header in a clean, readable format. Look for any header containing internal hostnames, private IPs, software versions, or timestamps that reveal operational patterns.

GDPR Considerations

Under GDPR, email metadata can constitute personal data if it can be linked to an identifiable person. The recipient's email address in headers is obviously personal data, but even operational metadata like timestamps and IP addresses can be considered personal data in the EU context.

If your application sends email to EU recipients, review your headers with your data protection officer. Minimizing the metadata in outgoing email is a straightforward privacy-by-design measure under Article 25.

For more on how MailHog handles data, see our security page.

FAQ

Can I remove the Received headers from my outgoing email?

Not directly. Received headers are added by each mail server the message passes through — you don't control what intermediate servers add. However, you can minimize the initial Received header by configuring your MTA to not include internal hostnames and IPs. Some email APIs (SendGrid, Postmark) strip your internal Received headers before relaying.

Does the Message-ID need to be unique?

Yes. RFC 5322 requires Message-ID to be globally unique. Use a UUID or random string followed by your domain: <550e8400-e29b-41d4-a716-446655440000@company.com>. This is unique, opaque, and doesn't leak operational details.

Is the X-Mailer header a real security risk?

It's a low-severity information disclosure. Knowing you use Nodemailer 6.9.13 isn't immediately exploitable, but it narrows an attacker's research surface. Removing it costs nothing and follows the principle of least privilege for metadata. For a deeper look at email authentication headers, see our DKIM, SPF, and DMARC guide.

← Back to all posts