Recognize rejection at the end of transmission
A WordPress site sends some emails correctly. For others, its log shows DATA END command failed, followed by 552 5.3.4 and a message indicating excessive size. The WordPress forum describes this case for notifications sent through an SMTP relay. The trace places rejection after transmitting the message to the queried relay. In this specific case, the server did not accept the message at that stage. Forum discussion mentions several possible causes and does not measure the limit applying to that site.
Record the full code and response text. SMTP code 552 alone may accompany other rejections. Enhanced code 5.3.4 describes a message too large for the system. 5.2.2 points to a full mailbox and 5.7.x to a security or delivery policy. Timing matters too. An error during sending in WordPress, before any SMTP dialogue, calls for another check. If the relay accepted the message with 250 at the end of DATA and a nondelivery notice arrived later, the first relay took responsibility for the message. Then identify the next server that issued rejection.
An SMTP test containing a few words checks that the account and relay can send a small message. The same route may reject a notification containing a PDF, several images or automatically added content. Compare the same event type, sender, staging recipient and transport. A test email from one plugin's settings and a receipt generated by another may take different routes. In the log, associate the test with a time and identifier, not just the sender's name.
- Record the notification type, log time zone, SMTP phase and full code. Copy neither login credentials nor message content into a shared ticket.
- Check whether the fault affects all notifications, a particular template or only certain attachments. Record application-side file sizes and any embedded logos.
- Keep one successful event and one failing event, both fictional if recreating them. Record which server responded and whether it returned a queue ID.
Compare messages using the same settings
With dashboard access, first identify the component actually producing the notification. In its mail settings screen, find the template, recipient and section attaching or generating files. If the attachment is generated after user action, such as an assembled report or confirmation PDF, measure the generated output. The uploaded form file's size does not necessarily represent the transmitted attachment's size. A second component may also embed an image or add another attachment to the same notification.
Prepare an isolated copy whose emails are captured by a test relay or controlled mailbox. Disable copy automations that could notify imported contacts. Reproduce three variants with the same action and one test recipient. Start with text only, add a small dummy file, then a larger dummy file or second attachment. Give each variant a distinct marker in its subject or tracking reference. For size diagnosis, change one element at a time. If recipient, template and attachment change together, a difference no longer identifies which variable mattered.
A capture relay may accept every size. In that case, the test confirms WordPress composes all three variants and lets you compare them. It reproduces a limit only if one is configured on the staging relay or the test environment has a policy equivalent to the affected route. Leave headroom below the documented limit, because a downstream relay may add headers and a provider may apply a stricter rule to certain routes.
- Trigger the attachment-free version and record its status in the transport log. Check that it appears in the staging mailbox or capture.
- Repeat with the small attachment, then the larger version. For each, record file size, full-message size if available, SMTP code and mailbox presence.
- If the small message also fails with another code, resolve that obstacle before measuring a limit. If only the large message encounters
5.3.4, find the limit of the rejecting server.
Read the limit in the correct place
With mail-provider access, find the event in the relay's delivery log. Filter by time, technical sender and staging recipient, then open the detailed response. A provider may supply size in bytes and each hop's status. Others supply only the SMTP response. If the trace comes from a module replacing SMTP with an API, find request and delivery statuses at that provider. The forum message concerns SMTP, while APIs may use different codes and limits.
An SMTP server may advertise a SIZE extension in its EHLO response. When a positive value is given, it is that server's advertised limit in bytes for its size extension. No usable value does not mean all messages will be accepted. A downstream relay may reject a size accepted by the first. The relevant information is the rule of the server that actually rejected the message, supplemented by the advertised account or route limit.
PHP and media-library limits apply when the file enters WordPress. Here, SMTP dialogue has already received the content. Increasing the upload limit may admit more files and worsen email rejection. Likewise, freeing recipient mailbox space is appropriate for a mailbox-quota diagnosis with corresponding code and trace. For message size, check the sender's policy in bytes and the recipient's if delivery fails after initial acceptance.
- Compare the small-message trace with the large one. Record who responds
250and who responds552 5.3.4. If they come from different servers, record both stages. - Ask for the full-message limit for the transport used. If the provider says “MB”, check the exact byte equivalent and whether the limit concerns the attachment alone or assembled MIME.
- If only support can access the relay log, provide the dummy marker, time, measured size and code. Ask for the rejection phase and route limit without attaching the real notification.
Measure the complete message from a terminal
Base64-encoded attachments grow before transmission. Each group of three bytes becomes four characters, with padding at the end if needed. A 6,000,000-byte attachment therefore already occupies 8,000,000 encoded characters. Line breaks, attachment headers, MIME boundaries and the message body add to that size. An embedded image adds more too. A file limit based solely on PDF size leaves little headroom when the notification contains several elements.
If you have terminal and staging-file access, save this script in a private folder as mesurer-message.php. It loads only the specified WordPress installation's PHPMailer classes and prepares a dummy message in memory. Run php mesurer-message.php "/chemin/wordpress", then php mesurer-message.php "/chemin/wordpress" "/chemin/prive/temoin.bin" with a readable dummy file. The first call gives attachment-free message size. The second displays attachment and complete-MIME bytes. The script has its own 20,000,000-byte limit for controls. That value represents no hosting limit.
The script prepares MIME without opening an SMTP session. It gives an approximate size for a simple message built by the library on disk. The result excludes your plugin template, signatures and headers added by transport, and downstream rewriting. To establish a notification's exact size, compare with the message captured during a dummy trigger or the relay's recorded size. With multiple attachments, add their sizes and overhead, then measure the full notification. A second PDF of a few megabytes can cross the threshold even when each attachment individually respects it.
<?php
declare(strict_types=1);
use PHPMailer\PHPMailer\PHPMailer;
if (PHP_SAPI !== 'cli' || $argc < 2 || $argc > 3) {
exit("Usage : php mesurer-message.php /chemin/wordpress [fichier-fictif]\n");
}
$root = realpath($argv[1]);
$lib = $root === false ? '' : $root . '/wp-includes/PHPMailer';
if ($lib === '' || !is_file($lib . '/PHPMailer.php') || !is_file($lib . '/Exception.php')) {
fwrite(STDERR, "Bibliothèque PHPMailer introuvable.\n");
exit(1);
}
require_once $lib . '/Exception.php';
require_once $lib . '/PHPMailer.php';
$piece = isset($argv[2]) ? realpath($argv[2]) : null;
$taille = 0;
if ($piece !== null) {
if ($piece === false || !is_file($piece) || !is_readable($piece)) {
fwrite(STDERR, "Fichier fictif introuvable ou illisible.\n");
exit(1);
}
$taille = filesize($piece);
if ($taille === false || $taille > 20_000_000) {
fwrite(STDERR, "Utilisez un témoin fictif de 20 000 000 octets maximum.\n");
exit(1);
}
}
try {
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->setFrom('origine@example.test');
$mail->addAddress('capture@example.test');
$mail->Subject = 'RECETTE-TAILLE';
$mail->Body = 'Message de recette.';
if ($piece !== null) {
$mail->addAttachment($piece, 'temoin.bin', PHPMailer::ENCODING_BASE64, 'application/octet-stream');
}
$mail->preSend();
printf("piece_octets=%d mime_octets=%d\n", $taille, strlen($mail->getSentMIMEMessage()));
} catch (Throwable $error) {
fwrite(STDERR, "Impossible de préparer le message témoin.\n");
exit(1);
}Reduce size on the route that failed
Start with content you control. If the attached report uses oversized images, correct the document-generation template. Keep the document readable and check that its pages, text and tables remain complete. If the notification attaches two versions of the same file, remove the unnecessary copy in the staging template. If the file must be transmitted unchanged, a download page with access appropriate to the recipient may suit. Check the link from the profile that must use it and any expiration. A private file placed in a public directory to reduce email size remains accessible according to that directory's rules.
If content must remain identical and you manage the relay, check whether the limit applies to the account, a connector or server. Propose a targeted increase only when the setting is documented and the next route also accepts the new size. Keep a copy of the previous setting. If the provider imposes a fixed limit, adapt the notification or use an approved route suited to the volume. Also check the authorized sender and failure tracking on that route. Recreating the SMTP account or changing DNS records does not resolve a confirmed size rejection for a message already reaching the relay.
A resized file must pass through the same action as the original. Success through a test-send tool does not prove the production notification changed templates. Compare messages again in staging, then check receipt of the complete message. If replacing the attachment with a link, test it with and without expected permissions according to document policy. If the notification fits the correct limit but loses essential information, restore the staging template and try another reduction.
- Change only the setting controlling the attachment or confirmed limit. Record its previous value, new MIME size and change location.
- Repeat the small control, then the corrected case. Check acceptance at the end of
DATA, delivery status and content actually received. - If the case still fails, compare server and code with the initial trace. A new rejection at the next hop needs separate diagnosis. Restore any staging setting that fails to give the intended result.
Retry a specific event and verify receipt
For a notification failing with permanent rejection, first check that the plugin or relay has not retained another attempt for the same event. Depending on the application, the queue may store old MIME or rebuild it from the current template. Retrying an already-assembled copy may send the old attachment again. If the feature can regenerate the message for one event, choose that operation and check subject, attachments and address before proceeding. If you lack access, give the event reference and test result to its owner.
Keep three proofs separate. WordPress or its plugin produced the notification. The relay accepted transmission. The test mailbox received usable content. The wp_mail() documentation states that a positive return does not guarantee receipt. For downstream-server rejection, wait for the relay's final result and check any notice before deciding to resend. If the email contains a temporary link, regenerate it through the intended mechanism instead of retrieving an old copy.
Finish with a second dummy event using the corrected configuration. If the first succeeded only after manual sending, check that the normal trigger uses the same rule and transport. Remove the measurement script and dummy documents from the staging folder after recording results. For a real case, retain measured volume, code and technical identifier in the authorized log. These suffice to compare a recurrence without archiving email contents.
Capture tests locally with Mailpit
Mailpit is a free SMTP capture tool for comparing messages without contacting a real recipient. Install it according to its documentation on your staging machine. By default, its SMTP server listens on port 1025 and its interface on port 8025. Configure it to remain accessible only to your test environment; do not expose a capture mailbox to the Internet.
In the WordPress copy's SMTP settings, enter the host running Mailpit and port 1025. Mailpit's default configuration uses neither authentication nor encryption: this setup is reserved for local capture. If WordPress runs in a container, localhost identifies that container, not necessarily Mailpit's; use the service name or address specified by your environment.
Send a dummy message without an attachment, then the same message with the test attachment. Check their presence in the local interface, contents and received attachments. This capture confirms what WordPress submits to this server; it reproduces neither the provider's limit nor final delivery. Therefore also retain the MIME measurement and redacted actual SMTP rejection. After testing, restore the copy's configuration and delete captured messages.
Sources and references
Use these references to check the features, requirements and limitations described. Reading documentation is not a practical test.
View 7 references
- WordPress forum — WordPress was unable to send the notification email ↗
- IETF — RFC 1870, SMTP message size declaration ↗
- IETF — RFC 3463, delivery status codes ↗
- IETF — RFC 2045, base64 MIME encoding ↗
- WordPress — wp_mail() ↗
- Official documentation — Capture tests locally with Mailpit ↗
- Official documentation — Capture tests locally with Mailpit ↗


