Complete email configuration and management guide for WordPress
Email Management
Configure and manage email functionality in WordPress. Learn to set up SMTP, handle email deliverability, and implement advanced email features for your website.
Email Configuration Basics
WordPress Default Email Settings
Default Configuration
// WordPress uses PHP mail() by default
// Server: localhost
// Port: 25 (or server's SMTP port)
// Authentication: None
// Encryption: NoneBasic Email Settings
// Configure WordPress email settings
update_option('admin_email', 'admin@yourdomain.com');
update_option('blogname', 'Your Site Name');
update_option('blogdescription', 'Your site description');
// Set email charset
define('WP_MAIL_CHARSET', 'UTF-8');SMTP Configuration
Manual SMTP Setup
// Configure SMTP in wp-config.php
define('SMTP_HOST', 'smtp.yourdomain.com');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls'); // tls or ssl
define('SMTP_AUTH', true);
define('SMTP_USER', 'your-email@yourdomain.com');
define('SMTP_PASS', 'your-email-password');
define('SMTP_FROM', 'noreply@yourdomain.com');
define('SMTP_FROM_NAME', 'Your Site Name');Gmail SMTP Configuration
// Gmail SMTP settings
define('SMTP_HOST', 'smtp.gmail.com');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls');
define('SMTP_AUTH', true);
define('SMTP_USER', 'your-gmail@gmail.com');
define('SMTP_PASS', 'your-app-password'); // Use app password, not regular passwordOutlook/Hotmail SMTP
// Outlook SMTP settings
define('SMTP_HOST', 'smtp-mail.outlook.com');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls');
define('SMTP_AUTH', true);
define('SMTP_USER', 'your-email@outlook.com');
define('SMTP_PASS', 'your-password');Email Delivery Services
Popular Email Services
SendGrid Configuration
// SendGrid SMTP settings
define('SMTP_HOST', 'smtp.sendgrid.net');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls');
define('SMTP_AUTH', true);
define('SMTP_USER', 'apikey'); // SendGrid uses 'apikey' as username
define('SMTP_PASS', 'your-sendgrid-api-key');Mailgun Setup
// Mailgun SMTP settings
define('SMTP_HOST', 'smtp.mailgun.org');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls');
define('SMTP_AUTH', true);
define('SMTP_USER', 'your-mailgun-smtp-username');
define('SMTP_PASS', 'your-mailgun-smtp-password');Amazon SES
// Amazon SES SMTP settings
define('SMTP_HOST', 'email-smtp.us-east-1.amazonaws.com'); // Change region as needed
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls');
define('SMTP_AUTH', true);
define('SMTP_USER', 'your-ses-smtp-username');
define('SMTP_PASS', 'your-ses-smtp-password');API-Based Email Services
SendGrid API Integration
// SendGrid API configuration
define('SENDGRID_API_KEY', 'your-sendgrid-api-key');
define('SENDGRID_FROM_EMAIL', 'noreply@yourdomain.com');
define('SENDGRID_FROM_NAME', 'Your Site Name');
// SendGrid API function
function send_email_via_sendgrid($to, $subject, $message, $headers = array()) {
$email = new \SendGrid\Mail\Mail();
$email->setFrom(SENDGRID_FROM_EMAIL, SENDGRID_FROM_NAME);
$email->setSubject($subject);
$email->addTo($to);
$email->addContent("text/html", $message);
$sendgrid = new \SendGrid(SENDGRID_API_KEY);
try {
$response = $sendgrid->send($email);
return array('success' => true, 'response' => $response);
} catch (Exception $e) {
return array('success' => false, 'error' => $e->getMessage());
}
}Email Testing and Debugging
Email Testing Tools
WordPress Email Testing
// Test email functionality
function test_wordpress_email() {
$to = 'test@yourdomain.com';
$subject = 'WordPress Email Test';
$message = 'This is a test email from WordPress.';
$headers = array('Content-Type: text/html; charset=UTF-8');
$result = wp_mail($to, $subject, $message, $headers);
if ($result) {
error_log('Email test successful');
return 'Email sent successfully';
} else {
error_log('Email test failed');
return 'Email sending failed';
}
}Email Logging
// Log all outgoing emails
function log_outgoing_email($mail) {
$log_entry = array(
'timestamp' => current_time('mysql'),
'to' => is_array($mail['to']) ? implode(', ', $mail['to']) : $mail['to'],
'subject' => $mail['subject'],
'headers' => $mail['headers'],
'message_length' => strlen($mail['message'])
);
// Log to file
error_log('EMAIL LOG: ' . json_encode($log_entry));
// Or store in database
global $wpdb;
$wpdb->insert('wp_email_logs', $log_entry);
return $mail;
}
add_filter('wp_mail', 'log_outgoing_email');Debug Email Issues
Common Email Problems
// Enable email debugging
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
// Test SMTP connection
function test_smtp_connection() {
$smtp_host = defined('SMTP_HOST') ? SMTP_HOST : 'localhost';
$smtp_port = defined('SMTP_PORT') ? SMTP_PORT : 25;
$connection = @fsockopen($smtp_host, $smtp_port, $errno, $errstr, 10);
if ($connection) {
fclose($connection);
return "SMTP connection successful to {$smtp_host}:{$smtp_port}";
} else {
return "SMTP connection failed: {$errstr} ({$errno})";
}
}Email Template Management
Custom Email Templates
HTML Email Template
function create_html_email_template($subject, $content, $header_image = '') {
$site_name = get_bloginfo('name');
$site_url = get_bloginfo('url');
$template = '
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>' . esc_html($subject) . '</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f4f4f4; }
.email-container { max-width: 600px; margin: 0 auto; background-color: #ffffff; }
.email-header { background-color: #007cba; color: white; padding: 20px; text-align: center; }
.email-content { padding: 30px; line-height: 1.6; }
.email-footer { background-color: #f4f4f4; padding: 20px; text-align: center; font-size: 12px; color: #666; }
.button { display: inline-block; background-color: #007cba; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; }
</style>
</head>
<body>
<div class="email-container">
' . ($header_image ? '<div class="email-header"><img src="' . esc_url($header_image) . '" alt="' . esc_attr($site_name) . '" style="max-width: 200px;"></div>' : '<div class="email-header"><h1>' . esc_html($site_name) . '</h1></div>') . '
<div class="email-content">
' . $content . '
</div>
<div class="email-footer">
<p>Sent from ' . esc_html($site_name) . '</p>
<p><a href="' . esc_url($site_url) . '">' . esc_url($site_url) . '</a></p>
</div>
</div>
</body>
</html>';
return $template;
}Plain Text Email Template
function create_plain_text_email_template($subject, $content) {
$site_name = get_bloginfo('name');
$site_url = get_bloginfo('url');
$template = $subject . "\n";
$template .= str_repeat('=', strlen($subject)) . "\n\n";
$template .= $content . "\n\n";
$template .= "---\n";
$template .= "Sent from {$site_name}\n";
$template .= "{$site_url}\n";
return $template;
}Email Header and Footer Management
Custom Email Headers
function add_custom_email_headers($headers) {
// Add custom headers
$headers[] = 'X-Mailer: WordPress/' . get_bloginfo('version');
$headers[] = 'X-Site-Name: ' . get_bloginfo('name');
$headers[] = 'X-Site-URL: ' . get_bloginfo('url');
$headers[] = 'List-Unsubscribe: <' . get_bloginfo('admin_email') . '>';
// Add anti-spam headers
$headers[] = 'X-Anti-Abuse: This is a legitimate email from ' . get_bloginfo('name');
return $headers;
}
add_filter('wp_mail', function($args) {
$args['headers'] = add_custom_email_headers($args['headers'] ?? array());
return $args;
});Email Queue and Batch Processing
Email Queue System
Basic Email Queue
// Create email queue table on plugin activation
function create_email_queue_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'email_queue';
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
to_email varchar(255) NOT NULL,
subject text NOT NULL,
message longtext NOT NULL,
headers text,
status enum('queued','sent','failed') DEFAULT 'queued',
priority tinyint(1) DEFAULT 5,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
sent_at datetime NULL,
error_message text,
PRIMARY KEY (id),
KEY status (status),
KEY priority (priority)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_email_queue_table');Queue Email Function
function queue_email($to, $subject, $message, $headers = array(), $priority = 5) {
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'email_queue',
array(
'to_email' => $to,
'subject' => $subject,
'message' => $message,
'headers' => serialize($headers),
'priority' => $priority,
'status' => 'queued'
)
);
return $wpdb->insert_id;
}Process Email Queue
function process_email_queue() {
global $wpdb;
$table_name = $wpdb->prefix . 'email_queue';
// Get emails to process (limit to prevent timeout)
$emails = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name
WHERE status = 'queued'
ORDER BY priority DESC, created_at ASC
LIMIT %d",
get_option('email_queue_batch_size', 10)
));
foreach ($emails as $email) {
$headers = unserialize($email->headers);
$result = wp_mail($email->to_email, $email->subject, $email->message, $headers);
if ($result) {
// Mark as sent
$wpdb->update(
$table_name,
array(
'status' => 'sent',
'sent_at' => current_time('mysql')
),
array('id' => $email->id)
);
} else {
// Mark as failed
$wpdb->update(
$table_name,
array(
'status' => 'failed',
'error_message' => 'wp_mail() returned false'
),
array('id' => $email->id)
);
}
}
}
// Schedule queue processing
if (!wp_next_scheduled('process_email_queue')) {
wp_schedule_event(time(), 'every_minute', 'process_email_queue');
}
add_action('process_email_queue', 'process_email_queue');Email Analytics and Monitoring
Email Tracking
Open and Click Tracking
function add_email_tracking($message, $email_id) {
$tracking_pixel = '<img src="' . get_site_url() . '/email-tracking/open.php?id=' . $email_id . '" width="1" height="1" style="display:none;">';
$message .= $tracking_pixel;
// Convert links to tracking links
$message = preg_replace_callback(
'/href=["\']([^"\']+)["\']/i',
function($matches) use ($email_id) {
$original_url = $matches[1];
$tracking_url = get_site_url() . '/email-tracking/click.php?id=' . $email_id . '&url=' . urlencode($original_url);
return 'href="' . $tracking_url . '"';
},
$message
);
return $message;
}
// Create tracking endpoints
function handle_email_open_tracking() {
$email_id = intval($_GET['id']);
// Log email open
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'email_tracking',
array(
'email_id' => $email_id,
'event_type' => 'open',
'ip_address' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'timestamp' => current_time('mysql')
)
);
// Return 1x1 transparent pixel
header('Content-Type: image/gif');
echo base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
exit;
}
function handle_email_click_tracking() {
$email_id = intval($_GET['id']);
$original_url = sanitize_text_field($_GET['url']);
// Log email click
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'email_tracking',
array(
'email_id' => $email_id,
'event_type' => 'click',
'ip_address' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'clicked_url' => $original_url,
'timestamp' => current_time('mysql')
)
);
// Redirect to original URL
wp_redirect($original_url);
exit;
}Email Performance Metrics
Delivery Statistics
function get_email_delivery_stats($date_range = 30) {
global $wpdb;
$start_date = date('Y-m-d H:i:s', strtotime("-{$date_range} days"));
$stats = $wpdb->get_row($wpdb->prepare(
"SELECT
COUNT(*) as total_sent,
SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) as delivered,
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed,
AVG(TIMESTAMPDIFF(MINUTE, created_at, sent_at)) as avg_delivery_time
FROM {$wpdb->prefix}email_queue
WHERE created_at >= %s",
$start_date
));
if ($stats->total_sent > 0) {
$stats->delivery_rate = ($stats->delivered / $stats->total_sent) * 100;
} else {
$stats->delivery_rate = 0;
}
return $stats;
}Security and Compliance
Email Security Best Practices
SPF, DKIM, and DMARC Setup
// SPF Record Example
// Add to DNS: v=spf1 include:_spf.yourdomain.com include:_spf.google.com ~all
// DKIM Setup (example for cPanel)
function setup_dkim_keys() {
$private_key_path = '/home/user/.dkim/private.key';
$public_key_path = '/home/user/.dkim/public.key';
// Generate DKIM keys
$key_resource = openssl_pkey_new(array(
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA
));
// Export keys
openssl_pkey_export($key_resource, $private_key);
$public_key_details = openssl_pkey_get_details($key_resource);
file_put_contents($private_key_path, $private_key);
file_put_contents($public_key_path, $public_key_details['key']);
// Set permissions
chmod($private_key_path, 0600);
chmod($public_key_path, 0644);
return array(
'private_key' => $private_key,
'public_key' => $public_key_details['key']
);
}GDPR Compliance
Email Consent Management
function manage_email_consent($user_id, $consent_type, $consent_given = true) {
$consent_key = 'email_consent_' . $consent_type;
update_user_meta($user_id, $consent_key, $consent_given ? 'yes' : 'no');
update_user_meta($user_id, $consent_key . '_date', current_time('mysql'));
// Log consent change
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'email_consent_log',
array(
'user_id' => $user_id,
'consent_type' => $consent_type,
'consent_value' => $consent_given ? 'granted' : 'revoked',
'ip_address' => $_SERVER['REMOTE_ADDR'],
'timestamp' => current_time('mysql')
)
);
}
function check_email_consent($user_id, $consent_type) {
$consent = get_user_meta($user_id, 'email_consent_' . $consent_type, true);
return $consent === 'yes';
}Advanced Email Features
Email Templates System
Template Management
class EmailTemplateManager {
private $templates = array();
public function __construct() {
$this->load_default_templates();
}
private function load_default_templates() {
$this->templates = array(
'welcome' => array(
'subject' => 'Welcome to {site_name}!',
'body' => 'Welcome {user_name} to {site_name}...',
'variables' => array('site_name', 'user_name', 'login_url')
),
'password_reset' => array(
'subject' => 'Password Reset - {site_name}',
'body' => 'Reset your password...',
'variables' => array('site_name', 'reset_url', 'user_name')
),
'order_confirmation' => array(
'subject' => 'Order Confirmation - {order_number}',
'body' => 'Thank you for your order...',
'variables' => array('order_number', 'customer_name', 'order_total')
)
);
}
public function get_template($template_name) {
return isset($this->templates[$template_name]) ? $this->templates[$template_name] : null;
}
public function render_template($template_name, $variables = array()) {
$template = $this->get_template($template_name);
if (!$template) {
return false;
}
$subject = $template['subject'];
$body = $template['body'];
// Replace variables
foreach ($variables as $key => $value) {
$subject = str_replace('{' . $key . '}', $value, $subject);
$body = str_replace('{' . $key . '}', $value, $body);
}
return array(
'subject' => $subject,
'body' => $body
);
}
}Automated Email Campaigns
Newsletter System
class EmailNewsletterSystem {
private $subscribers_table;
public function __construct() {
global $wpdb;
$this->subscribers_table = $wpdb->prefix . 'email_subscribers';
}
public function subscribe_user($email, $name = '') {
global $wpdb;
$wpdb->insert(
$this->subscribers_table,
array(
'email' => $email,
'name' => $name,
'status' => 'active',
'subscribed_at' => current_time('mysql')
)
);
return $wpdb->insert_id;
}
public function send_newsletter($subject, $content, $subscriber_ids = array()) {
global $wpdb;
if (empty($subscriber_ids)) {
// Get all active subscribers
$subscriber_ids = $wpdb->get_col($wpdb->prepare(
"SELECT id FROM {$this->subscribers_table} WHERE status = %s",
'active'
));
}
$sent_count = 0;
$failed_count = 0;
foreach ($subscriber_ids as $subscriber_id) {
$subscriber = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$this->subscribers_table} WHERE id = %d",
$subscriber_id
));
if ($subscriber) {
$personalized_content = $this->personalize_content($content, $subscriber);
$result = wp_mail($subscriber->email, $subject, $personalized_content);
if ($result) {
$sent_count++;
} else {
$failed_count++;
// Log failure
$this->log_send_failure($subscriber_id, 'wp_mail_failed');
}
}
}
return array(
'sent' => $sent_count,
'failed' => $failed_count
);
}
private function personalize_content($content, $subscriber) {
$replacements = array(
'{name}' => $subscriber->name ?: 'Valued Subscriber',
'{email}' => $subscriber->email,
'{unsubscribe_url}' => $this->get_unsubscribe_url($subscriber->id)
);
return str_replace(array_keys($replacements), array_values($replacements), $content);
}
}Monitoring and Maintenance
Email Health Monitoring
Delivery Rate Tracking
function monitor_email_delivery_health() {
$stats = get_email_delivery_stats(7); // Last 7 days
$health_status = array(
'delivery_rate' => $stats->delivery_rate,
'total_sent' => $stats->total_sent,
'status' => 'healthy'
);
// Check delivery rate
if ($stats->delivery_rate < 90) {
$health_status['status'] = 'warning';
$health_status['issues'][] = 'Low delivery rate: ' . round($stats->delivery_rate, 2) . '%';
}
if ($stats->delivery_rate < 80) {
$health_status['status'] = 'critical';
$health_status['issues'][] = 'Critical: Delivery rate below 80%';
}
// Check for high failure rate
if ($stats->total_sent > 0) {
$failure_rate = ($stats->failed / $stats->total_sent) * 100;
if ($failure_rate > 10) {
$health_status['issues'][] = 'High failure rate: ' . round($failure_rate, 2) . '%';
}
}
return $health_status;
}Email Queue Maintenance
Cleanup Old Emails
function cleanup_email_queue() {
global $wpdb;
$retention_days = get_option('email_queue_retention_days', 30);
$cutoff_date = date('Y-m-d H:i:s', strtotime("-{$retention_days} days"));
// Delete old sent emails
$deleted_sent = $wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->prefix}email_queue
WHERE status = 'sent' AND created_at < %s",
$cutoff_date
));
// Keep failed emails longer (90 days)
$failed_cutoff = date('Y-m-d H:i:s', strtotime("-90 days"));
$deleted_failed = $wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->prefix}email_queue
WHERE status = 'failed' AND created_at < %s",
$failed_cutoff
));
return array(
'deleted_sent' => $deleted_sent,
'deleted_failed' => $deleted_failed
);
}
// Schedule cleanup
if (!wp_next_scheduled('cleanup_email_queue')) {
wp_schedule_event(time(), 'daily', 'cleanup_email_queue');
}
add_action('cleanup_email_queue', 'cleanup_email_queue');Best Practices
Email Configuration Best Practices
- Use SMTP: Always use SMTP instead of PHP mail()
- Authentication: Use proper authentication and encryption
- DKIM/SPF: Set up proper email authentication
- Monitoring: Monitor delivery rates and bounce rates
- Testing: Test emails before sending to users
Performance Best Practices
- Queue System: Use email queue for bulk sending
- Rate Limiting: Implement sending rate limits
- Batch Processing: Send emails in manageable batches
- Caching: Cache email templates and configurations
- Optimization: Optimize email content and attachments
Security Best Practices
- Encryption: Use TLS/SSL for email transmission
- Authentication: Implement proper sender authentication
- Validation: Validate email addresses and content
- Monitoring: Monitor for spam and abuse
- Compliance: Follow email regulations (CAN-SPAM, GDPR)
Complete WordPress email management and optimization guide.