Mengirim Email dengan PHP
Pelajari cara mengirim email menggunakan PHP, dari mail() function hingga PHPMailer untuk kebutuhan yang lebih advanced. Email adalah fitur penting dalam aplikasi web modern.
Menggunakan mail() Function
Fungsi mail() adalah cara paling sederhana untuk mengirim email di PHP, meskipun memiliki keterbatasan dibanding library khusus.
Syntax Dasar mail()
<?php
// Syntax: mail(to, subject, message, headers, parameters)
$to = "recipient@example.com";
$subject = "Test Email";
$message = "Ini adalah email test dari PHP.";
// Header dasar
$headers = "From: sender@example.com\r\n";
$headers .= "Reply-To: sender@example.com\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
if (mail($to, $subject, $message, $headers)) {
echo "Email berhasil dikirim!";
} else {
echo "Gagal mengirim email.";
}
?>
Email dengan Header Lengkap
<?php
function sendBasicEmail($to, $subject, $message, $from) {
// Headers
$headers = "From: $from\r\n";
$headers .= "Reply-To: $from\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
// Additional headers
$headers .= "X-Priority: 1\r\n"; // High priority
$headers .= "Return-Path: $from\r\n";
return mail($to, $subject, $message, $headers);
}
// HTML Email
$htmlMessage = "
<html>
<head>
<title>Test Email</title>
</head>
<body>
<h2>Hello from PHP!</h2>
<p>Ini adalah <strong>email HTML</strong> dari PHP.</p>
<p>Klik <a href='https://example.com'>di sini</a> untuk info lebih lanjut.</p>
</body>
</html>
";
if (sendBasicEmail("user@example.com", "Test HTML Email", $htmlMessage, "noreply@yoursite.com")) {
echo "Email HTML berhasil dikirim!";
}
?>
Email dengan Multiple Recipients
<?php
function sendToMultiple($recipients, $subject, $message, $from) {
$headers = "From: $from\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$success = 0;
$failed = 0;
foreach ($recipients as $email) {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
if (mail($email, $subject, $message, $headers)) {
$success++;
} else {
$failed++;
}
} else {
$failed++;
}
}
return ['success' => $success, 'failed' => $failed];
}
// Multiple recipients
$recipients = [
"user1@example.com",
"user2@example.com",
"user3@example.com"
];
$result = sendToMultiple($recipients, "Newsletter", "Konten newsletter...", "newsletter@yoursite.com");
echo "Berhasil: {$result['success']}, Gagal: {$result['failed']}";
?>
Email dengan Attachment (Basic)
<?php
function sendWithAttachment($to, $subject, $message, $from, $filePath) {
$boundary = md5(time());
$headers = "From: $from\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
$body = "--$boundary\r\n";
$body .= "Content-Type: text/html; charset=UTF-8\r\n";
$body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$body .= $message . "\r\n";
if (file_exists($filePath)) {
$filename = basename($filePath);
$fileContent = chunk_split(base64_encode(file_get_contents($filePath)));
$body .= "--$boundary\r\n";
$body .= "Content-Type: application/octet-stream; name=\"$filename\"\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "Content-Disposition: attachment; filename=\"$filename\"\r\n\r\n";
$body .= $fileContent . "\r\n";
}
$body .= "--$boundary--";
return mail($to, $subject, $body, $headers);
}
// Kirim email dengan attachment
if (sendWithAttachment("user@example.com", "File Attachment", "Email dengan file attachment", "sender@example.com", "document.pdf")) {
echo "Email dengan attachment berhasil dikirim!";
}
?>
PHPMailer Library
PHPMailer adalah library yang powerful dan mudah digunakan untuk mengirim email dengan fitur lengkap seperti SMTP, authentication, dan attachment.
Instalasi PHPMailer
# Via Composer
composer require phpmailer/phpmailer
# Manual download
# Download dari https://github.com/PHPMailer/PHPMailer
# Extract dan include file yang diperlukan
Basic PHPMailer Usage
<?php
require_once 'vendor/autoload.php'; // Jika menggunakan Composer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
function sendEmailPHPMailer($to, $subject, $body, $from) {
$mail = new PHPMailer(true);
try {
// Server settings
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'your-email@gmail.com';
$mail->Password = 'your-app-password';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
// Recipients
$mail->setFrom($from, 'Your Name');
$mail->addAddress($to);
// Content
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->send();
return true;
} catch (Exception $e) {
error_log("Message could not be sent. Mailer Error: {$mail->ErrorInfo}");
return false;
}
}
// Usage
if (sendEmailPHPMailer("recipient@example.com", "Test PHPMailer", "<h1>Hello from PHPMailer!</h1>", "sender@example.com")) {
echo "Email berhasil dikirim dengan PHPMailer!";
}
?>
PHPMailer dengan Konfigurasi Lengkap
<?php
class EmailSender {
private $mail;
private $config;
public function __construct($config) {
$this->config = $config;
$this->mail = new PHPMailer(true);
$this->setupSMTP();
}
private function setupSMTP() {
$this->mail->isSMTP();
$this->mail->Host = $this->config['host'];
$this->mail->SMTPAuth = true;
$this->mail->Username = $this->config['username'];
$this->mail->Password = $this->config['password'];
$this->mail->SMTPSecure = $this->config['encryption'];
$this->mail->Port = $this->config['port'];
// Debug mode (development only)
$this->mail->SMTPDebug = $this->config['debug'] ?? 0;
// Additional settings
$this->mail->CharSet = 'UTF-8';
$this->mail->Encoding = 'base64';
}
public function send($to, $subject, $body, $altBody = '', $attachments = []) {
try {
// Clear previous recipients
$this->mail->clearAllRecipients();
$this->mail->clearAttachments();
// Set from
$this->mail->setFrom($this->config['from_email'], $this->config['from_name']);
// Add recipients
if (is_array($to)) {
foreach ($to as $email) {
$this->mail->addAddress($email);
}
} else {
$this->mail->addAddress($to);
}
// Content
$this->mail->isHTML(true);
$this->mail->Subject = $subject;
$this->mail->Body = $body;
$this->mail->AltBody = $altBody;
// Add attachments
foreach ($attachments as $attachment) {
if (file_exists($attachment['path'])) {
$this->mail->addAttachment(
$attachment['path'],
$attachment['name'] ?? basename($attachment['path'])
);
}
}
$this->mail->send();
return ['success' => true, 'message' => 'Email sent successfully'];
} catch (Exception $e) {
return ['success' => false, 'message' => $this->mail->ErrorInfo];
}
}
}
// Configuration
$emailConfig = [
'host' => 'smtp.gmail.com',
'username' => 'your-email@gmail.com',
'password' => 'your-app-password',
'encryption' => PHPMailer::ENCRYPTION_STARTTLS,
'port' => 587,
'from_email' => 'noreply@yoursite.com',
'from_name' => 'Your Website',
'debug' => 0 // Set to 2 for development
];
// Usage
$emailSender = new EmailSender($emailConfig);
$result = $emailSender->send(
'recipient@example.com',
'Welcome to Our Site',
'<h1>Welcome!</h1><p>Thank you for joining us.</p>',
'Welcome! Thank you for joining us.',
[
['path' => 'welcome-guide.pdf', 'name' => 'Welcome Guide.pdf']
]
);
echo $result['message'];
?>
SMTP Providers Configuration
<?php
// Gmail SMTP
$gmailConfig = [
'host' => 'smtp.gmail.com',
'port' => 587,
'encryption' => PHPMailer::ENCRYPTION_STARTTLS,
'username' => 'your-email@gmail.com',
'password' => 'your-app-password' // Use App Password, not regular password
];
// Outlook/Hotmail SMTP
$outlookConfig = [
'host' => 'smtp-mail.outlook.com',
'port' => 587,
'encryption' => PHPMailer::ENCRYPTION_STARTTLS,
'username' => 'your-email@outlook.com',
'password' => 'your-password'
];
// Yahoo SMTP
$yahooConfig = [
'host' => 'smtp.mail.yahoo.com',
'port' => 587,
'encryption' => PHPMailer::ENCRYPTION_STARTTLS,
'username' => 'your-email@yahoo.com',
'password' => 'your-app-password'
];
// Custom SMTP (hosting provider)
$customConfig = [
'host' => 'mail.yourdomaain.com',
'port' => 587,
'encryption' => PHPMailer::ENCRYPTION_STARTTLS,
'username' => 'noreply@yourdomain.com',
'password' => 'your-email-password'
];
?>
Email Templates
Membuat template email yang menarik dan responsive untuk meningkatkan user experience dan branding.
Basic HTML Template
<?php
function getEmailTemplate($title, $content, $ctaText = '', $ctaLink = '') {
$template = '
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>' . $title . '</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background: #007bff; color: white; padding: 20px; text-align: center; }
.content { padding: 30px 20px; background: #f8f9fa; }
.footer { background: #6c757d; color: white; padding: 15px; text-align: center; font-size: 12px; }
.btn { display: inline-block; padding: 12px 24px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; margin: 20px 0; }
.btn:hover { background: #0056b3; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>' . $title . '</h1>
</div>
<div class="content">
' . $content . '
' . ($ctaText && $ctaLink ? '<div style="text-align: center;"><a href="' . $ctaLink . '" class="btn">' . $ctaText . '</a></div>' : '') . '
</div>
<div class="footer">
<p>© 2024 Your Company. All rights reserved.</p>
<p>Jika Anda tidak ingin menerima email ini, <a href="#" style="color: #ccc;">unsubscribe</a></p>
</div>
</div>
</body>
</html>';
return $template;
}
// Welcome email template
$welcomeContent = '
<h2>Selamat Datang!</h2>
<p>Terima kasih telah bergabung dengan platform kami. Kami sangat senang memiliki Anda sebagai bagian dari komunitas kami.</p>
<p>Berikut adalah beberapa hal yang dapat Anda lakukan:</p>
<ul>
<li>Lengkapi profil Anda</li>
<li>Jelajahi fitur-fitur tersedia</li>
<li>Bergabung dengan komunitas</li>
</ul>
';
$welcomeEmail = getEmailTemplate(
'Selamat Datang di Platform Kami',
$welcomeContent,
'Mulai Sekarang',
'https://yoursite.com/dashboard'
);
?>
Template Engine Class
<?php
class EmailTemplate {
private $templatePath;
private $variables = [];
public function __construct($templatePath = 'email-templates/') {
$this->templatePath = $templatePath;
}
public function setVariable($key, $value) {
$this->variables[$key] = $value;
return $this;
}
public function setVariables($variables) {
$this->variables = array_merge($this->variables, $variables);
return $this;
}
public function render($templateName) {
$templateFile = $this->templatePath . $templateName . '.html';
if (!file_exists($templateFile)) {
throw new Exception("Template file not found: $templateFile");
}
$template = file_get_contents($templateFile);
// Replace variables
foreach ($this->variables as $key => $value) {
$template = str_replace('{{' . $key . '}}', $value, $template);
}
return $template;
}
public static function quickRender($templateName, $variables = []) {
$engine = new self();
return $engine->setVariables($variables)->render($templateName);
}
}
// Template file: email-templates/welcome.html
/*
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<h1>Hello {{username}}!</h1>
<p>{{message}}</p>
<a href="{{cta_link}}">{{cta_text}}</a>
</body>
</html>
*/
// Usage
$emailBody = EmailTemplate::quickRender('welcome', [
'title' => 'Welcome to Our Platform',
'username' => 'John Doe',
'message' => 'Thank you for joining us!',
'cta_link' => 'https://yoursite.com/verify',
'cta_text' => 'Verify Your Account'
]);
?>
Responsive Email Template
<?php
function getResponsiveTemplate($data) {
return '
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>' . $data['title'] . '</title>
<style>
@media only screen and (max-width: 600px) {
.container { width: 100% !important; }
.content { padding: 20px 15px !important; }
.btn { display: block !important; width: 100% !important; }
}
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
.container { max-width: 600px; margin: 0 auto; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 20px; text-align: center; }
.content { padding: 40px 30px; background: #ffffff; }
.card { background: #f8f9fa; padding: 20px; margin: 20px 0; border-radius: 8px; border-left: 4px solid #007bff; }
.btn { display: inline-block; padding: 15px 30px; background: #007bff; color: white; text-decoration: none; border-radius: 6px; font-weight: bold; }
.footer { background: #2c3e50; color: #bdc3c7; padding: 30px 20px; text-align: center; }
.social { margin: 20px 0; }
.social a { display: inline-block; margin: 0 10px; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>' . $data['title'] . '</h1>
<p>' . ($data['subtitle'] ?? '') . '</p>
</div>
<div class="content">
' . $data['content'] . '
' . (isset($data['card']) ? '<div class="card">' . $data['card'] . '</div>' : '') . '
' . (isset($data['cta']) ? '
<div style="text-align: center; margin: 30px 0;">
<a href="' . $data['cta']['link'] . '" class="btn">' . $data['cta']['text'] . '</a>
</div>' : '') . '
</div>
<div class="footer">
<div class="social">
<a href="#">Facebook</a>
<a href="#">Twitter</a>
<a href="#">Instagram</a>
</div>
<p>© 2024 Your Company. All rights reserved.</p>
<p><a href="#" style="color: #95a5a6;">Unsubscribe</a> | <a href="#" style="color: #95a5a6;">Privacy Policy</a></p>
</div>
</div>
</body>
</html>';
}
// Usage
$templateData = [
'title' => 'Password Reset Request',
'subtitle' => 'Secure your account',
'content' => '<p>We received a request to reset your password. Click the button below to create a new password.</p>',
'card' => '<strong>Important:</strong> This link will expire in 24 hours for security reasons.',
'cta' => [
'text' => 'Reset Password',
'link' => 'https://yoursite.com/reset-password?token=abc123'
]
];
$emailHTML = getResponsiveTemplate($templateData);
?>
Advanced Email Features
Fitur-fitur advanced untuk email system yang lebih robust dan professional.
Email Queue System
<?php
class EmailQueue {
private $queuePath;
public function __construct($queuePath = 'email-queue/') {
$this->queuePath = $queuePath;
if (!is_dir($queuePath)) {
mkdir($queuePath, 0755, true);
}
}
public function add($to, $subject, $body, $priority = 5, $sendAt = null) {
$email = [
'id' => uniqid(),
'to' => $to,
'subject' => $subject,
'body' => $body,
'priority' => $priority,
'send_at' => $sendAt ?? time(),
'created_at' => time(),
'attempts' => 0,
'status' => 'pending'
];
$filename = $this->queuePath . $email['id'] . '.json';
file_put_contents($filename, json_encode($email));
return $email['id'];
}
public function process($limit = 10) {
$files = glob($this->queuePath . '*.json');
$processed = 0;
foreach ($files as $file) {
if ($processed >= $limit) break;
$email = json_decode(file_get_contents($file), true);
if ($email['status'] === 'pending' && time() >= $email['send_at']) {
if ($this->sendEmail($email)) {
unlink($file); // Remove from queue
$processed++;
} else {
$email['attempts']++;
if ($email['attempts'] >= 3) {
$email['status'] = 'failed';
}
file_put_contents($file, json_encode($email));
}
}
}
return $processed;
}
private function sendEmail($email) {
// Implement actual email sending logic here
// Return true if successful, false otherwise
// Simulate email sending
return mail($email['to'], $email['subject'], $email['body']);
}
}
// Usage
$queue = new EmailQueue();
// Add emails to queue
$queue->add('user1@example.com', 'Welcome!', 'Welcome message', 1); // High priority
$queue->add('user2@example.com', 'Newsletter', 'Newsletter content', 5); // Normal priority
$queue->add('user3@example.com', 'Reminder', 'Reminder message', 3, time() + 3600); // Send in 1 hour
// Process queue (run this via cron job)
$processed = $queue->process(5);
echo "Processed $processed emails";
?>
Email Tracking
<?php
class EmailTracker {
private $db; // Assume PDO connection
public function __construct($database) {
$this->db = $database;
}
public function createTrackingPixel($emailId) {
$token = hash('sha256', $emailId . time() . rand());
// Save tracking info to database
$stmt = $this->db->prepare("INSERT INTO email_tracking (email_id, token, created_at) VALUES (?, ?, ?)");
$stmt->execute([$emailId, $token, time()]);
return "https://yoursite.com/track-email.php?t=" . $token;
}
public function addTrackingToEmail($emailContent, $emailId) {
$pixelUrl = $this->createTrackingPixel($emailId);
$trackingPixel = '<img src="' . $pixelUrl . '" width="1" height="1" style="display:none;">';
// Add tracking pixel before closing body tag
return str_replace('</body>', $trackingPixel . '</body>', $emailContent);
}
public function trackOpen($token) {
$stmt = $this->db->prepare("SELECT email_id FROM email_tracking WHERE token = ? AND opened_at IS NULL");
$stmt->execute([$token]);
$result = $stmt->fetch();
if ($result) {
// Mark as opened
$stmt = $this->db->prepare("UPDATE email_tracking SET opened_at = ?, ip_address = ?, user_agent = ? WHERE token = ?");
$stmt->execute([
time(),
$_SERVER['REMOTE_ADDR'] ?? '',
$_SERVER['HTTP_USER_AGENT'] ?? '',
$token
]);
return $result['email_id'];
}
return false;
}
public function trackClick($url, $emailId) {
// Create tracked URL
$token = hash('sha256', $url . $emailId . time());
$stmt = $this->db->prepare("INSERT INTO email_clicks (email_id, original_url, token, created_at) VALUES (?, ?, ?, ?)");
$stmt->execute([$emailId, $url, $token, time()]);
return "https://yoursite.com/track-click.php?t=" . $token;
}
}
// track-email.php
/*
<?php
$token = $_GET['t'] ?? '';
$tracker = new EmailTracker($pdo);
$emailId = $tracker->trackOpen($token);
// Return 1x1 transparent pixel
header('Content-Type: image/gif');
echo base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
?>
*/
?>
Email Validation dan Sanitization
<?php
class EmailValidator {
public static function validate($email) {
// Basic validation
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return ['valid' => false, 'error' => 'Invalid email format'];
}
// Check for disposable email providers
$disposableProviders = ['10minutemail.com', 'tempmail.org', 'guerrillamail.com'];
$domain = substr(strrchr($email, "@"), 1);
if (in_array($domain, $disposableProviders)) {
return ['valid' => false, 'error' => 'Disposable email not allowed'];
}
// DNS check
if (!checkdnsrr($domain, 'MX')) {
return ['valid' => false, 'error' => 'Invalid email domain'];
}
return ['valid' => true];
}
public static function sanitize($input) {
// Remove dangerous characters
$input = strip_tags($input);
$input = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
// Remove potential injection attempts
$dangerous = ['script', 'javascript:', 'vbscript:', 'onload', 'onerror'];
foreach ($dangerous as $danger) {
$input = str_ireplace($danger, '', $input);
}
return $input;
}
public static function isBlacklisted($email) {
// Check against blacklist (implement your logic)
$blacklist = ['spam@example.com', 'test@blacklist.com'];
return in_array(strtolower($email), $blacklist);
}
}
// Rate limiting class
class EmailRateLimiter {
private $redis; // Redis connection for rate limiting
public function __construct($redis) {
$this->redis = $redis;
}
public function canSend($identifier, $limit = 10, $window = 3600) {
$key = "email_limit:" . $identifier;
$current = $this->redis->get($key) ?: 0;
if ($current >= $limit) {
return false;
}
$this->redis->incr($key);
$this->redis->expire($key, $window);
return true;
}
}
// Usage
$validation = EmailValidator::validate('user@example.com');
if (!$validation['valid']) {
echo "Error: " . $validation['error'];
exit;
}
// Rate limiting
$rateLimiter = new EmailRateLimiter($redis);
if (!$rateLimiter->canSend($_SERVER['REMOTE_ADDR'])) {
echo "Rate limit exceeded. Please try again later.";
exit;
}
?>
Path Belajar PHP
Memahami apa itu PHP dan cara instalasinya
Mempelajari cara menulis kode PHP yang benar
Memahami alur program dan pengorganisasian kode
Membuat aplikasi web interaktif
Mengelola data dan keamanan aplikasi
Topik lanjutan untuk pengembangan professional
Tutorial Saat Ini
Level: Menengah
Memerlukan pemahaman dasar PHP