PHPMailer支持.doc/图片附件,PDF附件无法发送问题求助
Hey there! It looks like you're hitting a snag where PDF attachments won't send through your contact form, even though DOC files and images work perfectly. Let's walk through the most likely issues and how to fix them:
1. First, Capture Detailed Error Messages
Your current code has error reporting commented out, which makes it impossible to pinpoint exactly why PDFs are failing. Start by enabling error logging and PHPMailer's debug output:
error_reporting(E_ALL); ini_set('display_errors', 1);
Also, after attempting to move the uploaded file, add a quick check to verify the PDF isn't corrupted:
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { // Verify the uploaded PDF is intact if (!file_exists($uploadfile) || filesize($uploadfile) === 0) { echo "Uploaded PDF is corrupted or empty"; exit; } // Rest of your PHPMailer code... }
2. Add Proper File Upload Validation
You're missing critical checks for file type and size, which could let through invalid PDFs (like files over 2MB) or files mislabeled as PDFs. Add this validation before handling the upload:
// Allowed file types (uses real file content MIME types, not client-reported values) $allowedMimes = [ 'application/pdf', 'application/msword', 'image/jpeg', 'image/png', 'image/gif' ]; // Allowed file extensions $allowedExts = ['pdf', 'doc', 'jpg', 'jpeg', 'png', 'gif']; // 2MB size limit $maxFileSize = 2 * 1024 * 1024; $uploadedFile = $_FILES['userfile']; $fileExtension = strtolower(pathinfo($uploadedFile['name'], PATHINFO_EXTENSION)); $fileMime = mime_content_type($uploadedFile['tmp_name']); // Check file size if ($uploadedFile['size'] > $maxFileSize) { echo "File exceeds 2MB limit"; exit; } // Double-validate extension and MIME type for security if (!in_array($fileExtension, $allowedExts) || !in_array($fileMime, $allowedMimes)) { echo "Only .doc, .pdf, and image files are allowed"; exit; }
Using mime_content_type ensures you're checking the actual file content, not just the filename or client-reported MIME type (which can be faked).
3. Fix PHPMailer's AddAttachment Call
Your current AddAttachment syntax has a small issue—you shouldn't declare the $encoding variable inside the function call. Also, explicitly specifying the PDF's MIME type helps mail clients and servers recognize the attachment correctly:
// Get the actual MIME type of the uploaded file $attachmentMime = mime_content_type($uploadfile); // Add the attachment with correct encoding and MIME type $mail->AddAttachment($uploadfile, $uploadedFile['name'], 'base64', $attachmentMime);
This ensures PHPMailer handles the PDF's encoding properly, which is often the culprit when PDFs fail to send but other files work.
4. Check Server and Gmail SMTP Settings
- Server Upload Limits: Make sure your PHP config (
php.ini) hasupload_max_filesizeandpost_max_sizeset to at least 2MB (or higher if needed). - Gmail SMTP Requirements: If you're using Gmail, ensure:
- You've enabled "Less secure app access" (if you haven't set up 2FA).
- If you have 2FA enabled, use an App Password instead of your regular account password.
- Add SMTP debugging to see exactly what's happening with the connection:
This will show you if Gmail is rejecting the PDF attachment for any reason.$mail->SMTPDebug = 2; // Outputs detailed SMTP logs (disable in production) $mail->Debugoutput = 'html';
Full Fixed Code Example
<?php error_reporting(E_ALL); ini_set('display_errors', 1); date_default_timezone_set('America/Toronto'); require_once('class.phpmailer.php'); $msg = ''; if (array_key_exists('userfile', $_FILES)) { // Upload Validation $allowedMimes = [ 'application/pdf', 'application/msword', 'image/jpeg', 'image/png', 'image/gif' ]; $allowedExts = ['pdf', 'doc', 'jpg', 'jpeg', 'png', 'gif']; $maxFileSize = 2 * 1024 * 1024; $uploadedFile = $_FILES['userfile']; $fileExtension = strtolower(pathinfo($uploadedFile['name'], PATHINFO_EXTENSION)); $fileMime = mime_content_type($uploadedFile['tmp_name']); if ($uploadedFile['size'] > $maxFileSize) { echo "File exceeds 2MB limit"; exit; } if (!in_array($fileExtension, $allowedExts) || !in_array($fileMime, $allowedMimes)) { echo "Only .doc, .pdf, and image files are allowed"; exit; } // Handle File Upload $uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $uploadedFile['name'])); if (move_uploaded_file($uploadedFile['tmp_name'], $uploadfile)) { if (!file_exists($uploadfile) || filesize($uploadfile) === 0) { echo "Uploaded file is corrupted or empty"; exit; } // Configure PHPMailer $mail = new PHPMailer; $mail->IsSMTP(); $mail->SMTPAuth = true; $mail->SMTPSecure = 'tls'; $mail->Host = "smtp.gmail.com"; $mail->Port = 587; $mail->Username = "exampl@gmail.com"; $mail->Password = 'your_app_password_or_account_password'; // Uncomment for debugging: // $mail->SMTPDebug = 2; // $mail->Debugoutput = 'html'; $name = $_POST['name']; $email = $_POST['email']; $message = "Name: ".($name)."\n"; $message .= "Email: ".($email)."\n"; $message .= "Message: ".$_POST['message']; $mail->addAddress("example@gmail.com"); $mail->SetFrom($email, $name); $mail->Subject = "Message from website"; $mail->Body = $message; // Add Attachment with Correct MIME Type $attachmentMime = mime_content_type($uploadfile); $mail->AddAttachment($uploadfile, $uploadedFile['name'], 'base64', $attachmentMime); if($mail->Send()) { echo "Message sent!"; // Clean up temporary file unlink($uploadfile); } else { echo "Mailer Error: " . $mail->ErrorInfo; unlink($uploadfile); } } else { $msg = 'Failed to move file to ' . $uploadfile; echo $msg; } } ?>
Final Notes
- Always delete temporary files after sending the email (the code above uses
unlink($uploadfile)to do this) to avoid filling up your server's disk space. - Disable error reporting and SMTP debugging when deploying to production to protect sensitive information.
- If you're still having issues, check the PHPMailer error output—it will tell you exactly where the problem is (e.g., attachment encoding, SMTP authentication, etc.).
内容的提问来源于stack exchange,提问作者webdev

