Generally there are two types of bounces
- The bounces caused by directrejection of remote mail server when your postfix deliver the email.
- The bounces caused by remote server (next-hop server after your postfix) fails to deliver the message to final recipients.
The first case was already covered by excellent answer by Esa Jokinen above. Your best bet is parsing maillog.
The second case was special case of bounces. The example scenario:
- You send email with recipient firstname.lastname@example.org to mail.example.com server.
- In mail.example.com, email@example.com was aliased to firstname.lastname@example.org and must be forwarded to mail.example.net.
- Someday mail.example.net reject the your message so mail.example.com must send bounces to your server.
- Unfortunately maillog in your server will have "dsn=2" because mail.example.com already accepted the message but failed to forward it to mail.example.net.
Here the example of second type bounces email. There is forwarding rule Yahoo mail server email@example.com -> firstname.lastname@example.org. Unfortunately mail server of example.net reject the message :(
From MAILER-DAEMON Thu Mar 5 05:07:26 2015
Received: from nm21-vm7.bullet.mail.gq1.yahoo.com (nm21-vm7.bullet.mail.gq1.yahoo.com [184.108.40.206])
(using TLSv1 with cipher ECDHE-RSA-AES128-SHA (128/128 bits))
(No client certificate requested)
by mx.example.org (Postfix) with ESMTPS id D6365565FC
for <email@example.com>; Thu, 5 Mar 2015 05:07:25 +0700 (WIT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=bounce; t=1425506842; bh=zk/tWZNl6c36dmlPDmakM9ekK8cHVJANXMmSdsbkcWc=; h=From:To:Date:Subject:From:Subject; b=Im95h1qTg6qN3yUI7vF1fXtJ0SbUnzv8rUPwLbpNwxGPN2p8wfosXJzQgJ3nzr4L4ZQ50P2d9E9U4jEUNtnyi7nlFd5kKbtiVuda4H56h1PFnt+7wSpgHcd5Irs/lLODumb6ZZSEpCOWttcB9+JLaDfEUUPjGcbR+xww4XeH5Eo=
Date: Wed, 04 Mar 2015 22:07:22 -0000
Subject: Failure Notice
Sorry, we were unable to deliver your message to the following address.
Remote host said:
550 5.1.1 User unknown
For this case, your only method is parsing the bounces message. Unfortunately there are no standard bounces format, so you must parsing the body and determine the rejection caused.
The feature checklist of your postfix bounce parsing:
- Check if VERP address was valid. You don't want to parse invalid message.
- Parse the body, determine if they are soft or hard rejection.
For the second feature, you can google some common rejection message. The example is this bounce-regex-list.xml by Jakub Liska.
Esa Jokinen made a good point in the comment below about these two bounce types. If your goal is keep the server reputation, then dealing the first bounce type should be enough. The second bounce was about cleaning your lists. So dead email should be erased thus freeing some resources in your server.
Some mailing list managers such as PHPlist and Mailman also deal with this bounce problem with parsing the email body as they have no resources to parsing the maillog.