Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Email Template Editor #978

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,19 @@
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_mail_from_name = sanitizeInput($config_mail_from_name);
$config_mail_from_email = sanitizeInput($config_mail_from_email);

// Get Email Template
$config_et_client_securelink = prepareEmailTemplate($config_et_client_securelink);
$config_et_client_securelink_subj = prepareEmailTemplateTags($config_et_client_securelink_subj);

// Send user e-mail, if specified
if(!empty($config_smtp_host) && filter_var($item_email, FILTER_VALIDATE_EMAIL)){

$subject = "Time sensitive - $company_name secure link enclosed";
$subject = "$config_et_client_securelink_subj";
if ($item_expires_friendly == "never") {
$subject = "$company_name secure link enclosed";
$subject = "$config_et_client_securelink_subj";
}
$body = "Hello,<br><br>$session_name from $company_name sent you a time sensitive secure link regarding \"$item_name\".<br><br>The link will expire in <strong>$item_expires_friendly</strong> and may only be viewed <strong>$item_view_limit</strong> times, before the link is destroyed. <br><br><strong><a href=\'$url\'>Click here to access your secure content</a></strong><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$body = "$config_et_client_securelink";

$data = [
[
Expand Down
26 changes: 18 additions & 8 deletions cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,14 @@
$sql_ticket_reply = mysqli_query($mysqli, "SELECT ticket_reply FROM ticket_replies WHERE ticket_reply_type = 'Public' AND ticket_reply_ticket_id = $ticket_id ORDER BY ticket_reply_created_at DESC LIMIT 1");
$ticket_reply_row = mysqli_fetch_array($sql_ticket_reply);
$ticket_reply = $ticket_reply_row['ticket_reply'];

// Get Email Template
$config_et_client_ticket_autoclose = prepareEmailTemplate($config_et_client_ticket_autoclose, true);
$config_et_client_ticket_autoclose_subj = prepareEmailTemplateTags($config_et_client_ticket_autoclose_subj);

$subject = "Ticket pending closure - [$ticket_prefix$ticket_number] - $ticket_subject";
$subject = "$config_et_client_ticket_autoclose_subj";

$body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello, $contact_name<br><br>This is an automatic friendly reminder that your ticket regarding \"$ticket_subject\" will be closed, unless you respond.<br><br>--------------------------------<br>$ticket_reply--------------------------------<br><br>If your issue is resolved, you can ignore this email - the ticket will automatically close. If you need further assistance, please respond to this email. <br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: $ticket_status <br>Portal: https://$config_base_url/portal/ticket.php?id=$ticket_id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$body = "$config_et_client_ticket_autoclose";

$data = [
[
Expand Down Expand Up @@ -490,6 +494,10 @@
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);

// Get Email Template
$config_et_client_invoice_paymentreminder = prepareEmailTemplate($config_et_client_invoice_paymentreminder);
$config_et_client_invoice_paymentreminder_subj = prepareEmailTemplateTags($config_et_client_invoice_paymentreminder_subj);

// Late Charges

Expand All @@ -512,10 +520,8 @@

mysqli_query($mysqli, "INSERT INTO notifications SET notification_type = 'Invoice Overdue', notification = 'Invoice $invoice_prefix$invoice_number for $client_name in the amount of $invoice_amount is overdue by $day days', notification_action = 'invoice.php?invoice_id=$invoice_id', notification_client_id = $client_id, notification_entity_id = $invoice_id");

$subject = "$company_name Overdue Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>Our records indicate that we have not yet received payment for the invoice $invoice_prefix$invoice_number. We kindly request that you submit your payment as soon as possible. If you have any questions or concerns, please do not hesitate to contact us at $company_email or $company_phone.
<br><br>
Kindly review the invoice details mentioned below.<br><br>Invoice: $invoice_prefix$invoice_number<br>Issue Date: $invoice_date<br>Total: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "<br>Due Date: $invoice_due<br>Over Due By: $day Days<br><br><br>To view your invoice, please click <a href=\'https://$config_base_url/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>here</a>.<br><br><br>--<br>$company_name - Billing<br>$config_invoice_from_email<br>$company_phone";
$subject = "$config_et_client_invoice_paymentreminder_subj";
$body = "$config_et_client_invoice_paymentreminder";

$mail = addToMailQueue($mysqli, [
[
Expand Down Expand Up @@ -632,9 +638,13 @@
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);

// Get Email Template
$config_et_client_invoice_newrecurring = prepareEmailTemplate($config_et_client_invoice_newrecurring);
$config_et_client_invoice_newrecurring_subj = prepareEmailTemplateTags($config_et_client_invoice_newrecurring_subj);

$subject = "$company_name Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>An invoice regarding \"$invoice_scope\" has been generated. Please view the details below.<br><br>Invoice: $invoice_prefix$invoice_number<br>Issue Date: $invoice_date<br>Total: " . numfmt_format_currency($currency_format, $invoice_amount, $recurring_currency_code) . "<br>Due Date: $invoice_due<br><br><br>To view your invoice, please click <a href=\'https://$config_base_url/guest_view_invoice.php?invoice_id=$new_invoice_id&url_key=$invoice_url_key\'>here</a>.<br><br><br>--<br>$company_name - Billing<br>$config_invoice_from_email<br>$company_phone";
$subject = "$config_et_client_invoice_newrecurring_subj";
$body = "$config_et_client_invoice_newrecurring";

$mail = addToMailQueue($mysqli, [
[
Expand Down
11 changes: 8 additions & 3 deletions cron_ticket_email_parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,14 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date

$data = [];
if ($config_ticket_client_general_notifications == 1) {
$subject_email = "Ticket created - [$config_ticket_prefix$ticket_number] - $subject";
$body = "<i style='color: #808080'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>Thank you for your email. A ticket regarding \"$subject\" has been automatically created for you.<br><br>Ticket: $config_ticket_prefix$ticket_number<br>Subject: $subject<br>Status: New<br>https://$config_base_url/portal/ticket.php?id=$id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";


// Get Email Template
$config_et_client_ticket_new = prepareEmailTemplate($config_et_client_ticket_new, true);
$config_et_client_ticket_new_subj = prepareEmailTemplateTags($config_et_client_ticket_new_subj);

$subject_email = "$config_et_client_ticket_new_subj";
$body = "$config_et_client_ticket_new";

$data[] = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
Expand Down
2 changes: 1 addition & 1 deletion database_updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -2085,4 +2085,4 @@

} else {
// Up-to-date
}
}
172 changes: 172 additions & 0 deletions email-templates-sample.sql

Large diffs are not rendered by default.

119 changes: 119 additions & 0 deletions functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,125 @@ function sanitizeForEmail($data)
return $sanitized;
}

// Email Template [tag] [[tag]] and [[tag][tag2]] Replacements
function prepareEmailTemplateTags($emailTemplateTags)
{
// Placeholder to avoid collision with actual content
$placeholderPrefix = '__DOUBLE_BRACKET__';
$placeholders = [];
$counter = 0;

// Define the predetermined list of accepted tags
$acceptedTags = [
'company_name',
'config_base_url',
'ticket_client_id',
'contact_email',
'contact_name',
'ticket_assigned_to',
'ticket_category',
'ticket_created_by',
'ticket_details',
'ticket_number',
'ticket_prefix',
'ticket_priority',
'ticket_subject',
'ticket_id',
'client_id',
'client_name',
'invoice_amount',
'invoice_date',
'invoice_number',
'invoice_prefix',
'invoice_url_key',
'quote_amount',
'quote_date',
'quote_expire',
'quote_number',
'quote_prefix',
'quote_scope',
'quote_url_key',
'client_id',
'contact_email',
'contact_name',
'item_email',
'item_expires_friendly',
'item_type',
'item_view_limit',
'url',
'name',
'password_info',
'username',
'start',
'title',
'ticket_reply',
'company_phone'
];

// Perform variable substitution for double-bracketed tags [[this]] or [[this][that]]
$emailTemplateTags = preg_replace_callback('/\[\[(.*?)\]\]/', function($matches) use (&$placeholders, &$counter, $placeholderPrefix, $acceptedTags) {
$innerContent = $matches[1];
$parts = explode('][', $innerContent);

$result = array_map(function($part) use ($acceptedTags) {
$part = trim($part);
if (in_array($part, $acceptedTags)) {
global $$part;
return isset($$part) ? $$part : '$' . $part;
}
return $part; // Keep the part unchanged if it's not in the accepted list
}, $parts);

$placeholder = $placeholderPrefix . $counter++;
$placeholders[$placeholder] = '[' . implode('', $result) . ']';
return $placeholder;
}, $emailTemplateTags);

// Perform variable substitution for single-bracketed tags [this]
$emailTemplateTags = preg_replace_callback('/\[(.*?)\]/', function($matches) use ($acceptedTags) {
// Ensure the match is not double-bracketed
if (strpos($matches[0], '[[') === false && strpos($matches[0], ']]') === false) {
$var_name = $matches[1];
if (in_array($var_name, $acceptedTags)) {
global $$var_name;
return isset($$var_name) ? $$var_name : $matches[0];
}
}
return $matches[0]; // Return the match unchanged if it is double-bracketed or not in the accepted list
}, $emailTemplateTags);

// Replace placeholders with actual double-bracketed replacements
foreach ($placeholders as $placeholder => $replacement) {
$emailTemplateTags = str_replace($placeholder, $replacement, $emailTemplateTags);
}

// Replace single quotes with escaped quotes
$emailTemplateTags = str_replace("'", "\'", $emailTemplateTags);

return $emailTemplateTags;
}



// Prepare Email Template
function prepareEmailTemplate($emailtemplate, $ticketreply = false)
{
// Check if $ticketreply is true, then prepend the line
if ($ticketreply) {
$prependText = "<em style=\"color: #808080; font-size: 12pt; font-family: arial;\">##- Please type your reply above this line -##</em>\n<br><br>";
$emailtemplate = $prependText . $emailtemplate;
}

// Decode HTML entities
$emailtemplate = htmlspecialchars_decode($emailtemplate);

// Email Template [tag] replacement
$emailtemplate = prepareEmailTemplateTags($emailtemplate);

return $emailtemplate;
}


function timeAgo($datetime)
{
$time = strtotime($datetime);
Expand Down
31 changes: 31 additions & 0 deletions get_settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,37 @@
$config_imap_username = $row['config_imap_username'];
$config_imap_password = $row['config_imap_password'];

// Mail - Email Templates
$email_template_keys = [
'config_et_client_ticket_new', 'config_et_client_ticket_update', 'config_et_client_ticket_autoclose',
'config_et_client_ticket_updatedpendingclosure', 'config_et_client_ticket_closed', 'config_et_client_app_newaccount',
'config_et_client_app_passwordreset', 'config_et_client_app_passwordresetcomplete', 'config_et_client_calendar_rescheduled',
'config_et_client_calendar_scheduled', 'config_et_client_invoice_new', 'config_et_client_invoice_newrecurring',
'config_et_client_invoice_paid', 'config_et_client_invoice_paymentfull', 'config_et_client_invoice_paymentmultiple',
'config_et_client_invoice_paymentpartial', 'config_et_client_invoice_paymentreminder', 'config_et_client_invoice_paymentstripe',
'config_et_client_quote_new', 'config_et_client_securelink', 'config_et_watcher_notify'
];

foreach ($email_template_keys as $key) {
${$key} = $row[$key];
}

// Mail - Email Template Subjects
$email_subject_keys = [
'config_et_client_ticket_new_subj', 'config_et_client_ticket_update_subj', 'config_et_client_ticket_autoclose_subj',
'config_et_client_ticket_updatedpendingclosure_subj', 'config_et_client_ticket_closed_subj', 'config_et_client_app_newaccount_subj',
'config_et_client_app_passwordreset_subj', 'config_et_client_app_passwordresetcomplete_subj', 'config_et_client_calendar_rescheduled_subj',
'config_et_client_calendar_scheduled_subj', 'config_et_client_invoice_new_subj', 'config_et_client_invoice_newrecurring_subj',
'config_et_client_invoice_paid_subj', 'config_et_client_invoice_paymentfull_subj', 'config_et_client_invoice_paymentmultiple_subj',
'config_et_client_invoice_paymentpartial_subj', 'config_et_client_invoice_paymentreminder_subj', 'config_et_client_invoice_paymentstripe_subj',
'config_et_client_quote_new_subj', 'config_et_client_securelink_subj', 'config_et_watcher_notify_subj'
];

foreach ($email_subject_keys as $key) {
${$key} = $row[$key];
}


// Defaults
$config_start_page = $row['config_start_page'];
$config_default_transfer_from_account = intval($row['config_default_transfer_from_account']);
Expand Down
8 changes: 6 additions & 2 deletions guest_pay_invoice_stripe.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,14 @@ function log_to_console($message) {
$config_invoice_from_email = sanitizeInput($row['config_invoice_from_email']);

$config_base_url = sanitizeInput($config_base_url);

// Get Email Template
$config_et_client_invoice_paymentstripe = prepareEmailTemplate($config_et_client_invoice_paymentstripe);
$config_et_client_invoice_paymentstripe_subj = prepareEmailTemplateTags($config_et_client_invoice_paymentstripe_subj);

if (!empty($config_smtp_host)) {
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>We have received your payment in the amount of " . $pi_currency . $pi_amount_paid . " for invoice <a href=\'https://$config_base_url/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount: " . numfmt_format_currency($currency_format, $pi_amount_paid, $invoice_currency_code) . "<br>Balance: " . numfmt_format_currency($currency_format, '0', $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>~<br>$company_name - Billing<br>$config_invoice_from_email<br>$company_phone";
$subject = "$config_et_client_invoice_paymentstripe_subj";
$body = "$config_et_client_invoice_paymentstripe";

$data = [
[
Expand Down
18 changes: 13 additions & 5 deletions portal/login_reset.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,13 @@
mysqli_query($mysqli, "UPDATE contacts SET contact_password_reset_token = '$token' WHERE contact_id = $id LIMIT 1");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Contact', log_action = 'Modify', log_description = 'Sent a portal password reset e-mail for $email.', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client");

// Get Email Template
$config_et_client_app_passwordreset = prepareEmailTemplate($config_et_client_app_passwordreset);
$config_et_client_app_passwordreset_subj = prepareEmailTemplateTags($config_et_client_app_passwordreset_subj);

// Send reset email
$subject = "Password reset for $company_name Client Portal";
$body = "Hello $name,<br><br>Someone (probably you) has requested a new password for your account on $company_name\'s Client Portal. <br><br><b>Please <a href=\'$url\'>click here</a> to reset your password.</b> <br><br>Alternatively, copy and paste this URL into your browser:<br> $url<br><br><i>If you didn\'t request this change, you can safely ignore this email.</i><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$subject = "$config_et_client_app_passwordreset_subj";
$body = "$config_et_client_app_passwordreset";

$data = [
[
Expand Down Expand Up @@ -130,10 +134,14 @@
$password = password_hash($_POST['new_password'], PASSWORD_DEFAULT);
mysqli_query($mysqli, "UPDATE contacts SET contact_password_hash = '$password', contact_password_reset_token = NULL WHERE contact_id = $contact_id LIMIT 1");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Contact', log_action = 'Modify', log_description = 'Reset portal password for $email.', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client");


// Get Email Template
$config_et_client_app_passwordresetcomplete = prepareEmailTemplate($config_et_client_app_passwordresetcomplete);
$config_et_client_app_passwordresetcomplete_subj = prepareEmailTemplateTags($config_et_client_app_passwordresetcomplete_subj);

// Send confirmation email
$subject = "Password reset confirmation for $company_name Client Portal";
$body = "Hello $name,<br><br>Your password for your account on $company_name\'s Client Portal was successfully reset. You should be all set! <br><br><b>If you didn\'t reset your password, please get in touch ASAP.</b><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$subject = "$config_et_client_app_passwordresetcomplete_subj";
$body = "$config_et_client_app_passwordresetcomplete";


$data = [
Expand Down
8 changes: 6 additions & 2 deletions post/contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,13 @@
} else {
$password_info = mysqli_real_escape_string($mysqli, $_POST['contact_password'] . " -- Please change on first login");
}

// Get Email Template
$config_et_client_app_newaccount = prepareEmailTemplate($config_et_client_app_newaccount);
$config_et_client_app_newaccount_subj = prepareEmailTemplateTags($config_et_client_app_newaccount_subj);

$subject = "Your new $company_name portal account";
$body = "Hello $name,<br><br>$company_name has created a support portal account for you. <br><br>Username: $email<br>Password: $password_info<br><br>Login URL: https://$config_base_url/portal/<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$subject = "$config_et_client_app_newaccount_subj";
$body = "$config_et_client_app_newaccount";

// Queue Mail
$data = [
Expand Down
Loading