Security

Email Security Considerations

Input Sanitization

Always sanitize user-provided data before including it in emails:

// Good: Good — sanitize user input
$mail->greeting('Hello ' . esc_html($userName) . '!')
    ->line(esc_html($userMessage));

// Bad: Bad — raw user input in email body
$mail->greeting('Hello ' . $userName . '!')
    ->line($userMessage);

Header Injection Prevention

The Mailable class uses individual method calls for headers, which prevents header injection attacks. Never pass raw user input directly into header values:

// Good: Good — validate email addresses
if (is_email($userEmail)) {
    $mail->replyTo($userEmail);
}

// Bad: Bad — raw user input in headers
$mail->replyTo($_POST['email']);

Attachment Path Validation

Always validate file paths before attaching:

// Good: Good — validate the path exists and is within allowed directory
$allowedDir = wp_upload_dir()['basedir'];
$realPath = realpath($filePath);

if ($realPath && str_starts_with($realPath, $allowedDir)) {
    $mail->attach($realPath);
}

// Bad: Bad — user-controlled path without validation
$mail->attach($_GET['file']);

Template Security

When using PHP view templates, always escape output:

<!-- Good: Good -->
<p>Hello, <?= esc_html($name) ?></p>
<a href="<?= esc_url($link) ?>">Click here</a>

<!-- Bad: Bad -->
<p>Hello, <?= $name ?></p>
<a href="<?= $link ?>">Click here</a>

URL Validation

The built-in action button uses esc_url() to sanitize URLs. When building custom HTML, always escape URLs:

// Good: The action() method auto-escapes URLs
$mail->action('Click', $url); // esc_url() applied internally

// Good: Custom HTML — manually escape
$mail->html('<a href="' . esc_url($url) . '">Link</a>');

Reporting Vulnerabilities

See security.md for vulnerability reporting procedures.

Best Practices Summary

  1. Sanitize all user input with esc_html(), esc_url(), sanitize_email()
  2. Validate email addresses with is_email() before using them
  3. Validate file paths before attaching — check they exist and are within allowed directories
  4. Escape template output — never echo raw user data in templates
  5. Use SMTP — configure a WordPress SMTP plugin for secure transport (TLS/SSL)
  6. Keep updated — update to the latest version for security patches
  7. Limit recipients — validate and limit the number of recipients to prevent abuse