Last updated: August 29, 2026.
PHPMailer can attach files from disk and embed images referenced by cid URLs. Resolve paths on the server instead of accepting arbitrary filenames from the browser.
Attach a PDF and embed a logo
<?php
require __DIR__ . '/vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
// Configure SMTP, sender, and recipient first.
$mail->addAttachment(__DIR__ . '/exports/invoice-1042.pdf', 'invoice-1042.pdf');
$mail->addEmbeddedImage(__DIR__ . '/assets/logo.png', 'company-logo', 'logo.png');
$mail->isHTML(true);
$mail->Subject = 'Invoice 1042';
$mail->Body = '<p><img src="cid:company-logo" alt="Example Company"></p><p>Your invoice is attached.</p>';
$mail->AltBody = 'Your invoice is attached.';
$mail->send();Control attachment cost
- Check file size before attaching.
- Prefer protected links for large or sensitive files.
- Use server-resolved paths only.
- Delete generated temporary files after sending.
Control attachment paths and size
Resolve every attachment from an application-owned directory or generated-file record. Do not let a request parameter become an arbitrary server path, and prefer an authenticated download link for large or sensitive files.
Test a missing file, an oversized file, a non-ASCII filename, and an inline image blocked by the recipient. Delete generated temporary files only after the send job has finished.
- Set a descriptive attachment name.
- Keep the text alternative meaningful without images.
- Check provider message-size limits.
Keep resource limits explicit and make failure cleanup part of the example. Log enough context to diagnose the operation without recording passwords, private message bodies, or uploaded file contents.
Continue with SMTP with PHPMailer, temporary files, and existing PHP email guide.
Practical implementation check
Put the operation in a small function or service with explicit inputs and a clear failure result. Test invalid input, missing extensions, permission failures, and concurrent requests. Production logs should identify the operation and record ID without storing secrets or private content. Clean up partially created files or queue records when any later step fails.
Reference: PHPMailer file upload example.