Skip to main content

alterMIME Alternative

Replace the alterMIME content filter with a maintained milter - HTML disclaimers, per-user signatures, duplicate detection, and rules instead of shell scripts.

If you are looking for an alterMIME alternative, you are almost certainly running the classic Postfix disclaimer setup: a content_filter entry in master.cf, a shell script in /etc/postfix/disclaimer, and a text file that gets appended to outgoing mail. It works, it has worked for fifteen years, and it is usually something specific that finally breaks it - HTML that will not render, a disclaimer stacking up on every reply, a DKIM signature that no longer validates, or a request for per-employee signatures that a static text file cannot deliver.

This page covers what alterMIME actually does, the concrete reasons people replace it, what the alternatives are, and how to migrate a live Postfix server to MSH Postfix Milter without interrupting mail.

What alterMIME is

alterMIME is a small C program by Paul L Daniels that reads a MIME-encoded message, changes it, and writes it back out. It is not a mail server component and knows nothing about Postfix. Everything that makes it useful comes from the shell script you wrap around it:

/etc/postfix/disclaimer (excerpt)
#!/bin/sh
INSPECT_DIR=/var/spool/filter
SENDMAIL="/usr/sbin/sendmail -i"

cd $INSPECT_DIR || exit 75
cat > in.$$ || exit 75

if grep -qi "^${from_address}\$" /etc/postfix/disclaimer_addresses; then
/usr/bin/altermime --input=in.$$ \
--disclaimer=/etc/postfix/disclaimer.txt \
--disclaimer-html=/etc/postfix/disclaimer.html \
--xheader="X-Copyrighted-Material: see disclaimer" || exit 75
fi

$SENDMAIL "$@" < in.$$ || exit 75
rm -f in.$$

Postfix hands mail to that script through a pipe service, and the script re-injects the result with sendmail:

/etc/postfix/master.cf
smtp inet n - y - - smtpd
-o content_filter=dfilt:

dfilt unix - n n - - pipe
flags=Rq user=filter argv=/etc/postfix/disclaimer -f ${sender} -- ${recipient}

The tool itself does a handful of things, driven entirely by flags:

  • --disclaimer, --disclaimer-html, --disclaimer-b64 - append a footer from a file.
  • --htmltoo, --force-for-bad-html, --force-into-b64 - coax it into touching HTML parts it would otherwise skip.
  • --remove, --removeall, --replace / --with - delete or swap attachments by filename.
  • --xheader, --alter-header - add or rewrite a header.
  • --altersigned, --multipart-insert, --tmpdir - behaviour switches for awkward messages.

Credit where it is due: for a plain-text footer on a single-domain server, alterMIME is fast, tiny, free, and packaged by every major distribution. If that describes your setup and nothing is broken, you do not need to replace it.

Why people look for an alterMIME alternative

The complaints are remarkably consistent across mailing lists and forums, and they are structural rather than bugs anyone can fix.

HTML is the number one reason

Marketing supplies a designed HTML footer, and it either does not appear, appears as raw markup, or appears only for some senders. alterMIME appends to the parts it finds: if the client sent a plain-text-only message there is no HTML part to append to, and turning a text message into a valid multipart/alternative is exactly the kind of MIME surgery it was never designed for. The usual workarounds ---htmltoo, --force-for-bad-html, forcing every client to compose in HTML - treat the symptom.

The disclaimer grows on every reply

alterMIME appends unconditionally. It cannot tell that the same twelve lines of legal text already appear three times further down the quoted thread, so a long exchange ends up with more disclaimer than message. Detecting that yourself means writing your own matching logic in the filter script.

Content filters and DKIM do not mix well

A content_filter takes delivery of the message, rewrites the body, and re-injects it. Any DKIM signature that was already applied no longer matches the body it covers. Getting the order right around a re-injection point is fiddly, and a milter avoids the problem outright because milters run in the order listed in smtpd_milters - put the disclaimer milter before OpenDKIM and the message is signed after it has been modified.

Targeting is a text file and a grep

"Outgoing mail only", "external recipients only", "this domain gets a different footer", "not the notifications mailbox" - every one of those becomes another condition in the shell script and another list to keep current. The widely copied recipe for per-domain disclaimers is a chain of grep calls against ${from_address}. It works until someone joins the company and nobody updates disclaimer_addresses.

No per-user data at all

A static file cannot contain an employee's name, title, or phone number. Per-user signatures with alterMIME means generating one disclaimer file per mailbox from a directory export, on a cron job, and hoping the export stays in step with HR.

Maintenance and testing

Upstream alterMIME sits at 0.3.11 with a changelog that stops in 2010; a 0.3.12 tag exists in the inflex/alterMIME GitHub repository from 2023. It still builds and distributions still ship it, but nobody is developing it. Around it sits a shell script running as a dedicated filter user with hand-rolled exit codes, where the only way to test a change is to send real mail through the server and read the logs.

The realistic alternatives

There are four honest options once alterMIME stops fitting, and only one of them is this product.

  • Keep alterMIME and script around it. Free, and the right answer for a plain-text footer on one domain. The cost is that every new requirement becomes more shell script that only its author understands.
  • amavisd-new with a banner or an alterMIME hook. If you already run amavisd-new for virus and spam scanning, it can call out for disclaimer insertion. Deploying the whole stack purely to gain footers is a large amount of machinery for one feature, and the HTML limitations follow you.
  • Write your own milter. Full control via libmilter or a Python milter library, and a permanent maintenance commitment: MIME parsing, character sets, inline images, and duplicate detection are all yours to get right.
  • Use a maintained milter product. Attach through smtpd_milters, configure rules instead of scripts, and get HTML handling and per-user data as features rather than projects. That is what MSH Postfix Milter is.

Note what is not on the list. header_checks and body_checks cannot append text to a message body, and smtp_header_checks only rewrites headers. Postfix itself will not add a disclaimer under any configuration, which is precisely why alterMIME exists.

MSH Postfix Milter as the replacement

MSH Postfix Milter connects to Postfix as a milter rather than a content filter, so there is no pipe service, no filter user, no spool directory, and no re-injection. Messages are inspected in the SMTP conversation and modified in place.

Everything the disclaimer script encoded in if statements becomes a rule with conditions and actions, edited in an Administrator Panel and testable before it touches live mail.

alterMIME alternative for Postfix: disclaimer rule in MSH Postfix Milter with HTML template, position, and duplicate detection

What each alterMIME flag becomes

alterMIMEMSH Postfix Milter
--disclaimer=file.txtDisclaimer rule using a template, with the text part kept alongside the HTML
--disclaimer-html=file.htmlSame template - import your existing HTML, or build it in the visual designer
--htmltoo, --force-for-bad-htmlNot needed - message and template encodings are reconciled by the rule
--textpos, --htmlposPosition setting on the rule - top or bottom of the message
--remove, --removeallPolicy rule actions: strip or remove attachments by name, type, or size
--xheader, --alter-headerPolicy rule actions: add header, modify header, remove headers, rewrite subject
grep against disclaimer_addressesRule conditions on sender, recipient, direction, subject, headers, size, or group
One generated file per employeeDirectory service attributes substituted into the template per message
Nothing equivalentDuplicate detection with adjustable sensitivity
Nothing equivalentRules tester - simulate a message and see which rules match, without sending mail
Nothing equivalentScheduler, so a seasonal footer or campaign banner expires on its own

Inline images are the other everyday difference. A designed signature usually contains a logo, and templates can attach referenced images to the message as inline CID attachments, embed them as Base64, or leave them as external URLs - a choice alterMIME does not offer at all.

Migrating off alterMIME

The milter and the content filter are independent of each other, so the migration runs side by side and the only moment that matters is a single postfix reload.

  1. Install the milter and connect the Administrator Panel to the server module. Nothing changes in the mail path yet, because Postfix does not know about it.
  2. Recreate the disclaimer as a template. Import your existing disclaimer.txt and disclaimer.html, then create a disclaimer rule whose conditions match what the shell script decided with grep - typically message direction set to outgoing, plus any sender or group scoping.
  3. Test before switching. Run representative messages through the rules tester: an internal reply, an outbound message to an external recipient, a plain-text message, and a thread that already carries the old disclaimer. This is the step alterMIME never had.
  4. Register the milter so Postfix starts using it:
    sudo postconf -e smtpd_milters=inet:localhost:7080
    sudo postconf -e non_smtpd_milters=inet:localhost:7080
    sudo postconf -e milter_default_action=accept
    sudo systemctl reload postfix
  5. Retire the content filter. Remove the -o content_filter=dfilt: line and the dfilt pipe service from master.cf and reload again. Leave the script on disk for a few days if you want a fallback, then delete it along with the filter user and the /var/spool/filter directory.

One detail worth checking during the move: the old setup usually attached the filter to the smtp service only, so mail submitted on ports 587 and 465 quietly skipped the disclaimer. smtpd_milters covers every smtpd instance at once, and non_smtpd_milters covers locally submitted mail from cron jobs and applications, so expect the milter to catch messages the content filter was missing.

alterMIME vs MSH Postfix Milter

RequirementalterMIMEMSH Postfix Milter
Attaches to Postfix ascontent_filter pipe + shell scriptMilter
Plain-text disclaimerYesYes
Reliable HTML disclaimerFragileYes, with matching text alternative
Inline logo imagesNoYes - CID, Base64, or external URL
Per-user name and job titleOne generated file per userYes, from directory attributes
Stops disclaimers repeating on repliesNoYes
Outgoing-only or per-domain scopingShell script and address listsRule conditions
Covers submission on 587 and 465Only if wired up per serviceYes, via smtpd_milters
Signs cleanly with OpenDKIMRe-injection breaks existing signaturesYes, ordered ahead of the signing milter
Autoresponder and out-of-officeNoYes
Attachment blocking and strippingBy filename onlyBy name, type, or size
Test a change without sending mailNoYes, rules tester
LicenceFree, effectively unmaintainedCommercial, with a free trial

The summary is short. alterMIME is the right tool for a static plain-text footer on one domain, and it costs nothing. Once the requirement includes designed HTML, per-employee details, or scoping rules that a colleague can read a year from now, you are no longer maintaining a footer - you are maintaining a mail-rewriting application written in shell.

Frequently asked questions

What is alterMIME used for?

alterMIME is a small C utility that rewrites MIME-encoded mail. On Postfix servers it is almost always used from a content_filter shell script to append a disclaimer or signature to outgoing mail, and occasionally to strip attachments or add an X- header.

Is alterMIME still maintained?

Barely. The upstream release on pldaniels.com is 0.3.11 and the official changelog stops in 2010. A 0.3.12 tag exists in the inflex/alterMIME GitHub repository from 2023. Distributions still package it, so it installs and runs, but it is not actively developed.

What is the best alterMIME alternative for Postfix?

For disclaimers and signatures the realistic options are a milter or a full content-filter stack such as amavisd-new. MSH Postfix Milter is a direct replacement: it attaches through smtpd_milters instead of content_filter, handles HTML and plain-text alternatives, and replaces the shell script and address lists with rules you edit in an admin panel.

Why does my alterMIME disclaimer repeat on every reply?

alterMIME appends unconditionally. It has no idea the disclaimer is already present further down the thread, so each reply and forward adds another copy. MSH Postfix Milter has duplicate detection with an adjustable sensitivity level that stops the disclaimer stacking up.

Does replacing alterMIME with a milter fix DKIM?

It fixes the ordering problem behind most broken signatures. A content filter modifies the body and re-injects the message, which invalidates a DKIM signature that was already applied. Milters run in the order listed in smtpd_milters, so placing the disclaimer milter before OpenDKIM means the message is signed after the disclaimer is added.

Can I migrate from alterMIME without downtime?

Yes. The milter and the content filter are independent, so you install the milter, verify it with the rules tester, then remove the content_filter entry from master.cf and reload Postfix. Mail keeps flowing throughout, and the only moment that matters is the reload.

Can an alterMIME alternative insert per-user details like name and job title?

alterMIME cannot - it appends a static file, so per-user signatures mean generating one file per employee from a script. MSH Postfix Milter reads user attributes from a directory service and substitutes placeholders such as name, title, and phone at the moment the message is processed.

Try it on your own server

Install it alongside your existing alterMIME filter, rebuild one disclaimer as a rule, and compare the result before you change anything in master.cf.

Start a free trialDownload

Related reading: configuring a Postfix disclaimer, disclaimers on outgoing mail only, per-user signatures, and pricing. For the configuration details, see the quick start guide, disclaimer rules, and the rules tester.