Sending emails in PHP becomes reliable and simple when you use PHPMailer, the most popular email library for PHP. PHP's built-in mail() function often lands in spam, cannot use SMTP properly, and makes attachments painful. PHPMailer fixes all of that: it sends through a real SMTP server like Gmail, supports HTML emails and attachments, and reports clear errors when something goes wrong. In this guide, you will install PHPMailer with Composer, create a Gmail App Password, send your first email, add attachments, and wire it into a contact form — with full working code at every step.
What Is PHPMailer and Why Not Use mail()?
PHPMailer is a free, open-source library that has long been the standard way to send email from PHP. Where mail() simply hands your message to the server and hopes for the best, PHPMailer talks directly to an SMTP server with proper authentication and encryption — exactly how real email clients send mail. That means far fewer messages lost to spam filters, HTML formatting, file attachments, CC and BCC recipients, and error messages that actually tell you what went wrong. For any real project — a contact form, a registration system, password reset emails — PHPMailer is always the better choice.
What You Need Before You Start
You need a PHP project running on a local server like XAMPP or on real hosting, Composer installed on your computer (download it free from getcomposer.org), and a Gmail account to send from. Without Composer, you can download PHPMailer manually from GitHub and include the files yourself — but Composer is easier, and it is the method this guide follows.
Step 1: Install PHPMailer Using Composer
Open your terminal or command prompt, go to your project folder, and run this command:
composer require phpmailer/phpmailer
Composer downloads PHPMailer into a vendor folder inside your project and creates a composer.json file automatically. Every PHP file that sends email then starts with one line — require 'vendor/autoload.php'; — which loads the library for you.
Step 2: Create a Gmail App Password
Google no longer allows your regular Gmail password for SMTP connections, so you must generate a special App Password. Go to your Google Account, open Security, and first enable 2-Step Verification if it is not already on. Then open Security → App Passwords, select Mail as the app and your device, and click Generate. Google gives you a 16-character password — copy it, because you will paste it into your PHP code in the next step. Treat this password like any other secret: never share it, never post it publicly, and never commit it to GitHub. Just as you would hash user passwords in PHP instead of storing them plainly, keep credentials out of your code files wherever possible.
Step 3: Send Your First Email — Full Code
Create a file named send_email.php in your project and paste in this code. Replace the placeholders with your Gmail address and the App Password you just generated.
<?php
// Load Composer autoloader
require 'vendor/autoload.php';
// Import PHPMailer classes
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// Create a new PHPMailer instance
$mail = new PHPMailer(true);
try {
// ---------- SERVER SETTINGS ----------
$mail->isSMTP(); // Use SMTP
$mail->Host = 'smtp.gmail.com'; // Gmail SMTP server
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'your_email@gmail.com'; // Your Gmail address
$mail->Password = 'your_app_password_here'; // Your Gmail App Password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // TLS encryption
$mail->Port = 587; // TCP port for TLS
// ---------- SENDER AND RECIPIENT ----------
$mail->setFrom('your_email@gmail.com', 'Your Name');
$mail->addAddress('recipient@example.com', 'Recipient Name');
// ---------- EMAIL CONTENT ----------
$mail->isHTML(true); // Email format is HTML
$mail->Subject = 'Hello from PHPMailer!';
$mail->Body = '<h1>Hello!</h1><p>This email was sent using <b>PHPMailer</b> and Gmail SMTP.</p>';
$mail->AltBody = 'Hello! This email was sent using PHPMailer and Gmail SMTP.';
// Send the email
$mail->send();
echo 'Email has been sent successfully!';
} catch (Exception $e) {
echo "Email could not be sent. Error: {$mail->ErrorInfo}";
}
Run the file in your browser. If everything is correct, you will see the success message and the email will appear in the recipient's inbox within a few seconds.
Understanding the Important Settings
A few lines deserve a closer look. isSMTP() tells PHPMailer to use SMTP instead of the unreliable mail() function. SMTPSecure sets the encryption: use ENCRYPTION_STARTTLS with port 587 (recommended), or ENCRYPTION_SMTPS with port 465. isHTML(true) allows HTML in the body, and AltBody provides the plain-text version for clients that do not display HTML. The whole send is wrapped in try/catch, so if anything fails — a wrong password, a wrong server — the error is shown to you instead of crashing the page.
Step 4: Add Attachments and More Recipients
Attaching a file takes a single line, placed after addAddress() and before send(). You can attach as many files as you need:
$mail->addAttachment('/path/to/your/file.pdf', 'Invoice.pdf');
$mail->addAttachment('/path/to/image.jpg', 'Photo.jpg');
Sending to more people is just as easy. Call addAddress() once per recipient, and use addCC() for carbon copies (visible to everyone) and addBCC() for blind copies (hidden from other recipients):
$mail->addAddress('person1@example.com', 'Person One');
$mail->addAddress('person2@example.com', 'Person Two');
$mail->addCC('manager@example.com', 'Manager');
$mail->addBCC('archive@example.com', 'Archive');
Step 5: Send Email From a Contact Form
The most common real use is a contact form: a visitor fills in their details, and your website emails the message to you. The PHP below reads the form safely — trimming and validating the input — then sends it with addReplyTo() set to the visitor, so pressing Reply in your inbox answers them directly:
<?php
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = htmlspecialchars(trim($_POST['name']));
$email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL);
$message = htmlspecialchars(trim($_POST['message']));
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
die('Invalid email address.');
}
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'your_email@gmail.com';
$mail->Password = 'your_app_password_here';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('your_email@gmail.com', 'Website Contact Form');
$mail->addAddress('your_email@gmail.com'); // Send to yourself
$mail->addReplyTo($email, $name); // Reply goes to the visitor
$mail->isHTML(true);
$mail->Subject = "New Contact Form Message from $name";
$mail->Body = "<h2>New Contact Form Submission</h2>
<p><strong>Name:</strong> $name</p>
<p><strong>Email:</strong> $email</p>
<p><strong>Message:</strong><br>$message</p>";
$mail->send();
echo 'Thank you! Your message has been sent.';
} catch (Exception $e) {
echo "Sorry, the message could not be sent. Error: {$mail->ErrorInfo}";
}
}
The matching HTML form is a simple form with three fields named name, email and message, submitted with method="POST". The same pattern works for registration systems — for example, sending a welcome email from a student registration and login system the moment a new account is created.
Common Errors and How to Fix Them
- SMTP connect() failed — usually a wrong host or port. Confirm you are using smtp.gmail.com with port 587 and STARTTLS, and that your server allows outgoing connections on that port.
- Username and Password not accepted — you are using your regular Gmail password. You must use a 16-character App Password from Step 2, and 2-Step Verification must be enabled first.
- Could not instantiate mail function — PHPMailer is not loaded correctly. Check that vendor/autoload.php is required at the top of the file and that the vendor folder exists.
- Emails going to spam — common with free SMTP. Use a setFrom() address that matches your account, and for production move to a custom domain email or a service such as Mailgun, SendGrid or Amazon SES.
PHPMailer vs PHP mail(): Quick Comparison
| Feature | PHP mail() | PHPMailer |
|---|---|---|
| SMTP support | No | Yes |
| HTML emails | Limited | Full support |
| Attachments | Difficult | Easy, one line |
| Spam problems | Very common | Much less |
| Error handling | Poor | Excellent |
| Ease of use | Simple | Easy with setup |
Want to go one step further? Read our guide on How to Handle HTML Forms in PHP: GET vs POST and Simple Validation next. It explains the topic in the same simple way.
Frequently Asked Questions
Is PHPMailer free to use?
Yes. PHPMailer is free and open source for personal and commercial projects. Install it with Composer or download it from GitHub.
Why does Gmail reject my password in PHPMailer?
Because Google blocks your normal account password for SMTP. Enable 2-Step Verification, generate an App Password, and use that 16-character password in your code instead.
Can PHPMailer send emails without Gmail?
Yes. PHPMailer works with any SMTP server — your hosting provider's mail server, Outlook, or SendGrid, Mailgun and Amazon SES. Only the Host, Username, Password and Port values change.
How do I stop PHPMailer emails going to spam?
Send from an address that matches your authenticated account, avoid spammy subject lines, include a plain-text AltBody, and for serious projects use a custom domain with SPF and DKIM records set up, or a transactional email service.
Can I send an email to many people at once?
Yes. Call addAddress() for each recipient, or use addCC() and addBCC(). For large lists, use a dedicated email service instead — Gmail has daily sending limits.
Conclusion
Sending emails in PHP with PHPMailer is a one-time setup: install it with Composer, create a Gmail App Password, and the same few lines of code send plain emails, HTML emails, attachments and contact form messages reliably. Start with the basic example, then build it into your own forms and registration systems with confidence.
Leave a Comment