Files
wp-digital-download/includes/class-wpdd-email.php
jknapp 4731637f33
Some checks failed
Create Release / build (push) Failing after 3s
Major improvements: Fix download limits, enhance license display, fix software filenames
🔧 Bug Fixes:
- Fixed download limits defaulting to 5 instead of 0 for unlimited downloads
- Fixed software license filename sanitization (spaces→dashes, dots→underscores, proper .zip extension)
- Software downloads now show as "Test-Plugin-v2-2-0.zip" instead of "Test Plugin v2.2.0"

 UI/UX Enhancements:
- Redesigned license key display to span full table width with FontAwesome copy icons
- Added responsive CSS styling for license key rows
- Integrated FontAwesome CDN for modern copy icons

🏗️ Architecture Improvements:
- Added comprehensive filename sanitization in both download handler and API paths
- Enhanced software license product handling for local package files
- Improved error handling and logging throughout download processes

📦 Infrastructure:
- Added Gitea workflows for automated releases on push to main
- Created comprehensive .gitignore excluding test files and browser automation
- Updated documentation with all recent improvements and technical insights

🔍 Technical Details:
- Software license products served from wp-content/uploads/wpdd-packages/
- Download flow: token → process_download_by_token() → process_download() → deliver_file()
- Dual path coverage for both API downloads and regular file delivery
- Version placeholder system for automated deployment

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-09 19:16:57 -07:00

211 lines
7.2 KiB
PHP

<?php
/**
* Email handler class for WP Digital Download
* Handles email sending with logging and SMTP configuration
*/
if (!defined('ABSPATH')) {
exit;
}
class WPDD_Email {
public static function init() {
// Configure SMTP if enabled
if (get_option('wpdd_smtp_enabled')) {
add_action('phpmailer_init', array(__CLASS__, 'configure_smtp'));
}
}
/**
* Send email with logging
*
* @param string $to Email address to send to
* @param string $subject Email subject
* @param string $message Email message (HTML)
* @param string $email_type Type of email for logging (e.g., 'order_confirmation', 'download_link', etc.)
* @param array $headers Optional email headers
* @return bool Whether email was sent successfully
*/
public static function send($to, $subject, $message, $email_type = 'general', $headers = array()) {
global $wpdb;
// Set default headers if not provided
if (empty($headers)) {
$from_email = get_option('wpdd_from_email', get_option('admin_email'));
$from_name = get_option('wpdd_from_name', get_bloginfo('name'));
$headers = array(
'From: ' . $from_name . ' <' . $from_email . '>',
'Content-Type: text/html; charset=UTF-8'
);
}
// Send the email
$sent = wp_mail($to, $subject, $message, $headers);
// Log the email
$table_name = $wpdb->prefix . 'wpdd_email_logs';
// Create table if it doesn't exist
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
self::create_email_logs_table();
}
// Get error message if failed
$error_message = '';
if (!$sent) {
global $phpmailer;
if (isset($phpmailer) && is_object($phpmailer) && !empty($phpmailer->ErrorInfo)) {
$error_message = $phpmailer->ErrorInfo;
}
}
// Insert log entry
$wpdb->insert(
$table_name,
array(
'to_email' => $to,
'subject' => $subject,
'message' => $message,
'status' => $sent ? 'sent' : 'failed',
'email_type' => $email_type,
'error_message' => $error_message,
'sent_at' => current_time('mysql')
),
array('%s', '%s', '%s', '%s', '%s', '%s', '%s')
);
return $sent;
}
/**
* Configure SMTP settings for PHPMailer
*/
public static function configure_smtp($phpmailer) {
$phpmailer->isSMTP();
$phpmailer->Host = get_option('wpdd_smtp_host');
$phpmailer->Port = get_option('wpdd_smtp_port', 587);
$phpmailer->SMTPAuth = true;
$phpmailer->Username = get_option('wpdd_smtp_username');
$phpmailer->Password = get_option('wpdd_smtp_password');
$phpmailer->SMTPSecure = get_option('wpdd_smtp_encryption', 'tls');
$phpmailer->From = get_option('wpdd_from_email', get_option('admin_email'));
$phpmailer->FromName = get_option('wpdd_from_name', get_bloginfo('name'));
// Enable debugging for failed sends
if (defined('WP_DEBUG') && WP_DEBUG) {
$phpmailer->SMTPDebug = 2;
$phpmailer->Debugoutput = 'error_log';
}
}
/**
* Create email logs table if it doesn't exist
*/
private static function create_email_logs_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'wpdd_email_logs';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
to_email varchar(100) NOT NULL,
subject varchar(255) NOT NULL,
message longtext NOT NULL,
status varchar(20) NOT NULL DEFAULT 'sent',
email_type varchar(50) DEFAULT 'general',
error_message text DEFAULT NULL,
sent_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY to_email (to_email),
KEY status (status),
KEY email_type (email_type),
KEY sent_at (sent_at)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
/**
* Send order confirmation email
*/
public static function send_order_confirmation($order_id) {
global $wpdb;
$order = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_orders WHERE id = %d",
$order_id
));
if (!$order) {
return false;
}
$product = get_post($order->product_id);
if (!$product) {
return false;
}
$subject = sprintf(__('Order Confirmation - %s', 'wp-digital-download'), $product->post_title);
$message = sprintf(
__('<h2>Thank you for your purchase!</h2>
<p>Your order has been confirmed.</p>
<h3>Order Details:</h3>
<ul>
<li><strong>Order ID:</strong> #%d</li>
<li><strong>Product:</strong> %s</li>
<li><strong>Amount:</strong> %s</li>
<li><strong>Date:</strong> %s</li>
</ul>
<p>You can download your purchase from your account page.</p>
<p>Thank you for your business!</p>', 'wp-digital-download'),
$order->id,
esc_html($product->post_title),
wpdd_format_price($order->amount, $order->currency),
$order->purchase_date
);
return self::send($order->customer_email, $subject, $message, 'order_confirmation');
}
/**
* Send download link email
*/
public static function send_download_link($order_id, $download_link) {
global $wpdb;
$order = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}wpdd_orders WHERE id = %d",
$order_id
));
if (!$order) {
return false;
}
$product = get_post($order->product_id);
if (!$product) {
return false;
}
$subject = sprintf(__('Your Download Link - %s', 'wp-digital-download'), $product->post_title);
$message = sprintf(
__('<h2>Your Download is Ready!</h2>
<p>Click the link below to download your purchase:</p>
<p><a href="%s" style="display: inline-block; padding: 10px 20px; background: #0073aa; color: white; text-decoration: none; border-radius: 3px;">Download Now</a></p>
<h3>Product:</h3>
<p>%s</p>
<p><em>Note: This download link will expire. Please download your file as soon as possible.</em></p>
<p>Thank you!</p>', 'wp-digital-download'),
esc_url($download_link),
esc_html($product->post_title)
);
return self::send($order->customer_email, $subject, $message, 'download_link');
}
}