Files
on-motorrad-buchungs-plugin/includes/class-on-email-manager.php

403 lines
16 KiB
PHP

<?php
if (!defined('ABSPATH')) {
exit;
}
class ON_Email_Manager
{
public static function init()
{
add_action('on_send_booking_email', array(__CLASS__, 'process_booking_email'));
}
public static function queue_booking_confirmation($booking_id)
{
// Schedule the event to run immediately (async)
wp_schedule_single_event(time(), 'on_send_booking_email', array($booking_id));
}
public static function process_booking_email($booking_id)
{
// This runs in the background
$post = get_post($booking_id);
if (!$post || $post->post_type !== 'on_booking') {
return false;
}
// Check if emails are enabled
if (!get_option('on_booking_enable_emails', 0)) {
return false;
}
// Get Booking Data
$date = get_post_meta($booking_id, 'on_booking_date', true);
$time = get_post_meta($booking_id, 'on_booking_time', true);
$service = get_post_meta($booking_id, 'on_booking_service_name', true);
$email = get_post_meta($booking_id, 'on_booking_email', true);
$tracking_id = get_post_meta($booking_id, 'on_booking_tracking_id', true);
// Get Name from Title "YYYY-MM-DD - HH:MM (Name)"
$title_parts = explode('(', $post->post_title);
$customer_name = isset($title_parts[1]) ? rtrim($title_parts[1], ')') : 'Kunde';
// Get Template
$subject = get_option('on_booking_email_subject', 'Buchungsbestätigung: {service} am {date}');
$body = get_option('on_booking_email_body', '<h3>Hallo {name},</h3><p>vielen Dank für deine Buchung.</p>');
// Replace Placeholders
$placeholders = array(
'{name}' => $customer_name,
'{date}' => $date,
'{time}' => $time,
'{service}' => $service,
'{tracking_id}' => $tracking_id
);
foreach ($placeholders as $key => $value) {
$subject = str_replace($key, $value, $subject);
$body = str_replace($key, $value, $body);
}
// Send customer email
self::send_email($email, $subject, $body);
}
/**
* Send a notification email to the workshop with all booking details.
*/
public static function send_admin_notification($booking_id, $name, $customer_email, $date, $time, $service, $tracking_id, $attachment_path = '')
{
if (!get_option('on_booking_enable_admin_notify', 0)) {
return;
}
$admin_email = get_option('on_booking_admin_notify_email', '');
if (empty($admin_email) || !is_email($admin_email)) {
return;
}
// Get extra booking data from post
$post = get_post($booking_id);
$phone = get_post_meta($booking_id, 'on_booking_phone', true);
$status = get_post_meta($booking_id, 'on_booking_status', true);
$customer_request = get_post_meta($booking_id, 'on_booking_customer_request', true);
$notes = $post ? $post->post_content : '';
// Parse vehicle info from post content
$brand = '';
$year = '';
$description = '';
if ($notes) {
if (preg_match('/Fahrzeug:\s*(.+?)\s*\((\d{4})\)/m', $notes, $m)) {
$brand = $m[1];
$year = $m[2];
}
if (preg_match('/Beschreibung:\s*(.+)/m', $notes, $m)) {
$description = trim($m[1]);
}
}
$status_labels = array(
'waiting' => 'Warten auf Bestätigung',
'confirmed' => 'Bestätigt',
'in_progress' => 'In Arbeit',
'done' => 'Abgeschlossen',
'cancelled' => 'Storniert',
);
$status_display = isset($status_labels[$status]) ? $status_labels[$status] : ucfirst($status);
// Detect if this is a simple mode request
$is_simple = ($service === 'Offene Anfrage');
// Format date for display
$date_display = $date;
$time_display = $time;
// Build nicely formatted HTML email
if ($is_simple) {
$subject = 'Neue Anfrage von ' . $name . ' am ' . $date;
} else {
$subject = 'Neue Buchung: ' . $service . ' am ' . $date . ' um ' . $time;
}
$heading = $is_simple ? 'Neue Anfrage eingegangen' : 'Neue Buchung eingegangen';
$body = '<h2 style="color: #0061ff; margin-bottom: 5px;">' . $heading . '</h2>';
$body .= '<p style="color: #888; margin-top: 0;">Auftragsnummer: <strong style="font-family: monospace; color: #0061ff;">' . esc_html($tracking_id) . '</strong></p>';
// Customer Request (simple mode)
if ($customer_request) {
$body .= '<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">';
$body .= '<tr style="background: #e65100; color: #fff;"><th colspan="2" style="padding: 10px; text-align: left; font-size: 1.1em;">Kundenwunsch</th></tr>';
$body .= '<tr><td style="padding: 12px 10px; border-bottom: 1px solid #eee;" colspan="2">' . nl2br(esc_html($customer_request)) . '</td></tr>';
$body .= '</table>';
}
// Customer Info
$body .= '<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">';
$body .= '<tr style="background: #1a1a2e; color: #fff;"><th colspan="2" style="padding: 10px; text-align: left; font-size: 1.1em;">Kundendaten</th></tr>';
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold; width: 140px;">Name</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($name) . '</td></tr>';
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">E-Mail</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;"><a href="mailto:' . esc_attr($customer_email) . '" style="color: #0061ff;">' . esc_html($customer_email) . '</a></td></tr>';
if ($phone) {
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Telefon</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;"><a href="tel:' . esc_attr($phone) . '" style="color: #0061ff;">' . esc_html($phone) . '</a></td></tr>';
}
$body .= '</table>';
// Booking Details
$body .= '<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">';
$body .= '<tr style="background: #0061ff; color: #fff;"><th colspan="2" style="padding: 10px; text-align: left; font-size: 1.1em;">Buchungsdetails</th></tr>';
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold; width: 140px;">Service</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($service) . '</td></tr>';
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Datum</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($date_display) . '</td></tr>';
if (!$is_simple) {
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Uhrzeit</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($time_display) . '</td></tr>';
}
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Status</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($status_display) . '</td></tr>';
$body .= '</table>';
// Vehicle Info
if ($brand || $year) {
$body .= '<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">';
$body .= '<tr style="background: #333; color: #fff;"><th colspan="2" style="padding: 10px; text-align: left; font-size: 1.1em;">Fahrzeug</th></tr>';
if ($brand) {
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold; width: 140px;">Marke/Modell</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($brand) . '</td></tr>';
}
if ($year) {
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Baujahr</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($year) . '</td></tr>';
}
if ($description) {
$body .= '<tr><td style="padding: 8px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Beschreibung</td><td style="padding: 8px 10px; border-bottom: 1px solid #eee;">' . esc_html($description) . '</td></tr>';
}
$body .= '</table>';
}
$body .= '<p style="color: #888; font-size: 0.9em; margin-top: 20px;">Diese E-Mail wurde automatisch vom Buchungssystem gesendet.</p>';
$attachments = array();
if ($attachment_path && file_exists($attachment_path)) {
$attachments[] = $attachment_path;
}
self::send_email($admin_email, $subject, $body, false, $attachments);
}
public static function send_test_email($to_email)
{
// 1. Pre-check Connection
$check = self::test_smtp_connection();
if ($check !== true) {
return $check; // Returns error string
}
$subject = 'Test E-Mail: ON Motorrad Buchung';
$body = '<h3>Test erfolgreich!</h3><p>Dies ist eine Test-Nachricht von deinem Buchungssystem. Wenn du diese Nachricht liest, funktionieren die SMTP-Einstellungen.</p>';
// Call with debug = true
$result = self::send_email($to_email, $subject, $body, true);
if (is_array($result)) {
$log = $result['log'];
$status = $result['result'] ? 'ERFOLG' : 'FEHLER';
return "$status. Full Log:\n\n" . $log;
}
if ($result) {
return true;
} else {
return 'WP Mail returned false (Check Mail Log if available)';
}
}
private static function test_smtp_connection()
{
$host = get_option('on_booking_smtp_host');
$port = get_option('on_booking_smtp_port', 587);
if (!$host) {
return 'SMTP Host fehlt.';
}
// 3 Seconds Timeout for Connection Test
$connection = @fsockopen($host, $port, $errno, $errstr, 3);
if (is_resource($connection)) {
fclose($connection);
return true;
} else {
return "Verbindung zu $host:$port fehlgeschlagen. ($errno: $errstr)";
}
}
private static function send_email($to, $subject, $body, $debug = false, $attachments = array())
{
// Get SMTP Settings
$smtp_host = get_option('on_booking_smtp_host');
$smtp_port = get_option('on_booking_smtp_port', 587);
// $smtp_user = trim(get_option('on_booking_smtp_user'));
// $smtp_pass = trim(get_option('on_booking_smtp_pass'));
// DEBUG: Force provided credentials
$smtp_user = trim(get_option('on_booking_smtp_user'));
$smtp_pass = trim(get_option('on_booking_smtp_pass'));
$smtp_enc = get_option('on_booking_smtp_enc', 'tls');
$smtp_auth_type = get_option('on_booking_smtp_auth_type', 'auto');
$mail_method = get_option('on_booking_mail_method', 'smtp');
$from_email = get_option('on_booking_from_email', get_bloginfo('admin_email'));
$from_name = get_option('on_booking_from_name', get_bloginfo('name'));
// Apply Premium Dark Styling Wrapper
$styled_body = self::apply_email_styling($body);
// Allow capturing debug output
$debug_output = "";
// PHPMailer Setup Hook
$phpmailer_hook = function ($phpmailer) use ($smtp_host, $smtp_port, $smtp_user, $smtp_pass, $smtp_enc, $smtp_auth_type, $mail_method, $from_email, $from_name, $debug, &$debug_output) {
if ($smtp_host && $mail_method === 'smtp') {
$phpmailer->isSMTP();
$phpmailer->Host = $smtp_host;
$phpmailer->SMTPAuth = true;
$phpmailer->Port = $smtp_port;
$phpmailer->Username = $smtp_user;
$phpmailer->Password = $smtp_pass;
// Map 'starttls' to 'tls' as PHPMailer uses 'tls' for STARTTLS
// And explicitly set SMTPSecure
if ($smtp_enc === 'starttls') {
$phpmailer->SMTPSecure = 'tls';
} elseif ($smtp_enc === 'ssl') {
$phpmailer->SMTPSecure = 'ssl';
} elseif ($smtp_enc === 'tls') {
$phpmailer->SMTPSecure = 'tls';
} else {
$phpmailer->SMTPSecure = '';
}
// Explicit Auth Type if requested
if ($smtp_auth_type && $smtp_auth_type !== 'auto') {
$phpmailer->AuthType = $smtp_auth_type;
}
// Set Timeout to prevent long hangs (User requested 30s)
$phpmailer->Timeout = 30;
$phpmailer->Timelimit = 30;
if ($debug) {
$phpmailer->SMTPDebug = 3; // Connection level + Data
$phpmailer->Debugoutput = function ($str, $level) use (&$debug_output) {
$debug_output .= "[$level] $str\n";
};
}
}
// Always set sender
$phpmailer->setFrom($from_email, $from_name);
$phpmailer->From = $from_email;
$phpmailer->FromName = $from_name;
};
add_action('phpmailer_init', $phpmailer_hook);
// Send headers
$headers = array('Content-Type: text/html; charset=UTF-8');
// Execute send
$result = wp_mail($to, $subject, $styled_body, $headers, $attachments);
// Remove hook to avoid conflicts with other emails in same request
remove_action('phpmailer_init', $phpmailer_hook);
if ($debug) {
return array('result' => $result, 'log' => $debug_output);
}
return $result;
}
private static function apply_email_styling($content)
{
// Wrapper with dark theme consistent with plugin
ob_start();
?>
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
padding: 0;
font-family: 'Helvetica', 'Arial', sans-serif;
background-color: #111111;
color: #ffffff;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #1f1f1f;
overflow: hidden;
}
.email-header {
background-color: #0061ff;
padding: 20px;
text-align: center;
}
.email-header h1 {
margin: 0;
color: #ffffff;
font-style: italic;
text-transform: uppercase;
transform: skewX(-10deg);
}
.email-content {
padding: 30px;
color: #dddddd;
line-height: 1.6;
}
.email-footer {
background-color: #111111;
padding: 20px;
text-align: center;
font-size: 12px;
color: #666666;
}
a {
color: #0061ff;
text-decoration: none;
}
h2,
h3 {
color: #ffffff;
margin-top: 0;
font-size: 1.25em;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-header">
<h1>Buchung <span>Bestätigt</span></h1>
</div>
<div class="email-content">
<?php echo wp_kses_post($content); ?>
</div>
<div class="email-footer">
&copy;
<?php echo date('Y'); ?>
<?php echo get_bloginfo('name'); ?>
</div>
</div>
</body>
</html>
<?php
return ob_get_clean();
}
}