ellite/Wallos · error · Exception

$this->lang('empty_message')

Error message

$this->lang('empty_message')

What it means

PHPMailer throws 'empty_message' (STOP_CRITICAL) in createBody() when the composed message body ends up empty and the instance has exceptions enabled. It signals that send() cannot proceed because there is no HTML or plain-text body to transmit.

Solutions

  1. Set $mail->Body (and optionally $mail->AltBody) to a non-empty string before send()
  2. If using msgHTML(), verify the source HTML is non-empty after rendering
  3. Set $mail->isHTML(true) with a real body instead of relying on defaults

Example fix

// before
$mail->msgHTML($template->render([])); // renders empty
// after
$html = $template->render(['user' => $user]);
if (trim($html) === '') { throw new RuntimeException('Template rendered empty body'); }
$mail->msgHTML($html);
Defensive patterns

Strategy: validation

Validate before calling

if (trim($mail->Body) === '' && trim($mail->AltBody) === '') { throw new LogicException('PHPMailer body is empty; set Body/AltBody before send()'); }

Type guard

function hasNonEmptyString($v): bool { return is_string($v) && trim($v) !== ''; }

Try / catch

try { $mail->send(); } catch (PHPMailer\PHPMailer\Exception $e) { if (str_contains($e->getMessage(), 'empty_message') || str_contains($e->getMessage(), 'Message body empty')) { /* fix body */ } throw $e; }

Prevention

When it happens

Trigger: Calling send()/preSend() when $this->Body and $this->AltBody are both empty (e.g. msgHTML() was given an empty string or a body that rendered to nothing), or a body-building branch produced nothing.

Common situations: Rendering a Twig/Smarty template that outputs only whitespace, calling msgHTML(''), forgetting to set Body/AltBody, or clearing the body after an earlier send() call.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of ellite/Wallos@52820e87ca (2026-09-13). Data as JSON: /api/errors/d3721ba51bbc59d4. Report an issue: GitHub.

Appendix: source

Thrown at libs/PHPMailer/PHPMailer.php:3040

                $body .= static::$LE;
                $body .= $this->attachAll('inline', $this->boundary[3]);
                $body .= static::$LE;
                $body .= $this->endBoundary($this->boundary[2]);
                $body .= static::$LE;
                $body .= $this->attachAll('attachment', $this->boundary[1]);
                break;
            default:
                //Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
                //Reset the `Encoding` property in case we changed it for line length reasons
                $this->Encoding = $bodyEncoding;
                $body .= $this->encodeString($this->Body, $this->Encoding);
                break;
        }

        if ($this->isError()) {
            $body = '';
            if ($this->exceptions) {
                throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
            }
        } elseif ($this->sign_key_file) {
            try {
                if (!defined('PKCS7_TEXT')) {
                    throw new Exception($this->lang('extension_missing') . 'openssl');
                }

                $file = tempnam(sys_get_temp_dir(), 'srcsign');
                $signed = tempnam(sys_get_temp_dir(), 'mailsign');
                file_put_contents($file, $body);

                //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
                if (empty($this->sign_extracerts_file)) {
                    $sign = @openssl_pkcs7_sign(
                        $file,
                        $signed,
                        'file://' . realpath($this->sign_cert_file),
                        ['file://' . realpath($this->sign_key_file), $this->sign_key_pass],

View on GitHub (pinned to 52820e87ca)