Use Python or PHP Scripts to Process DSN Reports Offline
Automate DSN report parsing with Python or PHP scripts to reduce bounces and improve deliverability.
Why offline DSN report processing matters for list hygiene
You’re sending emails. Some bounce. You see the reports, but never act on them. Why? Because DSNs look like log salad—raw, nested, and hard to parse. But skipping them? That’s like ignoring the warning lights on a dashboard while speeding toward a crash.
DSN reports contain real-time feedback about delivery failures—hard bounces, mailbox overflows, rejected domains. Yet most teams let them pile up, missing golden opportunities to clean their lists before reputation degrades. Processing them offline with Python or PHP scripts turns chaos into clarity. You avoid system load during send windows, ensure consistent analysis across batches, and build audit trails that prove compliance.
Ignoring DSNs isn’t just passive—it’s costly. Bounced addresses stay in your list. Sender reputation drops. Spam traps trigger. You don’t need more tools. You need discipline. The fix? A script that reads DSNs offline, flags invalid addresses, and logs decisions systematically.
Key takeaways
- DSN reports reveal failed deliveries in real time but require parsing to be actionable.
- Processing DSNs offline with Python or PHP scripts avoids real-time system load and enables repeatable, audit-ready validation.
- Skipping DSN analysis allows invalid addresses to persist, harming sender reputation and increasing spam trap exposure.
What are DSN reports, and why do they matter?
DSN reports (Delivery Status Notifications) are automated SMTP responses sent by mail servers when an email fails to deliver. They include precise status codes like 550 or 5.1.1, diagnostic details, and the original recipient address — signals that reveal permanent delivery failures such as invalid emails, disabled accounts, or blocked domains. You can use Python or PHP scripts to process these reports offline, turning error data into actionable list hygiene results.
How DSN reports work in practice
When your mail server attempts to send an email and the recipient server rejects it, it sends back a DSN report via SMTP, typically to a predefined email address. This feedback isn't just a bounce — it’s structured data with standardized codes. For example, a 550 error means the recipient address doesn’t exist; a 5.1.1 means the mailbox was permanently rejected. These signals are reliable indicators of address validity, far more precise than a simple "failed" status.
Let’s say your campaign sends 10,000 emails. If 300 bounce with a 550 status and no recipient is found, you know those addresses should be removed. Unlike soft bounces (temporary issues), DSN failures like 550 or 5.2.2 are nearly always permanent. Processing these offline with scripts lets you automate cleanup without relying on third-party services — you keep control of the data, audit trail, and timing.
These reports follow IETF standards, defined in RFC 3464, which ensures consistency across email providers. The structure includes fields like the original recipient, final status code, diagnostic code, and the sending server’s IP — all useful for diagnosing issues in your outbound flows.
Why they’re essential for deliverability
Ignoring DSN reports leads to poor sender reputation. Sending to invalid or blocked addresses triggers spam filters and can get your domain blacklisted. A well-maintained list reduces bounce rates, improves inbox placement, and lowers the risk of being flagged by services like Spamhaus or MXToolbox.
You can use tools like bulk email list cleaning to pre-validate addresses before sending, but DSNs help you catch what slips through. They serve as a post-send feedback loop — one you can script in Python or PHP to parse, analyze, and update your database automatically.
How to parse DSN reports using Python or PHP scripts
You can process DSN reports offline using Python or PHP by parsing their MIME format structure. Use Python’s built-in email module or PHP’s mailparse extension to extract headers and body content. The Status header (like 5.1.1) indicates failure type—5xx means permanent, 4xx means transient—and Final-Recipient gives the exact email that failed. This lets you automate rejection of invalid or undeliverable addresses.
Step-by-step parsing process
- Read the DSN report file—it's typically a MIME-encoded message with a
message/delivery-statuscontent type. In Python, useemail.message_from_file()oremail.message_from_string(). In PHP, usemailparse_msg_parse_string()after enabling the extension. - Extract the Status header—look for
Status(e.g.,5.1.1) in the report. Codes starting with 5 indicate permanent failures (like invalid syntax or non-existent domains). Codes starting with 4 indicate temporary issues (like server timeouts). This distinction is essential to avoid treating recoverable issues as permanently invalid. - Identify the failing recipient—use the
Final-Recipientfield to get the exact email address. This is critical for updating your contact list or debugging delivery issues at scale. It’s often in the formatrfc822;[email protected], so parse the portion after the semicolon if needed. - Parse additional metadata—extract
Original-Message-ID,Diagnostic-Code, andRemote-MTAfor deeper diagnostics. These help distinguish between issues caused by the recipient’s server (e.g.,host unknown) versus your sending infrastructure. - Store or act on the result—record the address and reason in a database, flag it in your list, or purge it if it’s a 5xx failure. This reduces bounce rates and protects sender reputation.
Why structure matters
DSN reports follow RFC 3464, which defines their MIME format and required fields. Adhering to the standard ensures your parser handles edge cases like multi-line headers or base64-encoded bodies correctly. The original RFC is the definitive reference for field meanings and formatting.
For teams that generate hundreds of DSN reports daily, automating parsing with scripts saves time and prevents manual errors. You’re not limited to Python or PHP—any language with MIME parsing support works. But these two are widely available, well-documented, and integrate easily with existing infrastructure.
If you're building a system to verify email lists at scale, consider validating your data before sending. Our bulk email list cleaning tool detects invalid, malformed, and risky addresses before they hit your ESP, reducing bounces and protecting your sender reputation.
Common DSN failure codes and their meaning in list hygiene
You can use Python or PHP scripts to process DSN reports offline by parsing bounce response codes. Each code reveals a specific delivery issue—like "user unknown" or "mailbox full"—that informs list hygiene. Understanding these codes lets you automate cleanup: delete permanent failures, pause on temporary ones, and flag risky addresses. It's not just about filtering bounces—it's about turning raw DSN data into actionable list health insights.
DSN codes and their impact on list hygiene
DSN (Delivery Status Notification) codes are standardized by RFC 3463. They help distinguish between temporary delivery problems and permanent failures. When processing DSNs offline with scripts, you need to map these codes to real-world actions.
| DSN Code | Meaning | Recommended Action |
|---|---|---|
| 5.1.1 | User unknown — the mailbox does not exist on the recipient’s mail server. | Remove from the list permanently. This is a hard bounce. No further sending should occur. |
| 5.2.1 | Mailbox full — the recipient’s inbox has exceeded capacity. | Mark as temporary. You may retry after a grace period, but repeated occurrences indicate outdated or inactive addresses. Consider removing after 2–3 failures. |
| 5.2.2 | Mailbox not found — no such user exists at the domain. | Remove immediately. This is equivalent to 5.1.1—permanent failure. Likely due to typos or dead accounts. |
| 5.7.1 | Blocked by policy — the recipient server rejected the message based on content, sender reputation, or filtering rules. | Do not resend. This often results from greylisting, spam filters, or domain-level blocks. Avoid further delivery attempts until sender reputation improves. |
These codes reflect what mail servers are actually experiencing. You can use Python or PHP to read and parse DSNs from log files or email systems, then apply rules based on the status. For example, a script might count failures above a threshold and automatically flag or delete addresses.
When you’re cleaning lists at scale, relying on these codes alone isn’t enough. They tell you what failed, but not why. Adding a real-time email verification API or bulk validation tool improves precision. Tools like bulk email list cleaning can catch invalid addresses before they trigger bounces and confirm whether an address is deliverable—long before your campaign sends.
For more context, the RFC 3463 defines the standard DSN status codes. You can also look at Mail-Tester’s analysis of common bounce reasons to see how real-world filters apply these codes.
How to structure the output: from raw log to actionable list
You should save parsed DSN reports to a CSV or JSON file with columns for email, status, diagnostic, and timestamp. Group failed deliveries by reason—like “user unknown” or “domain not found”—to spot patterns, such as high failure rates for a single domain. Use this structured output to flag or remove invalid addresses before your next email send, reducing bounces and protecting sender reputation.
Build a clean, query-ready output format
Start by processing your DSN logs into a predictable structure. Each row should include: the recipient email, the final status (e.g., 5.1.1, 5.2.2), a human-readable diagnostic, and the timestamp of the failure. This format makes it easy to analyze trends and filter data later. Tools like bulk email list cleaning can process these files to help remove invalid entries at scale.
CSV files work well for quick analysis in spreadsheets. JSON offers more flexibility for programmatic use. Both support structured filtering—say, grouping all “5.1.1: user unknown” entries. You can use Python’s csv or json modules, or PHP’s fputcsv and json_encode, to output cleanly. This raw-to-structured path is standard: see RFC 3463 for message delivery status codes, which define the meaning behind common error codes like 5.1.1 or 5.2.2.
Spot patterns to improve deliverability
Once you’ve structured the data, group failures by diagnostic reason. A single domain returning “5.5.2: mailbox full” across hundreds of addresses? That’s a red flag. Or, if 40% of one subdomain fails with a “5.2.2: host not found,” you may have a DNS misconfiguration. Tools like MxToolbox or Spamhaus can confirm if a domain is blacklisted or has broken MX records.
Automate this by writing a script that counts failure types and alerts you when a single reason appears beyond expected rates—say, 10% of a list fails due to “temporary unavailable” (4xx codes), which usually indicates greylisting or server overload. These patterns inform your next steps: clean the list, update your email provider settings, or pause sends to that domain. Over time, this reduces hard bounces and protects your sender reputation. You’re not just reacting to failures—you’re preventing them.
Integrating DSN processing into a list hygiene workflow
Use Python or PHP scripts to parse DSN reports offline, then schedule them daily via cron or Task Scheduler. Process results to flag invalid or hard-bounced addresses, merge findings into your list hygiene system, and use the output to audit acquisition sources and improve data quality. This reduces bounce rates and protects sender reputation over time.
Automate DSN analysis with scheduled scripts
- Set up a daily job using cron (Linux) or Windows Task Scheduler to run your DSN processing script. This ensures you’re proactively catching failures without manual intervention. Scheduled execution is industry-standard for maintaining consistent list integrity.
- Parse DSN messages using a script that reads raw MIME-formatted DSN emails. Extract fields like status code, diagnostic text, and original recipient. Libraries like Python’s
emailmodule or PHP’sMail_MimeDecodehandle this reliably. - Classify bounce types based on status codes. A 5xx error means a hard bounce — the address is permanently invalid. Treat 4xx with caution; they may indicate temporary issues, but persistent ones should be flagged.
- Export results to a structured format like CSV or JSON. Include the original email, bounce type, date, and diagnostic code. This enables consistent integration with other systems.
Embed results into your hygiene pipeline
- Feed outputs into your list hygiene system. Merge the processed DSN data with your existing list. If an email appears in a DSN report as hard-bounced, mark it for removal in your database or CRM.
- Use flags to track problematic sources. If a cluster of hard bounces comes from a specific campaign, landing page, or form, audit the acquisition method. This helps identify poor-quality data collection practices.
- Monitor trends over time. Run the same script monthly to compare bounce rates across sources. A sudden spike may indicate form spam or outdated list reuse.
- Improve future data acquisition. Apply insights from DSN trends to refine signup forms, add validation tiers, or discontinue low-quality sources. This builds a self-correcting data pipeline.
For large-scale operations, combine offline DSN processing with real-time verification. Tools like real-time email verification APIs help prevent bad addresses from entering your list in the first place, while DSN scripts catch what slipped through.
For context, DSNs are defined in RFC 3464, which standardizes message delivery status reporting. This ensures interoperability across systems.
Why scripts beat manual analysis for large-scale DSN handling
You can’t process thousands of DSN reports by hand without introducing errors or missing critical patterns. With 100K email sends, hundreds of DSNs arrive in minutes—each one needs parsing, flagging, and routing to the right team. Scripts handle this at scale: consistent, fast, and without fatigue. They turn noise into action.
Scale demands automation—manual work breaks
A single email campaign sending to 100,000 recipients can trigger hundreds of DSNs in a matter of hours. Handling those by spreadsheet or clipboard is not just slow—it’s guaranteed to miss patterns, misclassify bounces, or log them incorrectly. The human error rate spikes under volume and repetition.
Scripts eliminate guesswork. They apply the same rules every time—no fatigue, no oversight, no "I’ll just skip this one." Whether it’s a permanent failure, a transient delay, or a policy block, the logic is fixed. That consistency is critical for accurate deliverability reporting.
Scripts integrate cleanly into existing workflows
You don’t need API keys from your ESP or access to a vendor dashboard. DSNs typically arrive as raw email messages, often in mbox or RFC 5322 format. A Python or PHP script can parse these directly from your mail server or log storage, then forward actionable data to your CRM, analytics tool, or internal system.
As the Internet Engineering Task Force (IETF) notes in RFC 3464, DSNs follow a strict structure. Scripts can extract fields like status codes, diagnostic codes, and original recipient addresses reliably—something far harder to do manually at scale.
For teams already tracking bounces and delivery issues, this is a direct upgrade. You're not replacing your infrastructure—you're making what exists work better. You can even use tools like bulk email list cleaning to proactively remove invalid addresses before sending, reducing future DSN volume and improving sender reputation.
How Email List Validation complements offline DSN processing
You can take DSN reports, extract bounce-heavy addresses, and verify them at scale using our API to catch invalid, catch-all, role-based, and disposable email addresses that DSNs alone miss. This reduces future bounces, improves sender reputation, and ensures your sending list stays clean without relying on reactive, incomplete data.
- Process DSN output to extract hard bounces, transient failures, and delivery errors — the raw, actionable signals you can't ignore.
- Use our real-time verification API to validate the flagged addresses in bulk, achieving 98.9% accuracy with full infrastructure support.
- Go beyond DSNs: detect catch-all domains, role-based emails (like admin@ or sales@), and disposable domains that DSNs often misread as valid or don’t catch at all.
- Automate cleaning by importing your DSN-derived list into our bulk verification tool—no scripting required.
- Review flagged results with confidence: our in-app AI assistant helps clarify ambiguous responses (e.g., “risky” or “catch-all”) and prioritizes which addresses to remove or re-verify.
- Compare your deliverability trends before and after cleanup using our inbox placement testing, which measures actual inbox delivery against known filters and spam engines.
Why DSNs alone aren’t enough
DSN reports tell you what failed, but not why—especially when it comes to subtle red flags like role accounts or temporary email domains. A single "550" error might mean a non-existent inbox, but it’s equally common with role addresses used by large senders. According to RFC 3463, DSNs convey delivery status but do not validate email address syntax, existence, or user preference.
Integrate clean data into your workflow
Once cleaned, your list integrates directly with platforms like Mailchimp, HubSpot, and Klaviyo via our native integrations, reducing future bounce rates and protecting your sender reputation. This closes the loop: DSNs alert you to issues, and validation ensures you act on them correctly.
Handling DSNs with multiple delivery errors per email
When a DSN report includes multiple delivery responses, extract only the final recipient status—ignore intermediate transient failures (like 4xx codes)—and focus on persistent issues (5xx) that indicate real delivery problems. Track repeated failures on the same domain to spot systemic issues like DNS misconfiguration or blacklisting, and use that data to improve your sender reputation.
Extracting the final delivery outcome
DSN reports sometimes list multiple status codes per email—especially when a message passes through several relay servers or gets retried. Only the last status code for a given recipient matters. For example, a 4xx error during a retry doesn’t mean the email failed permanently; a final 5xx response does. Let’s assume you’re processing a report: loop through all delivery statuses and store only the last one per recipient.
In practice, you’ll often find sequences like “450 — mailbox busy” → “451 — temporary error” → “550 — user unknown.” The first two are transient; the third is definitive. Treat the 550 as the final verdict. This avoids false positives and ensures your bounce management reflects actual delivery outcomes.
Identifying recurring domain-level failures
Repeating 5xx errors on the same domain—especially with multiple recipients—suggests a broader problem. It might be that the domain’s mail server is rejecting all incoming messages, or their DNS records (like SPF or DKIM) are misconfigured. If you see three or more failed deliveries to example.com in one batch, that’s a red flag worth investigating.
Use scripting in Python or PHP to group failed emails by domain and count failures within a time window. A single failure may be isolated; five failures to the same domain in 24 hours likely indicates a systemic issue. Tools like MxToolbox or Spamhaus can help validate if that domain is known to block certain senders.
Once identified, you can exclude entire domains from sending until the issue is resolved—or verify their email validity with a service like bulk email list cleaning before sending again.
Following the guidance in RFC 3464 (the standard for DSNs) helps ensure your logic matches how email servers report delivery outcomes. Some implementations still include outdated or redundant statuses, so filtering based on finality (not sequence) gives you the most reliable data.
What to do with the cleaned list after offline DSN processing
After processing DSN reports offline with Python or PHP scripts, you should filter out permanent failures, delay retries for transient ones, and keep diagnostic logs for audit. Then, validate high-value addresses in real time using Email List Validation’s API to confirm they’re still active. Finally, use the cleansed list in campaigns to improve inbox placement and reduce bounce rates. This workflow prevents wasted sends and stabilizes sender reputation.
Step-by-step actions
- Remove permanent failures. Addresses flagged with permanent DSN errors (e.g., 550 User unknown) should be purged immediately. Retaining them risks sender reputation damage and increases deliverability risk.
- Mark transient failures for retry after a delay. Errors like 451 or 421 indicate temporary issues. Use your scripts to tag these and schedule re-validation after a delay—common practice in RFC 8098 for retry logic.
- Archive diagnostic logs. Store full DSN reports in a secure, searchable format. This allows post-mortem analysis and helps correlate patterns across large sends. Industry standards like RFC 3464 outline the expected structure of DSNs.
- Re-test high-value addresses. Not all failures imply invalidity. Some addresses may have bounced due to transient server issues or large volume filtering. Use a real-time verification API to confirm current validity—especially for leads, customers, or partners.
- Apply the cleansed list to future campaigns. Only send to addresses that pass both DSN analysis and real-time validation. This directly reduces hard bounces and improves sender reputation, which is critical for inbox placement.
Why real-time validation matters
DSN data alone can’t confirm if an email address is still active. A domain may have changed policies or introduced new filters since the DSN was generated. You can verify address state with current DNS, MX, and SMTP checks. For example, the IETF’s RFC 8098 details best practices for retry strategies based on DSN codes.
Use Email List Validation’s API to validate the top tier of your list. It checks syntax, domain reachability, mailbox existence, and role account detection—all in seconds. This reduces the risk of sending to outdated or disposable emails before your campaign launches.
After cleaning and validating, integrate the list with your ESP via available integrations. This ensures consistent quality across Mailchimp, Klaviyo, HubSpot, and SendGrid. A cleaner list means lower bounce rates, fewer blocklist incidents, and a more predictable path to the inbox.
Offline processing is not a substitute — it’s a foundation
Processing DSN reports offline gives you reactive insight into delivery failures. Use that data to refine your proactive verification strategy, not replace it.
No tool eliminates all invalid addresses. But when you combine offline DSN analysis with automated verification workflows, you significantly reduce bounce rates and improve deliverability over time.
Accurate verification isn’t just about filtering out bad emails. With Email List Validation’s 98.9% accuracy, you ensure your list remains clean, valid, and deliverable — turning list maintenance into a reliable, ongoing practice.
Keep reading
- List validation API and automation for marketing teams (complete guide)
- How to Use Temporary Error Codes to Improve Retry Scheduling Reliability in Email Validation
- Multi-ESP Suppression List Management via JSON Automation for Deliverability
- Using API Response Codes from ESPs to Identify Invalid Emails
- Mapping 421 Service Unavailable Codes to Retry Protocols in Email Validation Platforms
Ready to put this into practice? Email List Validation verifies emails with 98.9% accuracy — start with 100 free verifications.
Frequently asked questions
Can DSN reports help reduce email bounce rates?
Yes. By identifying invalid or unreachable addresses, DSNs let you remove them from your list before the next send.
Do I need an email service provider API to access DSN reports?
No. DSNs arrive as raw messages via SMTP. You can process them offline without ongoing API access.
Why use Python instead of PHP for DSN processing?
Python has better built-in MIME support and libraries for data analysis. PHP works well but requires additional parsing extensions.
How often should I run DSN processing scripts?
Daily or after every major send campaign, depending on volume and sender reputation risk.
Can DSN reports detect disposable email addresses?
Not directly. They only show delivery failure. Use Email List Validation’s database for detection.
Are DSN parsing scripts secure?
Yes, if you handle raw logs securely, avoid logging personal data, and restrict access to scripts.
What’s the difference between transient and permanent DSN errors?
Transient (4xx) errors may resolve; permanent (5xx) errors indicate a failure that won’t be resolved by retrying.
How do I avoid missing DSNs when processing offline?
Ensure your mail server forwards DSNs to a dedicated mailbox, and use a script to monitor it reliably.
Can I process DSNs from third-party ESPs like SendGrid?
Yes, if they send DSNs to your server. You don’t need to use their API to access delivery failure data.
Do DSN reports include the original campaign or subject line?
Not by default. You must attach metadata (like campaign ID) when sending the email to link DSNs to campaigns.
What’s the benefit of combining DSNs with Email List Validation?
DSNs identify failures; Email List Validation finds invalid, role, and disposable addresses before they fail.
How much time does offline DSN processing save compared to manual review?
A single campaign with 50K sends can take hours to review manually. Scripts do it in minutes with full consistency.