AS2 MDN Not Received: Why Your Receipt Never Arrives and How to Fix It
Your Message Sent. The MDN Never Came Back.
This is different from "MDN verification failed." That means you got an MDN but your system couldn't validate it. This article covers a worse situation: the MDN simply never arrives. Your message goes out, your partner's system processes it (maybe), and you're left staring at a pending status that never resolves.
No MDN means no proof of delivery. For DSCSA compliance and many EDI agreements, that's a problem. You can't prove your trading partner received the transaction. And the root cause could be on your side, their side, or somewhere in between.
Let's systematically figure out where your MDN went.
First: Is the Message Actually Arriving?
Before troubleshooting the missing MDN, confirm the message itself is reaching your partner. A missing MDN might simply mean the message never got there.
Check your outbound logs for the HTTP response code:
- HTTP 200 or 202: The partner's server accepted the message. The MDN problem is separate from message delivery.
- HTTP 4xx or 5xx: The message was rejected. Fix the delivery problem first. See our connection troubleshooting guide for HTTP error diagnosis.
- No HTTP response at all: The connection failed. You have a network problem, not an MDN problem.
If you got a 200 back and still have no MDN, keep reading.
Synchronous MDN: Why the Response Is Empty
With synchronous MDNs, the receipt comes back on the same HTTP connection as the message delivery. Your system sends a POST, and the partner's system returns the MDN in the HTTP response body. Simple in theory. Here's what goes wrong.
The Partner's System Isn't Generating an MDN
The partner's AS2 server accepted the message but isn't configured to return an MDN for your partnership. This happens more often than you'd expect, especially when the partner has dozens or hundreds of trading relationships and your partnership was set up manually.
How to confirm: Ask your partner to check their partnership configuration for your AS2 ID. Specifically, ask whether MDN generation is enabled for your partnership and whether it's set to synchronous mode.
What to look for in your HTTP response:
# Send a test message and capture the full response
curl -v -X POST https://partner.example.com/as2 \
-H "AS2-From: YOUR_AS2_ID" \
-H "AS2-To: PARTNER_AS2_ID" \
-H "Message-ID: <test-123@your-domain.com>" \
-H "Content-Type: application/pkcs7-mime" \
--data-binary @test_message.as2 \
2>&1 | tee response.txtIf the response body is empty or contains only a generic acknowledgment (like plain text "OK") instead of a multipart/report MIME structure, the partner's system is not generating an MDN.
Timeout Before the MDN Returns
Your system sends the message. The partner's system starts processing. Processing takes longer than your HTTP client timeout. The connection closes. The MDN was being prepared but never made it back to you.
Symptoms:
- Your logs show a timeout or connection reset error
- The partner's logs show the message was processed successfully and an MDN was generated
- The problem happens more with large payloads or during peak hours
Typical timeout thresholds:
- Most AS2 software defaults: 30 to 60 seconds
- Nginx proxy_read_timeout: 60 seconds
- AWS ALB idle timeout: 60 seconds
- Apache reverse proxy: 60 seconds
Fix options:
- Increase your HTTP client timeout. Most AS2 software lets you configure this per partnership. Set it to 120 or 180 seconds.
- If the partner consistently needs more than 60 seconds to process and respond, switch to asynchronous MDNs. That's what async mode was designed for.
- Check for intermediary timeouts. If there's a load balancer or reverse proxy between you and the partner, its timeout may be lower than your client's timeout.
Load Balancer Dropping the Response
The partner has a load balancer in front of their AS2 server. The message goes through. The backend processes it and generates an MDN. But the load balancer's connection to the backend timed out or was reset, so the MDN never makes it back through the load balancer to you.
How to identify: You'll typically see an HTTP 502 or 504 error instead of a proper MDN. Or you'll get a 200 with an empty body, because the load balancer returned its own response after the backend went silent.
Fix: This is the partner's infrastructure problem. Share the exact timestamps and HTTP response details so they can check their load balancer logs. They'll likely need to increase their backend timeout or health check settings.
Asynchronous MDN: Where the Receipt Gets Lost
With async MDNs, the partner returns an immediate HTTP 200 to acknowledge receipt of your message. Then, separately, their system sends the MDN to your receipt URL via a new HTTP POST. More moving parts means more places for things to break.
Your Receipt URL Is Wrong
The receipt URL is specified in the Receipt-Delivery-Option header of your outgoing AS2 message. If this URL is wrong, the MDN goes to the wrong place (or nowhere).
Check your outgoing message headers:
# Look for this header in your outbound AS2 message logs
Receipt-Delivery-Option: https://your-server.example.com/as2/mdnCommon mistakes:
- HTTP instead of HTTPS (partner's system may refuse to send MDNs over unencrypted connections)
- Wrong port number
- Wrong path (
/as2/mdnvs/as2/HttpReceivervs/mdn) - Internal hostname or IP that isn't reachable from the partner's network (e.g.,
http://192.168.1.50/as2/mdn)
Verify your receipt URL is reachable from the outside:
# From a machine outside your network (or use a service like reqbin.com)
curl -v -X POST https://your-server.example.com/as2/mdn \
-H "Content-Type: text/plain" \
-d "test"You should get an HTTP response (even an error response is fine; it proves the URL is reachable). A connection timeout means the URL is not accessible from the internet.
Your Firewall Is Blocking the Inbound MDN
Your AS2 messages go out (egress). The async MDN comes in (ingress) as a separate HTTP POST from your partner's system. If your firewall only allows outbound connections to your partner but doesn't allow inbound connections from them, the MDN gets dropped.
Diagnose:
# Check if your AS2/MDN port is accepting connections
# Run this on your server
ss -tlnp | grep :443
# Check firewall rules (Linux)
sudo iptables -L -n | grep 443
# Or with firewalld
sudo firewall-cmd --list-allWhat to verify:
- Your firewall allows inbound HTTPS (port 443 or whatever port your AS2 receiver runs on) from your partner's IP range
- If you use security groups (AWS) or network security groups (Azure), the inbound rule exists
- If you're behind NAT, the port forwarding rule maps to your AS2 server
Ask your partner for their outbound IP addresses. They may send MDNs from a different IP than the one that receives your messages. Whitelist all of them.
DNS Issues on the Return Path
Your partner's system needs to resolve your hostname to send the async MDN. If their DNS can't resolve your receipt URL's hostname, the MDN goes nowhere.
This is easy to miss because your outbound messages work fine (you can resolve their hostname), but they can't resolve yours.
Diagnose (ask your partner to run this):
# From the partner's AS2 server
nslookup your-server.example.com
dig your-server.example.comIf the hostname doesn't resolve from their network, check:
- Is the DNS record published?
dig your-server.example.com @8.8.8.8 - Is it a private/internal hostname that only resolves inside your network?
- Did the DNS record recently change, and their DNS cache still has the old record?
TLS Issues on the Return Path
Your receipt URL uses HTTPS (it should). The partner's system initiates a TLS connection to your server to deliver the MDN. If the TLS handshake fails, the MDN is lost.
Common TLS problems on the return path:
- Your TLS certificate is expired
- Your TLS certificate is self-signed and the partner's system doesn't trust it
- Missing intermediate certificates in your TLS chain
- TLS version mismatch (your server requires TLS 1.3, their system only supports TLS 1.2)
Test your own TLS setup:
# Check your certificate chain and expiry
openssl s_client -connect your-server.example.com:443 -showcerts
# Check certificate expiry
echo | openssl s_client -connect your-server.example.com:443 2>/dev/null | \
openssl x509 -noout -dates
# Test with SSL Labs (web-based, comprehensive)
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=your-server.example.comThe Partner's System Never Attempted to Send
Sometimes the problem is simple: the partner's system processed your message but never tried to send the async MDN. Their AS2 server might have:
- Crashed during or after processing
- A bug in the async MDN queuing mechanism
- Been configured for synchronous MDN on their side (they think they already sent it on the original connection)
- A full outbound queue that's backed up
How to distinguish "never sent" from "sent but lost":
- Ask your partner to check their outbound MDN logs for your Message-ID
- If they show a successful MDN delivery to your URL, the MDN was sent but lost in transit (network, firewall, TLS, or DNS issue)
- If they show no outbound MDN attempt, their system never tried to send it (configuration or software issue on their end)
- If they show a failed delivery attempt with an error, that error tells you exactly what went wrong
The "MDN Sent but Lost" Checklist
If your partner confirms they sent the MDN and you never received it, something between their system and yours is swallowing it. Work through this checklist:
- Check your AS2 server's access logs. Did the inbound POST request arrive? If yes, your AS2 server received the MDN but failed to process it. Check your AS2 server logs for parsing errors.
- Check your reverse proxy logs. If you run Nginx, Apache, or a load balancer in front of your AS2 server, check its access logs. The request may have arrived at the proxy but not been forwarded.
- Check for WAF or IDS blocks. Security appliances sometimes flag inbound MDN posts as suspicious. The multipart/report content type and binary content can trigger false positives.
- Check your cloud provider's security groups. AWS security groups, Azure NSGs, and GCP firewall rules may not include the partner's outbound IP range for inbound traffic.
- Check NAT and port forwarding. If your AS2 server is behind NAT, verify the port forwarding rule is active and pointing to the correct internal IP.
Correlating Async MDNs to Original Messages
Async MDNs are matched to the original message via the Original-Message-ID field in the MDN body. If this correlation fails, your AS2 system may receive the MDN but not recognize which message it belongs to.
This looks like a missing MDN even though it was received. Your AS2 software's UI shows the original message as "awaiting MDN" while the MDN sits unmatched in the system.
Common causes:
- The partner's system doesn't include the Original-Message-ID or includes it in a non-standard format
- Your Message-ID contained characters that the partner's system mangled (angle brackets, special characters)
- Your system already timed out and discarded the pending message record before the MDN arrived
Fix: Check your AS2 server's received MDN log (separate from the matched MDN log). If unmatched MDNs are piling up, examine the Original-Message-ID field and compare it to your outbound Message-IDs.
Configuring MDN Timeout and Retry
Your AS2 software should have configurable timeouts for async MDN waiting periods. If the MDN doesn't arrive within the timeout window, the message is marked as unconfirmed.
Recommended settings:
- Async MDN timeout: 4 to 24 hours, depending on your partner's SLA. Some partners process messages in batches and don't send MDNs until the batch completes.
- Sync MDN timeout: 120 to 180 seconds. Longer than typical HTTP timeouts to accommodate processing time.
- Retry on missing async MDN: Resend the original message after the timeout expires. But set a maximum retry count (2 to 3). If the MDN never comes after retries, escalate to the partner manually.
Diagnostic Commands Reference
Keep these handy when troubleshooting missing MDNs:
# Verify your receipt URL is reachable from the internet
curl -v -X POST https://your-server.example.com/as2/mdn
# Check your TLS certificate chain
openssl s_client -connect your-server.example.com:443 -showcerts
# Check certificate expiry
echo | openssl s_client -connect your-server.example.com:443 2>/dev/null | \
openssl x509 -noout -dates
# Test DNS resolution of your hostname from a public resolver
dig your-server.example.com @8.8.8.8
# Check if your AS2 port is listening
ss -tlnp | grep :443
# Monitor inbound connections in real time
sudo tcpdump -i any port 443 -n
# Check your firewall rules
sudo iptables -L -n | grep 443
# Tail your reverse proxy access logs for MDN deliveries
tail -f /var/log/nginx/access.log | grep POSTQuick Decision Tree
Use this to narrow down the problem fast:
- Are you using sync or async MDN?
- Sync: The MDN should be in the HTTP response body. If it's not there, it was never generated by the partner.
- Async: Continue to step 2.
- Did the partner attempt to send the MDN? (Ask them to check their outbound logs.)
- No attempt: Their configuration is wrong. They need to enable MDN for your partnership.
- Attempt failed: The error in their logs tells you what's broken (DNS, TLS, connection refused, etc.).
- Attempt succeeded: Continue to step 3.
- Did the POST request reach your server? (Check your access logs or reverse proxy logs.)
- No: Firewall, security group, NAT, or WAF is blocking it.
- Yes: Continue to step 4.
- Did your AS2 software process the MDN? (Check for unmatched or errored MDNs in your AS2 logs.)
- No: The MDN was received but not parsed. Check for MIME parsing errors or Message-ID correlation failures.
- Yes, but it shows as failed: You have an MDN verification problem, not a missing MDN problem. See our MDN failures guide.
Prevent Missing MDNs Before They Happen
Most missing MDN issues are discovered in production, after a compliance audit asks for proof of delivery you can't produce. Prevention is straightforward:
- Test the full round-trip (message send, MDN return) before going live with any trading partner
- For async MDNs, verify your receipt URL is accessible from outside your network before the first test
- Confirm sync vs. async MDN mode with the partner explicitly. Don't assume.
- Monitor your MDN receipt rate. If it drops below 100%, investigate immediately rather than waiting for someone to notice
- Keep your TLS certificate current on your receipt endpoint. Set a calendar reminder 30 days before expiry.
AS2 Certify tests the complete MDN round-trip on every connection validation. It sends a test message to your AS2 endpoint and verifies that the MDN comes back, whether synchronous or asynchronous. If the MDN is missing, the test report identifies exactly where the chain broke: was it the receipt URL, the firewall, the TLS handshake, or the partner's MDN configuration? You get the answer in minutes instead of days of back-and-forth email with your trading partner.