diff --git a/cron_mail_queue.php b/cron_mail_queue.php index b084aae3..60005dac 100644 --- a/cron_mail_queue.php +++ b/cron_mail_queue.php @@ -3,6 +3,12 @@ require_once("config.php"); require_once("functions.php"); +//Initialize the HTML Purifier to prevent XSS +require("plugins/htmlpurifier/HTMLPurifier.standalone.php"); +$purifier_config = HTMLPurifier_Config::createDefault(); +$purifier_config->set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]); +$purifier = new HTMLPurifier($purifier_config); + $sql_settings = mysqli_query($mysqli, "SELECT * FROM settings WHERE company_id = 1"); $row = mysqli_fetch_array($sql_settings); @@ -42,10 +48,11 @@ if (mysqli_num_rows($sql_queue) > 0) { $email_recipient = nullable_htmlentities($row['email_recipient']); $email_recipient_name = nullable_htmlentities($row['email_recipient_name']); $email_subject = nullable_htmlentities($row['email_subject']); - $email_content = nullable_htmlentities($row['email_content']); + $email_content = $purifier->purify($row['email_content']); $email_queued_at = nullable_htmlentities($row['email_queued_at']); $email_sent_at = nullable_htmlentities($row['email_sent_at']); + // Sanitized Input $email_recipient_logging = sanitizeInput($row['email_recipient']); $email_subject_logging = sanitizeInput($row['email_subject']); @@ -97,12 +104,13 @@ if (mysqli_num_rows($sql_failed_queue) > 0) { $email_recipient = nullable_htmlentities($row['email_recipient']); $email_recipient_name = nullable_htmlentities($row['email_recipient_name']); $email_subject = nullable_htmlentities($row['email_subject']); - $email_content = nullable_htmlentities($row['email_content']); + $email_content = $purifier->purify($row['email_content']); $email_queued_at = nullable_htmlentities($row['email_queued_at']); $email_sent_at = nullable_htmlentities($row['email_sent_at']); // Increment the attempts $email_attempts = intval($row['email_attempts']) + 1; + // Sanitized Input $email_recipient_logging = sanitizeInput($row['email_recipient']); $email_subject_logging = sanitizeInput($row['email_subject']); diff --git a/post.php b/post.php index 8d921b32..348b5202 100644 --- a/post.php +++ b/post.php @@ -4058,6 +4058,7 @@ if(isset($_GET['email_invoice'])){ $client_id = $row['client_id']; $client_name = $row['client_name']; $contact_name = $row['contact_name']; + $contact_name_escaped = sanitizeInput($row['contact_name']); $contact_email = $row['contact_email']; $contact_email_escaped = sanitizeInput($row['contact_email']); $contact_phone = formatPhoneNumber($row['contact_phone']); @@ -4081,7 +4082,7 @@ if(isset($_GET['email_invoice'])){ $sql_payments = mysqli_query($mysqli,"SELECT * FROM payments, accounts WHERE payment_account_id = account_id AND payment_invoice_id = $invoice_id ORDER BY payment_id DESC"); - //Add up all the payments for the invoice and get the total amount paid to the invoice + // Add up all the payments for the invoice and get the total amount paid to the invoice $sql_amount_paid = mysqli_query($mysqli,"SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id"); $row = mysqli_fetch_array($sql_amount_paid); $amount_paid = floatval($row['amount_paid']); @@ -4089,58 +4090,51 @@ if(isset($_GET['email_invoice'])){ $balance = $invoice_amount - $amount_paid; if ($invoice_status == 'Paid') { - $subject = "Invoice $invoice_prefix$invoice_number Copy"; - $body = "Hello $contact_name,

Please click on the link below to see your invoice marked paid.

Invoice Link


~
$company_name
Billing Department
$config_invoice_from_email
$company_phone"; + $subject = sanitizeInput("Invoice $invoice_prefix$invoice_number Copy"); + $body = mysqli_real_escape_string($mysqli, "Hello $contact_name,

Please click on the link below to see your invoice marked paid.

Invoice Link


~
$company_name
Billing Department
$config_invoice_from_email
$company_phone"); } else { - $subject = "Invoice $invoice_prefix$invoice_number"; - $body = "Hello $contact_name,

Please view the details of the invoice below.

Invoice: $invoice_prefix$invoice_number
Issue Date: $invoice_date
Total: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "
Balance Due: " . numfmt_format_currency($currency_format, $balance, $invoice_currency_code) . "
Due Date: $invoice_due


To view your invoice click here


~
$company_name
Billing Department
$config_invoice_from_email
$company_phone"; + $subject = sanitizeInput("Invoice $invoice_prefix$invoice_number"); + $body = mysqli_real_escape_string($mysqli, "Hello $contact_name,

Please view the details of the invoice below.

Invoice: $invoice_prefix$invoice_number
Issue Date: $invoice_date
Total: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "
Balance Due: " . numfmt_format_currency($currency_format, $balance, $invoice_currency_code) . "
Due Date: $invoice_due


To view your invoice click here


~
$company_name
Billing Department
$config_invoice_from_email
$company_phone"); } - $mail = sendSingleEmail($config_smtp_host, $config_smtp_username, $config_smtp_password, $config_smtp_encryption, $config_smtp_port, - $config_invoice_from_email, $config_invoice_from_name, - $contact_email, $contact_name, - $subject, $body); + // Queue Mail + mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$contact_email_escaped', email_recipient_name = '$contact_name_escaped', email_from = '$config_invoice_from_email', email_from_name = '$config_invoice_from_name', email_subject = '$subject', email_content = '$body'"); - if ($mail === true) { - $_SESSION['alert_message'] = "Invoice has been sent"; - mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Emailed invoice', history_invoice_id = $invoice_id"); + // Get Email ID for reference + $email_id = mysqli_insert_id($mysqli); - //Don't change the status to sent if the status is anything but draft - if($invoice_status == 'Draft'){ - mysqli_query($mysqli,"UPDATE invoices SET invoice_status = 'Sent' WHERE invoice_id = $invoice_id"); - } + $_SESSION['alert_message'] = "Invoice has been sent to the mail queue"; + mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Queued', history_description = 'Invoice sent to the mail queue ID: $email_id', history_invoice_id = $invoice_id"); - //Logging - mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Invoice', log_action = 'Email', log_description = 'Invoice $invoice_prefix$invoice_number emailed to $contact_email_escaped', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_client_id = $client_id, log_user_id = $session_user_id, log_entity_id = $invoice_id"); - - } else { - $_SESSION['alert_type'] = "error"; - $_SESSION['alert_message'] = "Invoice Failed to send "; - mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Email Invoice Failed', history_invoice_id = $invoice_id"); - - mysqli_query($mysqli,"INSERT INTO notifications SET notification_type = 'Mail', notification = 'Failed to send email to $contact_email_escaped', notification_client_id = $client_id,"); - mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Mail', log_action = 'Error', log_description = 'Failed to send email to $contact_email_escaped regarding $subject. $mail', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_client_id = $client_id, log_user_id = $session_user_id, log_entity_id = $invoice_id"); + // Don't change the status to sent if the status is anything but draft + if($invoice_status == 'Draft'){ + mysqli_query($mysqli,"UPDATE invoices SET invoice_status = 'Sent' WHERE invoice_id = $invoice_id"); } + // Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Invoice', log_action = 'Email Queue', log_description = 'Invoice $invoice_prefix$invoice_number queued to $contact_email_escaped Email ID: $email_id', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_client_id = $client_id, log_user_id = $session_user_id, log_entity_id = $invoice_id"); + // Send copies of the invoice to any additional billing contacts $sql_billing_contacts = mysqli_query( $mysqli, "SELECT contact_name, contact_email FROM contacts WHERE contact_billing = 1 AND contact_email != '$contact_email_escaped' + AND contact_email != '' AND contact_client_id = $client_id" ); while ($billing_contact = mysqli_fetch_array($sql_billing_contacts)) { - $billing_contact_name = $billing_contact['contact_name']; - $billing_contact_email = $billing_contact['contact_email']; + $billing_contact_name = sanitizeInput($billing_contact['contact_name']); + $billing_contact_email = sanitizeInput($billing_contact['contact_email']); + + // Queue Mail + mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$billing_contact_email', email_recipient_name = '$billing_contact_name', email_from = '$config_invoice_from_email', email_from_name = '$config_invoice_from_name', email_subject = '$subject', email_content = '$body'"); + + // Get Email ID for reference + $email_id = mysqli_insert_id($mysqli); - sendSingleEmail($config_smtp_host, $config_smtp_username, $config_smtp_password, $config_smtp_encryption, $config_smtp_port, - $config_invoice_from_email, $config_invoice_from_name, - $billing_contact_email, $billing_contact_name, - $subject, $body); } - header("Location: " . $_SERVER["HTTP_REFERER"]); } diff --git a/settings_mail_queue.php b/settings_mail_queue.php new file mode 100644 index 00000000..3e329b46 --- /dev/null +++ b/settings_mail_queue.php @@ -0,0 +1,162 @@ +set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]); +$purifier = new HTMLPurifier($purifier_config); + +//Rebuild URL +$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o))); + +$sql = mysqli_query( + $mysqli, + "SELECT SQL_CALC_FOUND_ROWS * FROM email_queue + WHERE (email_from LIKE '%$q%' OR email_from_name LIKE '%$q%' OR email_recipient LIKE '%$q%' OR email_recipient_name LIKE '%$q%' OR email_subject LIKE '%$q%') + AND DATE(email_queued_at) BETWEEN '$dtf' AND '$dtt' + ORDER BY $sb $o LIMIT $record_from, $record_to" +); + +$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); + +?> + +
+
+

Email Queue

+
+
+
+
+
+
+ +
+ + +
+
+
+
+
" id="advancedFilter"> +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+
+ + "> + + + + + + + + + + + + purify($row['email_content']); + $email_attempts = intval($row['email_attempts']); + $email_queued_at = nullable_htmlentities($row['email_queued_at']); + $email_failed_at = nullable_htmlentities($row['email_failed_at']); + $email_sent_at = nullable_htmlentities($row['email_sent_at']); + $email_status = intval($row['email_status']); + if($email_status == 0){ + $email_status_display = "
Queued
"; + }elseif($email_status == 1){ + $email_status_display = "
Sending
"; + }elseif($email_status_display == 2){ + $email_status_display = "
Failed
$email_failed_at"; + }else{ + $email_status_display = "
Sent
$email_sent_at"; + } + + ?> + + + + + + + + + + + + + + + + +
QueuedFromToSubjectStatusAttemptsAction
$email_from_name"?>$email_recipient_name"?> + +
+
+ +
+
+ + + +