← Back to all products
$19
Bounce Handler
Parse email bounces, extract diagnostic info, and automatically clean mailing lists.
JSONMarkdownPython
📄 Product Preview
Try the interactive reader and demo tools below, or get the full product with all content unlocked.
📖 Interactive Reader (Free Preview) ⚙ Try Demo Tools 📦 Download Free Sample📁 File Structure 10 files
bounce-handler/
├── LICENSE
├── README.md
├── examples/
│ └── sample_bounces.json
├── free-sample.zip
├── guide/
│ ├── 01_features.md
│ ├── 02_quick-start.md
│ ├── 03_bounce-categories.md
│ └── 04_faq.md
├── index.html
└── src/
└── bounce_handler.py
📖 Documentation Preview README excerpt
Bounce Handler
Parse and categorize email bounces (hard/soft), extract diagnostic info, and automatically clean your mailing lists by removing permanently undeliverable addresses.
Features
- Hard/soft/unknown classification — Categorizes bounces by SMTP response codes
- SMTP code matching — Recognizes 550, 421, and dozens of enhanced status codes
- Regex pattern matching — Catches bounces from non-standard error messages
- Raw .eml parsing — Extract bounce info directly from bounce notification emails
- List cleaning — Removes hard-bounced addresses from your mailing list
- JSON/CSV output — Export categorized bounces for further processing
- Diagnostic extraction — Pulls the human-readable error message from each bounce
Requirements
- Python 3.10+
- No external dependencies (stdlib only)
Quick Start
# Categorize bounces from a JSON file
python src/bounce_handler.py --input examples/sample_bounces.json
# Parse a raw bounce email (.eml)
python src/bounce_handler.py --parse-raw bounce_notification.eml
# Clean a mailing list by removing hard bounces
python src/bounce_handler.py --input bounces.json --clean emails.txt --output clean.txt
Input Format
The tool expects a JSON array of bounce records:
[
{
"email": "user@example.com",
"smtp_code": "550",
"diagnostic": "5.1.1 The email account does not exist",
"timestamp": "2026-03-14T12:00:00Z"
},
{
"email": "other@example.com",
"smtp_code": "421",
"diagnostic": "Try again later",
"timestamp": "2026-03-14T12:01:00Z"
}
]
Bounce Categories
| Category | SMTP Codes | Action |
|---|---|---|
| Hard bounce | 550, 551, 552, 553, 554, 5.1.1, 5.1.2, etc. | Remove from list immediately |
| Soft bounce | 421, 450, 451, 452, 4.2.2, etc. | Retry later, remove after 3+ consecutive |
| Unknown | Unrecognized codes or missing data | Review manually |
... continues with setup instructions, usage examples, and more.
📄 Code Sample .py preview
src/bounce_handler.py
#!/usr/bin/env python3
"""
Bounce Handler — Email Arsenal (DataNest)
Parses and categorizes email bounces (hard/soft), extracts diagnostic info,
and cleans mailing lists by removing permanently undeliverable addresses.
Usage:
python bounce_handler.py --input bounces.json
python bounce_handler.py --input bounces.json --clean emails.txt --output clean.txt
python bounce_handler.py --parse-raw bounce_email.eml
Dependencies: Python 3.10+ stdlib only
License: MIT
"""
from __future__ import annotations
import argparse
import csv
import json
import logging
import re
import sys
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from enum import Enum
from pathlib import Path
from typing import Any
# ---------------------------------------------------------------------------
# Constants
# ---------------------------------------------------------------------------
logger = logging.getLogger("bounce_handler")
# SMTP response codes that indicate hard bounces (permanent failures)
HARD_BOUNCE_CODES = frozenset({
"550", "551", "552", "553", "554", # Various permanent failures
"5.1.1", # Bad destination mailbox address
"5.1.2", # Bad destination system address
"5.1.3", # Bad destination mailbox address syntax
"5.1.6", # Destination mailbox has moved
"5.4.1", # No answer from host
"5.7.1", # Delivery not authorized
})
# SMTP response codes that indicate soft bounces (temporary failures)
SOFT_BOUNCE_CODES = frozenset({
"421", "450", "451", "452", # Various temporary failures
# ... 357 more lines ...