feat: Custom email system foundation
## ✅ Step 1-3: Email System Core ### EmailManager.php - ✅ Disables WooCommerce emails (prevents duplicates) - ✅ Hooks into all WC order status changes - ✅ Hooks into customer, product events - ✅ Checks if events are enabled before sending - ✅ Sends via wp_mail() (SMTP plugin compatible) ### EmailRenderer.php - ✅ Renders emails with design templates - ✅ Variable replacement system - ✅ Gets recipient email (staff/customer) - ✅ Loads order/product/customer variables - ✅ Filter hook: `woonoow_email_template` - ✅ Supports HTML template designs ### Email Design Templates (3) **templates/emails/modern.html** - ✅ Clean, minimalist, Apple-inspired - ✅ Dark mode support - ✅ Mobile responsive - ✅ 2024 design trends **templates/emails/classic.html** - ✅ Professional, traditional - ✅ Gradient header - ✅ Table styling - ✅ Business-appropriate **templates/emails/minimal.html** - ✅ Ultra-clean, monospace font - ✅ Black & white aesthetic - ✅ Text-focused - ✅ Dark mode invert ### Architecture ``` Design Template (HTML) → Content Template (Text) → Final Email modern.html → order_processing → Beautiful HTML ``` --- **Next:** Rich text editor + Content templates 🎨
This commit is contained in:
382
includes/Core/Notifications/EmailManager.php
Normal file
382
includes/Core/Notifications/EmailManager.php
Normal file
@@ -0,0 +1,382 @@
|
||||
<?php
|
||||
/**
|
||||
* Email Manager
|
||||
*
|
||||
* Manages custom email notifications and disables WooCommerce default emails
|
||||
*
|
||||
* @package WooNooW\Core\Notifications
|
||||
*/
|
||||
|
||||
namespace WooNooW\Core\Notifications;
|
||||
|
||||
class EmailManager {
|
||||
|
||||
/**
|
||||
* Instance
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Get instance
|
||||
*/
|
||||
public static function instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->init_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize hooks
|
||||
*/
|
||||
private function init_hooks() {
|
||||
// Disable WooCommerce emails to prevent duplicates
|
||||
add_action('woocommerce_email', [$this, 'disable_wc_emails'], 1);
|
||||
|
||||
// Hook into WooCommerce order status changes
|
||||
add_action('woocommerce_order_status_pending_to_processing', [$this, 'send_order_processing_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_pending_to_completed', [$this, 'send_order_completed_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_processing_to_completed', [$this, 'send_order_completed_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_completed', [$this, 'send_order_completed_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_pending_to_on-hold', [$this, 'send_order_on_hold_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_failed_to_processing', [$this, 'send_order_processing_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_cancelled', [$this, 'send_order_cancelled_email'], 10, 2);
|
||||
add_action('woocommerce_order_status_refunded', [$this, 'send_order_refunded_email'], 10, 2);
|
||||
add_action('woocommerce_order_fully_refunded', [$this, 'send_order_refunded_email'], 10, 2);
|
||||
|
||||
// New order notification for admin
|
||||
add_action('woocommerce_new_order', [$this, 'send_new_order_admin_email'], 10, 1);
|
||||
|
||||
// Customer note
|
||||
add_action('woocommerce_new_customer_note', [$this, 'send_customer_note_email'], 10, 1);
|
||||
|
||||
// New customer account
|
||||
add_action('woocommerce_created_customer', [$this, 'send_new_customer_email'], 10, 3);
|
||||
|
||||
// Low stock / Out of stock
|
||||
add_action('woocommerce_low_stock', [$this, 'send_low_stock_email'], 10, 1);
|
||||
add_action('woocommerce_no_stock', [$this, 'send_out_of_stock_email'], 10, 1);
|
||||
add_action('woocommerce_product_set_stock', [$this, 'check_stock_levels'], 10, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable WooCommerce default emails
|
||||
*
|
||||
* @param WC_Emails $email_class
|
||||
*/
|
||||
public function disable_wc_emails($email_class) {
|
||||
// Get WooNooW notification settings
|
||||
$settings = get_option('woonoow_notification_settings', []);
|
||||
|
||||
// Check if custom emails are enabled (default: yes)
|
||||
$use_custom_emails = $settings['use_custom_emails'] ?? true;
|
||||
|
||||
if (!$use_custom_emails) {
|
||||
return; // Keep WC emails if custom emails disabled
|
||||
}
|
||||
|
||||
// Disable all WooCommerce transactional emails
|
||||
$emails_to_disable = [
|
||||
'WC_Email_New_Order', // Admin: New order
|
||||
'WC_Email_Cancelled_Order', // Admin: Cancelled order
|
||||
'WC_Email_Failed_Order', // Admin: Failed order
|
||||
'WC_Email_Customer_On_Hold_Order', // Customer: Order on-hold
|
||||
'WC_Email_Customer_Processing_Order', // Customer: Processing order
|
||||
'WC_Email_Customer_Completed_Order', // Customer: Completed order
|
||||
'WC_Email_Customer_Refunded_Order', // Customer: Refunded order
|
||||
'WC_Email_Customer_Invoice', // Customer: Invoice
|
||||
'WC_Email_Customer_Note', // Customer: Note added
|
||||
'WC_Email_Customer_Reset_Password', // Customer: Reset password
|
||||
'WC_Email_Customer_New_Account', // Customer: New account
|
||||
];
|
||||
|
||||
foreach ($emails_to_disable as $email_id) {
|
||||
add_filter('woocommerce_email_enabled_' . strtolower(str_replace('WC_Email_', '', $email_id)), '__return_false');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send order processing email
|
||||
*
|
||||
* @param int $order_id
|
||||
* @param WC_Order $order
|
||||
*/
|
||||
public function send_order_processing_email($order_id, $order = null) {
|
||||
if (!$order) {
|
||||
$order = wc_get_order($order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('order_processing', 'email', 'customer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('order_processing', 'customer', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send order completed email
|
||||
*
|
||||
* @param int $order_id
|
||||
* @param WC_Order $order
|
||||
*/
|
||||
public function send_order_completed_email($order_id, $order = null) {
|
||||
if (!$order) {
|
||||
$order = wc_get_order($order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('order_completed', 'email', 'customer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('order_completed', 'customer', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send order on-hold email
|
||||
*
|
||||
* @param int $order_id
|
||||
* @param WC_Order $order
|
||||
*/
|
||||
public function send_order_on_hold_email($order_id, $order = null) {
|
||||
if (!$order) {
|
||||
$order = wc_get_order($order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('order_processing', 'email', 'customer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email (use processing template for on-hold)
|
||||
$this->send_email('order_processing', 'customer', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send order cancelled email
|
||||
*
|
||||
* @param int $order_id
|
||||
* @param WC_Order $order
|
||||
*/
|
||||
public function send_order_cancelled_email($order_id, $order = null) {
|
||||
if (!$order) {
|
||||
$order = wc_get_order($order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send to admin
|
||||
if ($this->is_event_enabled('order_cancelled', 'email', 'staff')) {
|
||||
$this->send_email('order_cancelled', 'staff', $order);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send order refunded email
|
||||
*
|
||||
* @param int $order_id
|
||||
* @param WC_Order $order
|
||||
*/
|
||||
public function send_order_refunded_email($order_id, $order = null) {
|
||||
if (!$order) {
|
||||
$order = wc_get_order($order_id);
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('order_refunded', 'email', 'customer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('order_refunded', 'customer', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send new order admin email
|
||||
*
|
||||
* @param int $order_id
|
||||
*/
|
||||
public function send_new_order_admin_email($order_id) {
|
||||
$order = wc_get_order($order_id);
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('order_placed', 'email', 'staff')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('order_placed', 'staff', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send customer note email
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
public function send_customer_note_email($args) {
|
||||
$order = wc_get_order($args['order_id']);
|
||||
|
||||
if (!$order) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('customer_note', 'email', 'customer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email with note data
|
||||
$this->send_email('customer_note', 'customer', $order, ['note' => $args['customer_note']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send new customer email
|
||||
*
|
||||
* @param int $customer_id
|
||||
* @param array $new_customer_data
|
||||
* @param bool $password_generated
|
||||
*/
|
||||
public function send_new_customer_email($customer_id, $new_customer_data = [], $password_generated = false) {
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('new_customer', 'email', 'customer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$customer = new \WC_Customer($customer_id);
|
||||
|
||||
// Send email
|
||||
$this->send_email('new_customer', 'customer', $customer, [
|
||||
'password_generated' => $password_generated,
|
||||
'user_login' => $new_customer_data['user_login'] ?? '',
|
||||
'user_pass' => $new_customer_data['user_pass'] ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send low stock email
|
||||
*
|
||||
* @param WC_Product $product
|
||||
*/
|
||||
public function send_low_stock_email($product) {
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('low_stock', 'email', 'staff')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('low_stock', 'staff', $product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send out of stock email
|
||||
*
|
||||
* @param WC_Product $product
|
||||
*/
|
||||
public function send_out_of_stock_email($product) {
|
||||
// Check if event is enabled
|
||||
if (!$this->is_event_enabled('out_of_stock', 'email', 'staff')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email
|
||||
$this->send_email('out_of_stock', 'staff', $product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check stock levels when product stock is updated
|
||||
*
|
||||
* @param WC_Product $product
|
||||
*/
|
||||
public function check_stock_levels($product) {
|
||||
$stock = $product->get_stock_quantity();
|
||||
$low_stock_threshold = get_option('woocommerce_notify_low_stock_amount', 2);
|
||||
|
||||
if ($stock <= 0) {
|
||||
$this->send_out_of_stock_email($product);
|
||||
} elseif ($stock <= $low_stock_threshold) {
|
||||
$this->send_low_stock_email($product);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if event is enabled
|
||||
*
|
||||
* @param string $event_id
|
||||
* @param string $channel_id
|
||||
* @param string $recipient_type
|
||||
* @return bool
|
||||
*/
|
||||
private function is_event_enabled($event_id, $channel_id, $recipient_type) {
|
||||
$settings = get_option('woonoow_notification_settings', []);
|
||||
|
||||
// Check if event exists and channel is enabled
|
||||
if (isset($settings['events'][$event_id]['channels'][$channel_id])) {
|
||||
return $settings['events'][$event_id]['channels'][$channel_id]['enabled'] ?? false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email
|
||||
*
|
||||
* @param string $event_id
|
||||
* @param string $recipient_type
|
||||
* @param mixed $data
|
||||
* @param array $extra_data
|
||||
*/
|
||||
private function send_email($event_id, $recipient_type, $data, $extra_data = []) {
|
||||
// Get email renderer
|
||||
$renderer = EmailRenderer::instance();
|
||||
|
||||
// Render email
|
||||
$email = $renderer->render($event_id, $recipient_type, $data, $extra_data);
|
||||
|
||||
if (!$email) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send email via wp_mail
|
||||
$headers = [
|
||||
'Content-Type: text/html; charset=UTF-8',
|
||||
'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>',
|
||||
];
|
||||
|
||||
wp_mail($email['to'], $email['subject'], $email['body'], $headers);
|
||||
|
||||
// Log email sent
|
||||
do_action('woonoow_email_sent', $event_id, $recipient_type, $email);
|
||||
}
|
||||
}
|
||||
274
includes/Core/Notifications/EmailRenderer.php
Normal file
274
includes/Core/Notifications/EmailRenderer.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
/**
|
||||
* Email Renderer
|
||||
*
|
||||
* Renders email templates with content
|
||||
*
|
||||
* @package WooNooW\Core\Notifications
|
||||
*/
|
||||
|
||||
namespace WooNooW\Core\Notifications;
|
||||
|
||||
class EmailRenderer {
|
||||
|
||||
/**
|
||||
* Instance
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Get instance
|
||||
*/
|
||||
public static function instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render email
|
||||
*
|
||||
* @param string $event_id Event ID (order_placed, order_processing, etc.)
|
||||
* @param string $recipient_type Recipient type (staff, customer)
|
||||
* @param mixed $data Order, Product, or Customer object
|
||||
* @param array $extra_data Additional data
|
||||
* @return array|null ['to', 'subject', 'body']
|
||||
*/
|
||||
public function render($event_id, $recipient_type, $data, $extra_data = []) {
|
||||
// Get template settings
|
||||
$template_settings = $this->get_template_settings($event_id, $recipient_type);
|
||||
|
||||
if (!$template_settings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get recipient email
|
||||
$to = $this->get_recipient_email($recipient_type, $data);
|
||||
|
||||
if (!$to) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get variables
|
||||
$variables = $this->get_variables($event_id, $data, $extra_data);
|
||||
|
||||
// Replace variables in subject and content
|
||||
$subject = $this->replace_variables($template_settings['subject'], $variables);
|
||||
$content = $this->replace_variables($template_settings['body'], $variables);
|
||||
|
||||
// Get HTML template design
|
||||
$design_template = $this->get_design_template($template_settings['design'] ?? 'modern');
|
||||
|
||||
// Render final HTML
|
||||
$html = $this->render_html($design_template, $content, $subject, $variables);
|
||||
|
||||
return [
|
||||
'to' => $to,
|
||||
'subject' => $subject,
|
||||
'body' => $html,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template settings
|
||||
*
|
||||
* @param string $event_id
|
||||
* @param string $recipient_type
|
||||
* @return array|null
|
||||
*/
|
||||
private function get_template_settings($event_id, $recipient_type) {
|
||||
// Get saved template
|
||||
$template = TemplateProvider::get_template($event_id, 'email');
|
||||
|
||||
if (!$template) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get design template preference
|
||||
$settings = get_option('woonoow_notification_settings', []);
|
||||
$design = $settings['email_design_template'] ?? 'modern';
|
||||
|
||||
return [
|
||||
'subject' => $template['subject'] ?? '',
|
||||
'body' => $template['body'] ?? '',
|
||||
'design' => $design,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recipient email
|
||||
*
|
||||
* @param string $recipient_type
|
||||
* @param mixed $data
|
||||
* @return string|null
|
||||
*/
|
||||
private function get_recipient_email($recipient_type, $data) {
|
||||
if ($recipient_type === 'staff') {
|
||||
return get_option('admin_email');
|
||||
}
|
||||
|
||||
// Customer
|
||||
if ($data instanceof \WC_Order) {
|
||||
return $data->get_billing_email();
|
||||
}
|
||||
|
||||
if ($data instanceof \WC_Customer) {
|
||||
return $data->get_email();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variables for template
|
||||
*
|
||||
* @param string $event_id
|
||||
* @param mixed $data
|
||||
* @param array $extra_data
|
||||
* @return array
|
||||
*/
|
||||
private function get_variables($event_id, $data, $extra_data = []) {
|
||||
$variables = [
|
||||
'store_name' => get_bloginfo('name'),
|
||||
'store_url' => home_url(),
|
||||
'site_title' => get_bloginfo('name'),
|
||||
];
|
||||
|
||||
// Order variables
|
||||
if ($data instanceof \WC_Order) {
|
||||
$variables = array_merge($variables, [
|
||||
'order_number' => $data->get_order_number(),
|
||||
'order_id' => $data->get_id(),
|
||||
'order_date' => $data->get_date_created()->date('F j, Y'),
|
||||
'order_total' => $data->get_formatted_order_total(),
|
||||
'order_subtotal' => wc_price($data->get_subtotal()),
|
||||
'order_tax' => wc_price($data->get_total_tax()),
|
||||
'order_shipping' => wc_price($data->get_shipping_total()),
|
||||
'order_discount' => wc_price($data->get_discount_total()),
|
||||
'order_status' => wc_get_order_status_name($data->get_status()),
|
||||
'order_url' => $data->get_view_order_url(),
|
||||
'payment_method' => $data->get_payment_method_title(),
|
||||
'shipping_method' => $data->get_shipping_method(),
|
||||
'customer_name' => $data->get_formatted_billing_full_name(),
|
||||
'customer_first_name' => $data->get_billing_first_name(),
|
||||
'customer_last_name' => $data->get_billing_last_name(),
|
||||
'customer_email' => $data->get_billing_email(),
|
||||
'customer_phone' => $data->get_billing_phone(),
|
||||
'billing_address' => $data->get_formatted_billing_address(),
|
||||
'shipping_address' => $data->get_formatted_shipping_address(),
|
||||
]);
|
||||
|
||||
// Order items
|
||||
$items_html = '';
|
||||
foreach ($data->get_items() as $item) {
|
||||
$product = $item->get_product();
|
||||
$items_html .= sprintf(
|
||||
'<tr><td>%s × %d</td><td>%s</td></tr>',
|
||||
$item->get_name(),
|
||||
$item->get_quantity(),
|
||||
wc_price($item->get_total())
|
||||
);
|
||||
}
|
||||
$variables['order_items'] = $items_html;
|
||||
}
|
||||
|
||||
// Product variables
|
||||
if ($data instanceof \WC_Product) {
|
||||
$variables = array_merge($variables, [
|
||||
'product_id' => $data->get_id(),
|
||||
'product_name' => $data->get_name(),
|
||||
'product_sku' => $data->get_sku(),
|
||||
'product_price' => wc_price($data->get_price()),
|
||||
'product_url' => get_permalink($data->get_id()),
|
||||
'stock_quantity' => $data->get_stock_quantity(),
|
||||
'stock_status' => $data->get_stock_status(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Customer variables
|
||||
if ($data instanceof \WC_Customer) {
|
||||
$variables = array_merge($variables, [
|
||||
'customer_id' => $data->get_id(),
|
||||
'customer_name' => $data->get_display_name(),
|
||||
'customer_first_name' => $data->get_first_name(),
|
||||
'customer_last_name' => $data->get_last_name(),
|
||||
'customer_email' => $data->get_email(),
|
||||
'customer_username' => $data->get_username(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Merge extra data
|
||||
$variables = array_merge($variables, $extra_data);
|
||||
|
||||
return apply_filters('woonoow_email_variables', $variables, $event_id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace variables in text
|
||||
*
|
||||
* @param string $text
|
||||
* @param array $variables
|
||||
* @return string
|
||||
*/
|
||||
private function replace_variables($text, $variables) {
|
||||
foreach ($variables as $key => $value) {
|
||||
$text = str_replace('{' . $key . '}', $value, $text);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get design template path
|
||||
*
|
||||
* @param string $design Template name (modern, classic, minimal)
|
||||
* @return string
|
||||
*/
|
||||
private function get_design_template($design) {
|
||||
$template_path = WOONOOW_PATH . 'templates/emails/' . $design . '.html';
|
||||
|
||||
// Allow filtering template path
|
||||
$template_path = apply_filters('woonoow_email_template', $template_path, $design);
|
||||
|
||||
// Fallback to modern if template doesn't exist
|
||||
if (!file_exists($template_path)) {
|
||||
$template_path = WOONOOW_PATH . 'templates/emails/modern.html';
|
||||
}
|
||||
|
||||
return $template_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render HTML email
|
||||
*
|
||||
* @param string $template_path Path to HTML template
|
||||
* @param string $content Email content (HTML)
|
||||
* @param string $subject Email subject
|
||||
* @param array $variables All variables
|
||||
* @return string
|
||||
*/
|
||||
private function render_html($template_path, $content, $subject, $variables) {
|
||||
if (!file_exists($template_path)) {
|
||||
// Fallback to plain HTML
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Load template
|
||||
$html = file_get_contents($template_path);
|
||||
|
||||
// Replace placeholders
|
||||
$html = str_replace('{{email_heading}}', $subject, $html);
|
||||
$html = str_replace('{{email_content}}', $content, $html);
|
||||
$html = str_replace('{{store_name}}', $variables['store_name'], $html);
|
||||
$html = str_replace('{{store_url}}', $variables['store_url'], $html);
|
||||
$html = str_replace('{{current_year}}', date('Y'), $html);
|
||||
|
||||
// Replace all other variables
|
||||
foreach ($variables as $key => $value) {
|
||||
$html = str_replace('{{' . $key . '}}', $value, $html);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
238
templates/emails/classic.html
Normal file
238
templates/emails/classic.html
Normal file
@@ -0,0 +1,238 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{email_heading}}</title>
|
||||
<style>
|
||||
/* Reset */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
|
||||
|
||||
/* Base */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
background-color: #f4f4f4;
|
||||
color: #333333;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.email-container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.email-header {
|
||||
padding: 30px 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-logo {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.email-content {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.email-heading {
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: #333333;
|
||||
margin: 0 0 20px;
|
||||
line-height: 1.3;
|
||||
border-bottom: 3px solid #667eea;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.email-text {
|
||||
font-size: 16px;
|
||||
color: #555555;
|
||||
margin: 0 0 16px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.email-text strong {
|
||||
color: #333333;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.email-button {
|
||||
display: inline-block;
|
||||
padding: 15px 35px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #ffffff !important;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 24px 0;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* Info Box */
|
||||
.info-box {
|
||||
background-color: #f9f9f9;
|
||||
border: 2px solid #eeeeee;
|
||||
border-radius: 4px;
|
||||
padding: 24px;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px dashed #dddddd;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 14px;
|
||||
color: #777777;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
font-weight: 600;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Table */
|
||||
.email-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 24px 0;
|
||||
border: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
.email-table th {
|
||||
text-align: left;
|
||||
padding: 14px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.email-table td {
|
||||
padding: 14px;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.email-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.email-table tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.email-footer {
|
||||
padding: 30px 40px;
|
||||
background-color: #333333;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-footer-text {
|
||||
font-size: 13px;
|
||||
color: #cccccc;
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.email-footer-link {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Divider */
|
||||
.divider {
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, transparent, #667eea, transparent);
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media only screen and (max-width: 600px) {
|
||||
.email-header,
|
||||
.email-content,
|
||||
.email-footer {
|
||||
padding: 25px 20px !important;
|
||||
}
|
||||
|
||||
.email-heading {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
padding: 16px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="padding: 30px 20px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" class="email-container">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td class="email-header">
|
||||
<a href="{{store_url}}" class="email-logo">{{store_name}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Content -->
|
||||
<tr>
|
||||
<td class="email-content">
|
||||
<h1 class="email-heading">{{email_heading}}</h1>
|
||||
|
||||
<!-- Dynamic content will be inserted here -->
|
||||
{{email_content}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="email-footer">
|
||||
<p class="email-footer-text">
|
||||
© {{current_year}} {{store_name}}. All rights reserved.
|
||||
</p>
|
||||
<p class="email-footer-text">
|
||||
<a href="{{store_url}}" class="email-footer-link">Visit our store</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
280
templates/emails/minimal.html
Normal file
280
templates/emails/minimal.html
Normal file
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{email_heading}}</title>
|
||||
<style>
|
||||
/* Reset */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
|
||||
|
||||
/* Base */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.email-container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.email-header {
|
||||
padding: 40px 40px 20px;
|
||||
border-bottom: 2px solid #000000;
|
||||
}
|
||||
|
||||
.email-logo {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.email-content {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.email-heading {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
margin: 0 0 30px;
|
||||
line-height: 1.4;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.email-text {
|
||||
font-size: 14px;
|
||||
color: #000000;
|
||||
margin: 0 0 20px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.email-text strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.email-button {
|
||||
display: inline-block;
|
||||
padding: 12px 30px;
|
||||
background-color: #000000;
|
||||
color: #ffffff !important;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
margin: 24px 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
/* Info Box */
|
||||
.info-box {
|
||||
border: 1px solid #000000;
|
||||
padding: 20px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 12px;
|
||||
color: #000000;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 14px;
|
||||
color: #000000;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Table */
|
||||
.email-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 30px 0;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.email-table th {
|
||||
text-align: left;
|
||||
padding: 12px;
|
||||
background-color: #000000;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.email-table td {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #000000;
|
||||
font-size: 14px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.email-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.email-footer {
|
||||
padding: 20px 40px 40px;
|
||||
border-top: 2px solid #000000;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.email-footer-text {
|
||||
font-size: 11px;
|
||||
color: #000000;
|
||||
margin: 0 0 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.email-footer-link {
|
||||
color: #000000;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Divider */
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: #000000;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media only screen and (max-width: 600px) {
|
||||
.email-header,
|
||||
.email-content,
|
||||
.email-footer {
|
||||
padding: 30px 20px !important;
|
||||
}
|
||||
|
||||
.email-heading {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
padding: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode - invert colors */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #000000 !important;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
background-color: #000000 !important;
|
||||
}
|
||||
|
||||
.email-header {
|
||||
border-bottom-color: #ffffff !important;
|
||||
}
|
||||
|
||||
.email-logo,
|
||||
.email-heading,
|
||||
.email-text,
|
||||
.email-text strong,
|
||||
.info-label,
|
||||
.info-value,
|
||||
.email-table td,
|
||||
.email-footer-text,
|
||||
.email-footer-link {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.info-box,
|
||||
.email-table {
|
||||
border-color: #ffffff !important;
|
||||
}
|
||||
|
||||
.email-table td {
|
||||
border-bottom-color: #ffffff !important;
|
||||
}
|
||||
|
||||
.email-button {
|
||||
background-color: #ffffff !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.email-table th {
|
||||
background-color: #ffffff !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.email-footer {
|
||||
border-top-color: #ffffff !important;
|
||||
}
|
||||
|
||||
.divider {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="padding: 0;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" class="email-container">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td class="email-header">
|
||||
<a href="{{store_url}}" class="email-logo">{{store_name}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Content -->
|
||||
<tr>
|
||||
<td class="email-content">
|
||||
<h1 class="email-heading">{{email_heading}}</h1>
|
||||
|
||||
<!-- Dynamic content will be inserted here -->
|
||||
{{email_content}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="email-footer">
|
||||
<p class="email-footer-text">
|
||||
© {{current_year}} {{store_name}}
|
||||
</p>
|
||||
<p class="email-footer-text">
|
||||
<a href="{{store_url}}" class="email-footer-link">{{store_url}}</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
275
templates/emails/modern.html
Normal file
275
templates/emails/modern.html
Normal file
@@ -0,0 +1,275 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{email_heading}}</title>
|
||||
<style>
|
||||
/* Reset */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
|
||||
|
||||
/* Base */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
background-color: #f5f5f7;
|
||||
color: #1d1d1f;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.email-container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.email-header {
|
||||
padding: 40px 40px 30px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #e5e5e7;
|
||||
}
|
||||
|
||||
.email-logo {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #1d1d1f;
|
||||
text-decoration: none;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.email-content {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.email-heading {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #1d1d1f;
|
||||
margin: 0 0 20px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.email-text {
|
||||
font-size: 16px;
|
||||
color: #424245;
|
||||
margin: 0 0 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.email-text strong {
|
||||
color: #1d1d1f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.email-button {
|
||||
display: inline-block;
|
||||
padding: 14px 32px;
|
||||
background-color: #0071e3;
|
||||
color: #ffffff !important;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin: 24px 0;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.email-button:hover {
|
||||
background-color: #0077ed;
|
||||
}
|
||||
|
||||
/* Info Box */
|
||||
.info-box {
|
||||
background-color: #f5f5f7;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #e5e5e7;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 14px;
|
||||
color: #6e6e73;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 14px;
|
||||
color: #1d1d1f;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Table */
|
||||
.email-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.email-table th {
|
||||
text-align: left;
|
||||
padding: 12px;
|
||||
background-color: #f5f5f7;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #6e6e73;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.email-table td {
|
||||
padding: 16px 12px;
|
||||
border-bottom: 1px solid #e5e5e7;
|
||||
font-size: 15px;
|
||||
color: #1d1d1f;
|
||||
}
|
||||
|
||||
.email-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.email-footer {
|
||||
padding: 30px 40px;
|
||||
background-color: #f5f5f7;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e5e5e7;
|
||||
}
|
||||
|
||||
.email-footer-text {
|
||||
font-size: 13px;
|
||||
color: #6e6e73;
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.email-footer-link {
|
||||
color: #0071e3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media only screen and (max-width: 600px) {
|
||||
.email-header,
|
||||
.email-content,
|
||||
.email-footer {
|
||||
padding: 30px 20px !important;
|
||||
}
|
||||
|
||||
.email-heading {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
padding: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #000000 !important;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
background-color: #1c1c1e !important;
|
||||
}
|
||||
|
||||
.email-header {
|
||||
border-bottom-color: #38383a !important;
|
||||
}
|
||||
|
||||
.email-logo,
|
||||
.email-heading,
|
||||
.info-value,
|
||||
.email-table td {
|
||||
color: #f5f5f7 !important;
|
||||
}
|
||||
|
||||
.email-text {
|
||||
color: #a1a1a6 !important;
|
||||
}
|
||||
|
||||
.email-text strong {
|
||||
color: #f5f5f7 !important;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background-color: #2c2c2e !important;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
border-bottom-color: #38383a !important;
|
||||
}
|
||||
|
||||
.email-table th {
|
||||
background-color: #2c2c2e !important;
|
||||
}
|
||||
|
||||
.email-table td {
|
||||
border-bottom-color: #38383a !important;
|
||||
}
|
||||
|
||||
.email-footer {
|
||||
background-color: #1c1c1e !important;
|
||||
border-top-color: #38383a !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="padding: 40px 20px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" class="email-container">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td class="email-header">
|
||||
<a href="{{store_url}}" class="email-logo">{{store_name}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Content -->
|
||||
<tr>
|
||||
<td class="email-content">
|
||||
<h1 class="email-heading">{{email_heading}}</h1>
|
||||
|
||||
<!-- Dynamic content will be inserted here -->
|
||||
{{email_content}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="email-footer">
|
||||
<p class="email-footer-text">
|
||||
© {{current_year}} {{store_name}}. All rights reserved.
|
||||
</p>
|
||||
<p class="email-footer-text">
|
||||
<a href="{{store_url}}" class="email-footer-link">Visit our store</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user