How to Customize Message-ID Format in Postfix for Java Applications to Prevent Spam Filtering


2 views

When sending emails through a Java application with Postfix, you might encounter message-IDs that look like:

message-id=<143303043.111334605578921.JavaMail.applicationname@hostname>

This format becomes problematic when:

  • Your relay host requires domain-based message-IDs
  • Spam filters flag messages with hostname-only IDs
  • You need consistent tracking across mailing systems

The JavaMail API generates its own Message-ID header by default, bypassing Postfix's formatting. Unlike the Linux mail command which inherits Postfix's settings:

message-id=<10213429251967.C2D74C1A8D@domain.tld>

Override the default behavior in your Java application:

Properties props = new Properties();
props.put("mail.smtp.localhost", "domain.tld");
props.put("mail.smtp.localaddress", "domain.tld");

Create a header_check rule in main.cf:

header_checks = regexp:/etc/postfix/header_checks

Then in /etc/postfix/header_checks:

/^Message-ID:.*@hostname/ REPLACE Message-ID: <${message_id}@domain.tld>

Add to main.cf:

local_header_rewrite_clients = static:all
message_id_format = <%t.%i.%c@domain.tld>

After implementing changes, test with:

echo "Test" | mail -s "Message-ID Test" recipient@example.com
postcat -q MESSAGE_ID | grep ^message-id

For Java applications, inspect raw headers in the received email or use a debugging SMTP server.

For more control, create a milter (mail filter) in Python:

import re
from pymilter import Milter

class MessageIDMilter(Milter):
    def envfrom(self, mailfrom, *str):
        self.message_id = f"<{int(time.time())}.{os.getpid()}.{random.randint(0,999999)}@domain.tld>"
        return Milter.CONTINUE
        
    def header(self, name, value):
        if name.lower() == "message-id":
            return Milter.ADDHEADER, "Message-ID", self.message_id
        return Milter.CONTINUE

When sending emails through Java applications using Postfix, you might encounter message-IDs formatted like:

message-id=<143303043.111334605578921.JavaMail.applicationanme@hostname>

This becomes problematic when:

  • Your relay host requires domain.tld in message-IDs
  • Spam filters flag messages with incomplete domain identifiers
  • You want consistent message-ID formatting across all sending methods

JavaMail API generates its own Message-ID header by default, bypassing Postfix's message ID generation. This explains why:

  • mail command produces proper message-IDs (e.g., message-id=<10213429251967.C2D74C1A8D@domain.tld>)
  • Java applications generate different formats

Option 1: Configure JavaMail Properties

Override JavaMail's default behavior by setting these properties in your mail session:

Properties props = new Properties();
props.put("mail.smtp.localhost", "domain.tld");
props.put("mail.smtp.localaddress", "domain.tld");
Session session = Session.getInstance(props);

Option 2: Postfix Header Rewriting

Use Postfix's header_checks to rewrite the Message-ID:

# In main.cf
header_checks = regexp:/etc/postfix/header_checks

# In header_checks
/^Message-ID:.*@hostname$/ REPLACE Message-ID: <${message_id}@domain.tld>

Option 3: Custom MTA Configuration

Configure Postfix to override incoming Message-IDs:

# In main.cf
local_header_rewrite_clients = permit_mynetworks
smtp_generic_maps = hash:/etc/postfix/generic

After implementing any solution, verify with:

postmap /etc/postfix/generic
postfix reload
telnet localhost 25

Send a test email and check headers using:

postcat -q message_id
  • Always test changes in staging first
  • Monitor spam scores after implementation
  • Consider implementing DKIM/DMARC for better deliverability
  • Document your message-ID format policy