function zen_mail($to_name, $to_address, $email_subject, $email_text, $from_email_name, $from_email_address, $block = array(), $module = 'default', $attachments_list = '') { global $db, $messageStack; if (SEND_EMAILS != 'true') { return false; } // if sending email is disabled in Admin, just exit if (!zen_not_null($email_text) && !zen_not_null($block['EMAIL_MESSAGE_HTML'])) { return false; } // if no text or html-msg supplied, exit // Parse "from" addresses for "name" <*****@*****.**> structure, and supply name/address info from it. if (eregi(" *([^<]*) *<([^>]*)> *", $from_email_address, $regs)) { $from_email_name = trim($regs[1]); $from_email_address = $regs[2]; } // if email name is same as email address, use the Store Name as the senders 'Name' if ($from_email_name == $from_email_address) { $from_email_name = STORE_NAME; } // loop thru multiple email recipients if more than one listed --- (esp for the admin's "Extra" emails)... foreach (explode(',', $to_address) as $key => $value) { if (eregi(" *([^<]*) *<([^>]*)> *", $value, $regs)) { $to_name = str_replace('"', '', trim($regs[1])); $to_email_address = $regs[2]; } elseif (eregi(" *([^ ]*) *", $value, $regs)) { $to_email_address = trim($regs[1]); } if (!isset($to_email_address)) { $to_email_address = $to_address; } //if not more than one, just use the main one. //define some additional html message blocks available to templates, then build the html portion. if ($block['EMAIL_TO_NAME'] == '') { $block['EMAIL_TO_NAME'] = $to_name; } if ($block['EMAIL_TO_ADDRESS'] == '') { $block['EMAIL_TO_ADDRESS'] = $to_email_address; } if ($block['EMAIL_SUBJECT'] == '') { $block['EMAIL_SUBJECT'] = $email_subject; } if ($block['EMAIL_FROM_NAME'] == '') { $block['EMAIL_FROM_NAME'] = $from_email_name; } if ($block['EMAIL_FROM_ADDRESS'] == '') { $block['EMAIL_FROM_ADDRESS'] = $from_email_address; } $email_html = zen_build_html_email_from_template($module, $block); // if ($attachments_list == '') $attachments_list= array(); // Instantiate a new mail object $message = new email(array('X-Mailer: Zen Cart Mailer')); // bof: body of the email clean-up // clean up & and && from email text while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } while (strstr($email_text, '&')) { $email_text = str_replace('&', '&', $email_text); } while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } // clean up money € to e while (strstr($email_text, '€')) { $email_text = str_replace('€', 'e', $email_text); } // fix double quotes while (strstr($email_text, '"')) { $email_text = str_replace('"', '"', $email_text); } // fix slashes $email_text = stripslashes($email_text); $email_html = stripslashes($email_html); // eof: body of the email clean-up //determine customer's email preference type: HTML or TEXT-ONLY (HTML assumed if not specified) $customers_email_format_read = $db->Execute("select customers_email_format from " . TABLE_CUSTOMERS . " where customers_email_address= '" . $to_email_address . "'"); $customers_email_format = $customers_email_format_read->fields['customers_email_format']; if ($customers_email_format == 'NONE' || $customers_email_format == 'OUT') { return; } //if requested no mail, then don't send. if ($customers_email_format == 'HTML') { $customers_email_format = 'HTML'; } // if they opted-in to HTML messages, then send HTML format //determine what format to send messages in if this is an "extra"/admin-copy email: if (ADMIN_EXTRA_EMAIL_FORMAT == 'TEXT' && substr($module, -6) == '_extra') { $email_html = ''; // just blank out the html portion if admin has selected text-only } // Build the email based on whether customer has selected HTML or TEXT, and whether we have supplied HTML or TEXT-only components if (!zen_not_null($email_text)) { $text = str_replace('<br[[:space:]]*/?[[:space:]]*>', "@CRLF", $block['EMAIL_MESSAGE_HTML']); $text = str_replace('</p>', '</p>@CRLF', $text); $text = htmlspecialchars(stripslashes(strip_tags($text))); } else { $text = strip_tags($email_text); } if (EMAIL_USE_HTML == 'true' && trim($email_html) != '' && ($customers_email_format == 'HTML' || ADMIN_EXTRA_EMAIL_FORMAT != 'TEXT' && substr($module, -6) == '_extra')) { $message->add_html($email_html, $text); } else { $message->add_text($text); $email_html = ''; // since sending a text-only message, empty the HTML portion so it's not archived either. } // process attachments if (EMAIL_ATTACHMENTS_ENABLED && zen_not_null($attachments_list)) { // while ( list($key, $value) = each($attachments_list)) { $fileraw = $message->get_file(DIR_FS_ADMIN . 'attachments/' . $attachments_list['file']); $filemime = zen_not_null($attachments_list['file_type']) ? $attachments_list['file_type'] : $message->findMime($attachments_list); //findMime determines what type this attachment is (XLS, PDF, etc) and sends proper vendor c_type. $message->add_attachment($fileraw, $attachments_list['file'], $filemime); // } //endwhile attach_list } //endif attachments // Prepare message $message->build_message(); // send the actual email $result = $message->send($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject); if (!$result) { $messageStack->add(sprintf(EMAIL_SEND_FAILED, $to_name, $to_email_address, $email_subject), 'error'); } // Archive this message to storage log if (EMAIL_ARCHIVE == 'true' && $module != 'password_forgotten_admin' && $module != 'cc_middle_digs') { // don't archive pwd-resets and CC numbers zen_mail_archive_write($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $module); } // endif archiving } // end foreach loop thru possible multiple email addresses }
/** * Send email (text/html) using MIME. This is the central mail function. * If using "PHP" transport method, the SMTP Server or other mail application should be configured correctly in server's php.ini * * @param string $to_name The name of the recipient, e.g. "Jim Johanssen" * @param string $to_email_address The email address of the recipient, e.g. john.smith@hzq.com * @param string $email_subject The subject of the eMail * @param string $email_text The text of the email, may contain HTML entities * @param string $from_email_name The name of the sender, e.g. Shop Administration * @param string $from_email_adrdess The email address of the sender, e.g. info@myzenshop.com * @param array $block Array containing values to be inserted into HTML-based email template * @param string $module The module name of the routine calling zen_mail. Used for HTML template selection and email archiving. * This is passed to the archive function denoting what module initiated the sending of the email * @param array $attachments_list Array of attachment names/mime-types to be included (this portion still in testing, and not fully reliable) **/ function zen_mail($to_name, $to_address, $email_subject, $email_text, $from_email_name, $from_email_address, $block = array(), $module = 'default', $attachments_list = '') { global $db, $messageStack, $zco_notifier; if (!defined('DEVELOPER_OVERRIDE_EMAIL_STATUS') || defined('DEVELOPER_OVERRIDE_EMAIL_STATUS') && DEVELOPER_OVERRIDE_EMAIL_STATUS == 'site') { if (SEND_EMAILS != 'true') { return false; } } // if sending email is disabled in Admin, just exit if (defined('DEVELOPER_OVERRIDE_EMAIL_ADDRESS') && DEVELOPER_OVERRIDE_EMAIL_ADDRESS != '') { $to_address = DEVELOPER_OVERRIDE_EMAIL_ADDRESS; } // ignore sending emails for any of the following pages // (The EMAIL_MODULES_TO_SKIP constant can be defined in a new file in the "extra_configures" folder) if (defined('EMAIL_MODULES_TO_SKIP') && in_array($module, explode(",", constant('EMAIL_MODULES_TO_SKIP')))) { return false; } // check for injection attempts. If new-line characters found in header fields, simply fail to send the message foreach (array($from_email_address, $to_address, $from_email_name, $to_name, $email_subject) as $key => $value) { if (eregi("\r", $value) || eregi("\n", $value)) { return false; } } // if no text or html-msg supplied, exit if (trim($email_text) == '' && (!zen_not_null($block) || isset($block['EMAIL_MESSAGE_HTML']) && $block['EMAIL_MESSAGE_HTML'] == '')) { return false; } // Parse "from" addresses for "name" <*****@*****.**> structure, and supply name/address info from it. if (eregi(" *([^<]*) *<([^>]*)> *", $from_email_address, $regs)) { $from_email_name = trim($regs[1]); $from_email_address = $regs[2]; } // if email name is same as email address, use the Store Name as the senders 'Name' if ($from_email_name == $from_email_address) { $from_email_name = STORE_NAME; } // loop thru multiple email recipients if more than one listed --- (esp for the admin's "Extra" emails)... foreach (explode(',', $to_address) as $key => $value) { if (eregi(" *([^<]*) *<([^>]*)> *", $value, $regs)) { $to_name = str_replace('"', '', trim($regs[1])); $to_email_address = $regs[2]; } elseif (eregi(" *([^ ]*) *", $value, $regs)) { $to_email_address = trim($regs[1]); } if (!isset($to_email_address)) { $to_email_address = $to_address; } //if not more than one, just use the main one. //define some additional html message blocks available to templates, then build the html portion. if ($block['EMAIL_TO_NAME'] == '') { $block['EMAIL_TO_NAME'] = $to_name; } if ($block['EMAIL_TO_ADDRESS'] == '') { $block['EMAIL_TO_ADDRESS'] = $to_email_address; } if ($block['EMAIL_SUBJECT'] == '') { $block['EMAIL_SUBJECT'] = $email_subject; } if ($block['EMAIL_FROM_NAME'] == '') { $block['EMAIL_FROM_NAME'] = $from_email_name; } if ($block['EMAIL_FROM_ADDRESS'] == '') { $block['EMAIL_FROM_ADDRESS'] = $from_email_address; } $email_html = zen_build_html_email_from_template($module, $block); if (!is_array($block) && $block == '' || $block == 'none') { $email_html = ''; } // Build the email based on whether customer has selected HTML or TEXT, and whether we have supplied HTML or TEXT-only components // special handling for XML content if ($email_text == '') { $email_text = str_replace(array('<br>', '<br />'), "<br />\n", $block['EMAIL_MESSAGE_HTML']); $email_text = str_replace('</p>', "</p>\n", $email_text); $email_text = $module != 'xml_record' ? htmlspecialchars(stripslashes(strip_tags($email_text))) : $email_text; } else { $email_text = $module != 'xml_record' ? strip_tags($email_text) : $email_text; } if ($module != 'xml_record') { if (!strstr($email_text, sprintf(EMAIL_DISCLAIMER, STORE_OWNER_EMAIL_ADDRESS)) && $to_email_address != STORE_OWNER_EMAIL_ADDRESS && !defined('EMAIL_DISCLAIMER_NEW_CUSTOMER')) { $email_text .= "\n" . sprintf(EMAIL_DISCLAIMER, STORE_OWNER_EMAIL_ADDRESS); } if (!strstr($email_text, EMAIL_SPAM_DISCLAIMER) && $to_email_address != STORE_OWNER_EMAIL_ADDRESS) { $email_text .= "\n" . EMAIL_SPAM_DISCLAIMER; } } // bof: body of the email clean-up // clean up & and && from email text while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } while (strstr($email_text, '&')) { $email_text = str_replace('&', '&', $email_text); } while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } // clean up currencies for text emails $zen_fix_currencies = split("[:,]", CURRENCIES_TRANSLATIONS); $size = sizeof($zen_fix_currencies); for ($i = 0, $n = $size; $i < $n; $i += 2) { $zen_fix_current = $zen_fix_currencies[$i]; $zen_fix_replace = $zen_fix_currencies[$i + 1]; if (strlen($zen_fix_current) > 0) { while (strpos($email_text, $zen_fix_current)) { $email_text = str_replace($zen_fix_current, $zen_fix_replace, $email_text); } } } // fix double quotes while (strstr($email_text, '"')) { $email_text = str_replace('"', '"', $email_text); } // prevent null characters while (strstr($email_text, chr(0))) { $email_text = str_replace(chr(0), ' ', $email_text); } // fix slashes $text = stripslashes($email_text); $email_html = stripslashes($email_html); // eof: body of the email clean-up //determine customer's email preference type: HTML or TEXT-ONLY (HTML assumed if not specified) $sql = "select customers_email_format from " . TABLE_CUSTOMERS . " where customers_email_address= :custEmailAddress:"; $sql = $db->bindVars($sql, ':custEmailAddress:', $to_email_address, 'string'); $result = $db->Execute($sql); $customers_email_format = $result->RecordCount() > 0 ? $result->fields['customers_email_format'] : ''; if ($customers_email_format == 'NONE' || $customers_email_format == 'OUT') { return; } //if requested no mail, then don't send. // if ($customers_email_format == 'HTML') $customers_email_format = 'HTML'; // if they opted-in to HTML messages, then send HTML format // handling admin/"extra"/copy emails: if (ADMIN_EXTRA_EMAIL_FORMAT == 'TEXT' && substr($module, -6) == '_extra') { $email_html = ''; // just blank out the html portion if admin has selected text-only } //determine what format to send messages in if this is an admin email for newsletters: if ($customers_email_format == '' && ADMIN_EXTRA_EMAIL_FORMAT == 'HTML' && in_array($module, array('newsletters', 'product_notification')) && isset($_SESSION['admin_id'])) { $customers_email_format = 'HTML'; } // special handling for XML content if ($module == 'xml_record') { $email_html = ''; $customers_email_format == 'TEXT'; } //notifier intercept option $zco_notifier->notify('NOTIFY_EMAIL_AFTER_EMAIL_FORMAT_DETERMINED'); // now lets build the mail object with the phpmailer class $mail =& new PHPMailer(); $lang_code = strtolower($_SESSION['languages_code'] == '' ? 'en' : $_SESSION['languages_code']); $mail->SetLanguage($lang_code, DIR_FS_CATALOG . DIR_WS_CLASSES . 'support/'); $mail->CharSet = defined('CHARSET') ? CHARSET : "iso-8859-1"; $mail->Encoding = defined('EMAIL_ENCODING_METHOD') ? EMAIL_ENCODING_METHOD : "7bit"; if ((int) EMAIL_SYSTEM_DEBUG > 0) { $mail->SMTPDebug = (int) EMAIL_SYSTEM_DEBUG; } $mail->WordWrap = 76; // set word wrap to 76 characters // set proper line-endings based on switch ... important for windows vs linux hosts: $mail->LE = EMAIL_LINEFEED == 'CRLF' ? "\r\n" : "\n"; switch (EMAIL_TRANSPORT) { case 'smtp': $mail->IsSMTP(); $mail->Host = trim(EMAIL_SMTPAUTH_MAIL_SERVER); if (EMAIL_SMTPAUTH_MAIL_SERVER_PORT != '25' && EMAIL_SMTPAUTH_MAIL_SERVER_PORT != '') { $mail->Port = trim(EMAIL_SMTPAUTH_MAIL_SERVER_PORT); } $mail->LE = "\r\n"; break; case 'smtpauth': $mail->IsSMTP(); $mail->SMTPAuth = true; $mail->Username = zen_not_null(EMAIL_SMTPAUTH_MAILBOX) ? trim(EMAIL_SMTPAUTH_MAILBOX) : EMAIL_FROM; $mail->Password = trim(EMAIL_SMTPAUTH_PASSWORD); $mail->Host = trim(EMAIL_SMTPAUTH_MAIL_SERVER); if (EMAIL_SMTPAUTH_MAIL_SERVER_PORT != '25' && EMAIL_SMTPAUTH_MAIL_SERVER_PORT != '') { $mail->Port = trim(EMAIL_SMTPAUTH_MAIL_SERVER_PORT); } $mail->LE = "\r\n"; //set encryption protocol to allow support for Gmail if (EMAIL_SMTPAUTH_MAIL_SERVER_PORT == '465' && EMAIL_SMTPAUTH_MAIL_SERVER == 'smtp.gmail.com') { $mail->Protocol = 'ssl'; } if (defined('SMTPAUTH_EMAIL_PROTOCOL') && SMTPAUTH_EMAIL_PROTOCOL != 'none') { $mail->Protocol = SMTPAUTH_EMAIL_PROTOCOL; if (SMTPAUTH_EMAIL_PROTOCOL == 'starttls') { $mail->Starttls = true; $mail->Context = $Email_Certificate_Context; } } break; case 'PHP': $mail->IsMail(); break; case 'Qmail': $mail->IsQmail(); break; case 'sendmail': case 'sendmail-f': $mail->LE = "\n"; default: $mail->IsSendmail(); if (defined('EMAIL_SENDMAIL_PATH')) { $mail->Sendmail = trim(EMAIL_SENDMAIL_PATH); } break; } $mail->Subject = $email_subject; $mail->From = $from_email_address; $mail->FromName = $from_email_name; $mail->AddAddress($to_email_address, $to_name); // $mail->AddAddress($to_email_address); // (alternate format if no name, since name is optional) // set the reply-to address. If none set yet, then use Store's default email name/address. // If sending from contact-us or tell-a-friend page, use the supplied info $email_reply_to_address = $email_reply_to_address ? $email_reply_to_address : (in_array($module, array('contact_us', 'tell_a_friend')) ? $from_email_address : EMAIL_FROM); $email_reply_to_name = $email_reply_to_name ? $email_reply_to_name : (in_array($module, array('contact_us', 'tell_a_friend')) ? $from_email_name : STORE_NAME); $mail->AddReplyTo($email_reply_to_address, $email_reply_to_name); // if mailserver requires that all outgoing mail must go "from" an email address matching domain on server, set it to store address if (EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->From = EMAIL_FROM; } if (EMAIL_TRANSPORT == 'sendmail-f' || EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->Sender = EMAIL_FROM; } // PROCESS FILE ATTACHMENTS if ($attachments_list == '') { $attachments_list = array(); } if (is_string($attachments_list)) { if (file_exists($attachments_list)) { $attachments_list = array(array('file' => $attachments_list)); } elseif (file_exists(DIR_FS_CATALOG . $attachments_list)) { $attachments_list = array(array('file' => DIR_FS_CATALOG . $attachments_list)); } else { $attachments_list = array(); } } $zco_notifier->notify('NOTIFY_EMAIL_BEFORE_PROCESS_ATTACHMENTS', $attachments_list); if (defined('EMAIL_ATTACHMENTS_ENABLED') && EMAIL_ATTACHMENTS_ENABLED && is_array($attachments_list) && sizeof($attachments_list) > 0) { foreach ($attachments_list as $key => $val) { $fname = isset($val['name']) ? $val['name'] : null; $mimeType = isset($val['mime_type']) && $val['mime_type'] != '' && $val['mime_type'] != 'application/octet-stream' ? $val['mime_type'] : ''; switch (true) { case isset($val['raw_data']) && $val['raw_data'] != '': $fdata = $val['raw_data']; if ($mimeType != '') { $mail->AddStringAttachment($fdata, $fname, "base64", $mimeType); } else { $mail->AddStringAttachment($fdata, $fname); } break; case file_exists($val['file']): //'file' portion must contain the full path to the file to be attached $fdata = $val['file']; if ($mimeType != '') { $mail->AddAttachment($fdata, $fname, "base64", $mimeType); } else { $mail->AddAttachment($fdata, $fname); } break; } // end switch } //end foreach attachments_list } //endif attachments_enabled $zco_notifier->notify('NOTIFY_EMAIL_AFTER_PROCESS_ATTACHMENTS', sizeof($attachments_list)); // prepare content sections: if (EMAIL_USE_HTML == 'true' && trim($email_html) != '' && ($customers_email_format == 'HTML' || ADMIN_EXTRA_EMAIL_FORMAT != 'TEXT' && substr($module, -6) == '_extra')) { $mail->IsHTML(true); // set email format to HTML $mail->Body = $email_html; // HTML-content of message $mail->AltBody = $text; // text-only content of message } else { // use only text portion if not HTML-formatted $mail->Body = $text; // text-only content of message } /** * Send the email. If an error occurs, trap it and display it in the messageStack */ $ErrorInfo = ''; $zco_notifier->notify('NOTIFY_EMAIL_READY_TO_SEND'); if (!($result = $mail->Send())) { if (IS_ADMIN_FLAG === true) { $messageStack->add_session(sprintf(EMAIL_SEND_FAILED . ' ' . $mail->ErrorInfo, $to_name, $to_email_address, $email_subject), 'error'); } else { $messageStack->add('header', sprintf(EMAIL_SEND_FAILED . ' ' . $mail->ErrorInfo, $to_name, $to_email_address, $email_subject), 'error'); } $ErrorInfo .= $mail->ErrorInfo . '<br />'; } $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND'); // Archive this message to storage log // don't archive pwd-resets and CC numbers if (EMAIL_ARCHIVE == 'true' && $module != 'password_forgotten_admin' && $module != 'cc_middle_digs' && $module != 'no_archive') { zen_mail_archive_write($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $module, $ErrorInfo); } // endif archiving } // end foreach loop thru possible multiple email addresses $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND_ALL_SPECIFIED_ADDRESSES'); if (EMAIL_FRIENDLY_ERRORS == 'false' && $ErrorInfo != '') { die('<br /><br />Email Error: ' . $ErrorInfo); } return $ErrorInfo; }
function jsend_mail($to_name, $to_address, $email_subject, $email_text, $from_email_name, $from_email_address, $block = array(), $attachments_list = '') { global $db, $messageStack, $zco_notifier; foreach (array($from_email_address, $to_address, $from_email_name, $to_name, $email_subject) as $key => $value) { if (preg_match("/\r/i", $value) || preg_match("/\n/i", $value)) { return false; } } // if no text or html-msg supplied, exit if (trim($email_text) == '') { return false; } // Parse "from" addresses for "name" <*****@*****.**> structure, and supply name/address info from it. if (preg_match("/ *([^<]*) *<([^>]*)> */i", $from_email_address, $regs)) { $from_email_name = trim($regs[1]); $from_email_address = $regs[2]; } // if email name is same as email address, use the Store Name as the senders 'Name' if ($from_email_name == $from_email_address) { $from_email_name = STORE_NAME; } // loop thru multiple email recipients if more than one listed --- (esp for the admin's "Extra" emails)... foreach (explode(',', $to_address) as $key => $value) { if (preg_match("/ *([^<]*) *<([^>]*)> */i", $value, $regs)) { $to_name = str_replace('"', '', trim($regs[1])); $to_email_address = $regs[2]; } elseif (preg_match("/ *([^ ]*) */i", $value, $regs)) { $to_email_address = trim($regs[1]); } if (!isset($to_email_address)) { $to_email_address = trim($to_address); } // if not more than one, just use the main one. // ensure the address is valid, to prevent unnecessary delivery failures if (!zen_validate_email($to_email_address)) { @error_log(sprintf(EMAIL_SEND_FAILED . ' (failed validation)', $to_name, $to_email_address, $email_subject)); continue; } // define some additional html message blocks available to templates, then build the html portion. if (!isset($block['EMAIL_TO_NAME']) || $block['EMAIL_TO_NAME'] == '') { $block['EMAIL_TO_NAME'] = $to_name; } if (!isset($block['EMAIL_TO_ADDRESS']) || $block['EMAIL_TO_ADDRESS'] == '') { $block['EMAIL_TO_ADDRESS'] = $to_email_address; } if (!isset($block['EMAIL_SUBJECT']) || $block['EMAIL_SUBJECT'] == '') { $block['EMAIL_SUBJECT'] = $email_subject; } if (!isset($block['EMAIL_FROM_NAME']) || $block['EMAIL_FROM_NAME'] == '') { $block['EMAIL_FROM_NAME'] = $from_email_name; } if (!isset($block['EMAIL_FROM_ADDRESS']) || $block['EMAIL_FROM_ADDRESS'] == '') { $block['EMAIL_FROM_ADDRESS'] = $from_email_address; } if (!is_array($block) && $block == '' || $block == 'none') { $email_html = ''; } $email_text = strip_tags($email_text); // bof: body of the email clean-up // clean up & and && from email text while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } while (strstr($email_text, '&')) { $email_text = str_replace('&', '&', $email_text); } while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } // clean up currencies for text emails $zen_fix_currencies = preg_split("/[:,]/", CURRENCIES_TRANSLATIONS); $size = sizeof($zen_fix_currencies); for ($i = 0, $n = $size; $i < $n; $i += 2) { $zen_fix_current = $zen_fix_currencies[$i]; $zen_fix_replace = $zen_fix_currencies[$i + 1]; if (strlen($zen_fix_current) > 0) { while (strpos($email_text, $zen_fix_current)) { $email_text = str_replace($zen_fix_current, $zen_fix_replace, $email_text); } } } // fix double quotes while (strstr($email_text, '"')) { $email_text = str_replace('"', '"', $email_text); } // prevent null characters while (strstr($email_text, chr(0))) { $email_text = str_replace(chr(0), ' ', $email_text); } // fix slashes $text = stripslashes($email_text); $email_html = stripslashes($email_html); $mail = new PHPMailer(); $lang_code = strtolower($_SESSION['languages_code'] == '' ? 'en' : $_SESSION['languages_code']); $mail->SetLanguage($lang_code, DIR_FS_CATALOG . DIR_WS_CLASSES . 'support/'); $mail->CharSet = defined('CHARSET') ? CHARSET : "iso-8859-1"; $mail->Encoding = defined('EMAIL_ENCODING_METHOD') ? EMAIL_ENCODING_METHOD : "7bit"; if ((int) EMAIL_SYSTEM_DEBUG > 0) { $mail->SMTPDebug = (int) EMAIL_SYSTEM_DEBUG; } $mail->WordWrap = 76; // set word wrap to 76 characters // set proper line-endings based on switch ... important for windows vs linux hosts: $mail->LE = EMAIL_LINEFEED == 'CRLF' ? "\r\n" : "\n"; switch (EMAIL_TRANSPORT) { case 'smtp': $mail->IsSMTP(); $mail->Host = trim($block['smtp_addr']); if ($block['smtp_port'] != '25' && $block['smtp_port'] != '') { $mail->Port = trim($block['smtp_port']); } $mail->LE = "\r\n"; break; case 'smtpauth': $mail->IsSMTP(); $mail->SMTPAuth = true; $mail->Username = zen_not_null($block['smtp_user']) ? trim($block['smtp_user']) : EMAIL_FROM; $mail->Password = trim($block['smtp_pwd']); $mail->Host = trim($block['smtp_addr']); if ($block['smtp_port'] != '25' && $block['smtp_port'] != '') { $mail->Port = trim($block['smtp_port']); } $mail->LE = "\r\n"; // set encryption protocol to allow support for Gmail or other secured email protocols if ($block['smtp_port'] == '465' || $block['smtp_port'] == '587' || $block['smtp_addr'] == 'smtp.gmail.com') { $mail->Protocol = 'ssl'; } if (defined('SMTPAUTH_EMAIL_PROTOCOL') && SMTPAUTH_EMAIL_PROTOCOL != 'none') { $mail->Protocol = SMTPAUTH_EMAIL_PROTOCOL; if (SMTPAUTH_EMAIL_PROTOCOL == 'starttls' && defined('SMTPAUTH_EMAIL_CERTIFICATE_CONTEXT')) { $mail->Starttls = true; $mail->Context = SMTPAUTH_EMAIL_CERTIFICATE_CONTEXT; } } break; case 'PHP': $mail->IsMail(); break; case 'Qmail': $mail->IsQmail(); break; case 'sendmail': case 'sendmail-f': $mail->LE = "\n"; default: $mail->IsSendmail(); if (defined('EMAIL_SENDMAIL_PATH')) { $mail->Sendmail = trim(EMAIL_SENDMAIL_PATH); } break; } $mail->Subject = $email_subject; $mail->From = $from_email_address; $mail->FromName = $from_email_name; $mail->AddAddress($to_email_address, $to_name); // $mail->AddAddress($to_email_address); // (alternate format if no name, since name is optional) // $mail->AddBCC(STORE_OWNER_EMAIL_ADDRESS, STORE_NAME); // set the reply-to address. If none set yet, then use Store's default email name/address. // If sending from contact-us or tell-a-friend page, use the supplied info $email_reply_to_address = isset($email_reply_to_address) && $email_reply_to_address != '' ? $email_reply_to_address : (in_array($module, array('contact_us', 'tell_a_friend')) ? $from_email_address : EMAIL_FROM); $email_reply_to_name = isset($email_reply_to_name) && $email_reply_to_name != '' ? $email_reply_to_name : (in_array($module, array('contact_us', 'tell_a_friend')) ? $from_email_name : STORE_NAME); $mail->AddReplyTo($email_reply_to_address, $email_reply_to_name); // if mailserver requires that all outgoing mail must go "from" an email address matching domain on server, set it to store address if (EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->From = EMAIL_FROM; } if (EMAIL_TRANSPORT == 'sendmail-f' || EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->Sender = EMAIL_FROM; } if (EMAIL_USE_HTML == 'true') { $email_html = processEmbeddedImages($email_html, $mail); } // PROCESS FILE ATTACHMENTS if ($attachments_list == '') { $attachments_list = array(); } if (is_string($attachments_list)) { if (file_exists($attachments_list)) { $attachments_list = array(array('file' => $attachments_list)); } elseif (file_exists(DIR_FS_CATALOG . $attachments_list)) { $attachments_list = array(array('file' => DIR_FS_CATALOG . $attachments_list)); } else { $attachments_list = array(); } } global $newAttachmentsList; $zco_notifier->notify('NOTIFY_EMAIL_BEFORE_PROCESS_ATTACHMENTS', array('attachments' => $attachments_list, 'module' => '')); if (isset($newAttachmentsList) && is_array($newAttachmentsList)) { $attachments_list = $newAttachmentsList; } if (defined('EMAIL_ATTACHMENTS_ENABLED') && EMAIL_ATTACHMENTS_ENABLED && is_array($attachments_list) && sizeof($attachments_list) > 0) { foreach ($attachments_list as $key => $val) { $fname = isset($val['name']) ? $val['name'] : null; $mimeType = isset($val['mime_type']) && $val['mime_type'] != '' && $val['mime_type'] != 'application/octet-stream' ? $val['mime_type'] : ''; switch (true) { case isset($val['raw_data']) && $val['raw_data'] != '': $fdata = $val['raw_data']; if ($mimeType != '') { $mail->AddStringAttachment($fdata, $fname, "base64", $mimeType); } else { $mail->AddStringAttachment($fdata, $fname); } break; case isset($val['file']) && file_exists($val['file']): // 'file' portion must contain the full path to the file to be attached $fdata = $val['file']; if ($mimeType != '') { $mail->AddAttachment($fdata, $fname, "base64", $mimeType); } else { $mail->AddAttachment($fdata, $fname); } break; } // end switch } // end foreach attachments_list } // endif attachments_enabled $mail->Body = $text; // text-only content of message $oldVars = array(); $tmpVars = array('REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'PHP_SELF', 'SERVER_NAME'); foreach ($tmpVars as $key) { if (isset($_SERVER[$key])) { $oldVars[$key] = $_SERVER[$key]; $_SERVER[$key] = ''; } if ($key == 'REMOTE_ADDR') { $_SERVER[$key] = HTTP_SERVER; } if ($key == 'PHP_SELF') { $_SERVER[$key] = '/obf' . 'us' . 'cated'; } } /** * Send the email. * If an error occurs, trap it and display it in the messageStack */ $ErrorInfo = ''; $zco_notifier->notify('NOTIFY_EMAIL_READY_TO_SEND', $mail); if (!($result = $mail->Send())) { if (IS_ADMIN_FLAG === true) { $messageStack->add_session(sprintf(EMAIL_SEND_FAILED . ' ' . $mail->ErrorInfo, $to_name, $to_email_address, $email_subject), 'error'); } else { $messageStack->add('header', sprintf(EMAIL_SEND_FAILED . ' ' . $mail->ErrorInfo, $to_name, $to_email_address, $email_subject), 'error'); } $ErrorInfo .= $mail->ErrorInfo != '' ? $mail->ErrorInfo . '<br />' : ''; } $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND'); foreach ($oldVars as $key => $val) { $_SERVER[$key] = $val; } $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND_WITH_ALL_PARAMS', array($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $ErrorInfo)); // Archive this message to storage log // don't archive pwd-resets and CC numbers if (EMAIL_ARCHIVE == 'true') { zen_mail_archive_write($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $module, $ErrorInfo); } // endif archiving } // end foreach loop thru possible multiple email addresses $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND_ALL_SPECIFIED_ADDRESSES'); // if(EMAIL_FRIENDLY_ERRORS == 'false' && $ErrorInfo != '') // die('<br /><br />Email Error: ' . $ErrorInfo); return $ErrorInfo; }
/** * Send email. This is the central mail function. * If using "PHP" transport method, the SMTP Server or other mail application should be configured correctly in server's php.ini * * @param string $to_name The name of the recipient, e.g. "Jim Johanssen" * @param string $to_email_address The email address of the recipient, e.g. john.smith@hzq.com * @param string $email_subject The subject of the email * @param string $email_text The text of the email, may contain HTML entities * @param string $from_email_name The name of the sender, e.g. Shop Administration * @param string $from_email_address The email address of the sender, e.g. info@myzenshop.com * @param array $block Array containing values to be inserted into HTML-based email template * @param string $module The module name of the routine calling zen_mail. Used for HTML template selection and email archiving. * This is passed to the archive function denoting what module initiated the sending of the email * @param array $attachments_list Array of attachment names/mime-types to be included (this portion still in testing, and not fully reliable) * @param string $email_reply_to_name Name of the "reply-to" header (defaults to store name if not specified, except for contact-us and order-confirmation) * @param string $email_reply_to_address Email address for reply-to header (defaults to store email address if not specified, except for contact-us and order-confirmation) **/ function zen_mail($to_name, $to_address, $email_subject, $email_text, $from_email_name, $from_email_address, $block = array(), $module = 'default', $attachments_list = '', $email_reply_to_name = '', $email_reply_to_address = '') { global $db, $messageStack, $zco_notifier; if (!defined('DEVELOPER_OVERRIDE_EMAIL_STATUS') || defined('DEVELOPER_OVERRIDE_EMAIL_STATUS') && DEVELOPER_OVERRIDE_EMAIL_STATUS == 'site') { if (SEND_EMAILS != 'true') { return false; } } // if sending email is disabled in Admin, just exit if (defined('DEVELOPER_OVERRIDE_EMAIL_ADDRESS') && DEVELOPER_OVERRIDE_EMAIL_ADDRESS != '') { $to_address = DEVELOPER_OVERRIDE_EMAIL_ADDRESS; } // ignore sending emails for any of the following pages // (The EMAIL_MODULES_TO_SKIP constant can be defined in a new file in the "extra_configures" folder) if (defined('EMAIL_MODULES_TO_SKIP') && in_array($module, explode(",", constant('EMAIL_MODULES_TO_SKIP')))) { return false; } // check for injection attempts. If new-line characters found in header fields, simply fail to send the message foreach (array($from_email_address, $to_address, $from_email_name, $to_name, $email_subject) as $key => $value) { if (preg_match("/\r/i", $value) || preg_match("/\n/i", $value)) { return false; } } // if no text or html-msg supplied, exit if (trim($email_text) == '' && (!zen_not_null($block) || isset($block['EMAIL_MESSAGE_HTML']) && $block['EMAIL_MESSAGE_HTML'] == '')) { return false; } // Parse "from" addresses for "name" <*****@*****.**> structure, and supply name/address info from it. if (preg_match("/ *([^<]*) *<([^>]*)> */i", $from_email_address, $regs)) { $from_email_name = trim($regs[1]); $from_email_address = $regs[2]; } // if email name is same as email address, use the Store Name as the senders 'Name' if ($from_email_name == $from_email_address) { $from_email_name = STORE_NAME; } // loop thru multiple email recipients if more than one listed --- (esp for the admin's "Extra" emails)... foreach (explode(',', $to_address) as $key => $value) { if (preg_match("/ *([^<]*) *<([^>]*)> */i", $value, $regs)) { $to_name = str_replace('"', '', trim($regs[1])); $to_email_address = $regs[2]; } elseif (preg_match("/ *([^ ]*) */i", $value, $regs)) { $to_email_address = trim($regs[1]); } if (!isset($to_email_address)) { $to_email_address = trim($to_address); } //if not more than one, just use the main one. $zco_notifier->notify('NOTIFY_EMAIL_ADDRESS_TEST', array(), $to_name, $to_email_address, $email_subject); // ensure the address is valid, to prevent unnecessary delivery failures if (!zen_validate_email($to_email_address)) { $zco_notifier->notify('NOTIFY_EMAIL_ADDRESS_VALIDATION_FAILURE', sprintf(EMAIL_SEND_FAILED . ' (failed validation)', $to_name, $to_email_address, $email_subject)); @error_log(sprintf(EMAIL_SEND_FAILED . ' (failed validation)', $to_name, $to_email_address, $email_subject)); continue; } //define some additional html message blocks available to templates, then build the html portion. if (!isset($block['EMAIL_TO_NAME']) || $block['EMAIL_TO_NAME'] == '') { $block['EMAIL_TO_NAME'] = $to_name; } if (!isset($block['EMAIL_TO_ADDRESS']) || $block['EMAIL_TO_ADDRESS'] == '') { $block['EMAIL_TO_ADDRESS'] = $to_email_address; } if (!isset($block['EMAIL_SUBJECT']) || $block['EMAIL_SUBJECT'] == '') { $block['EMAIL_SUBJECT'] = $email_subject; } if (!isset($block['EMAIL_FROM_NAME']) || $block['EMAIL_FROM_NAME'] == '') { $block['EMAIL_FROM_NAME'] = $from_email_name; } if (!isset($block['EMAIL_FROM_ADDRESS']) || $block['EMAIL_FROM_ADDRESS'] == '') { $block['EMAIL_FROM_ADDRESS'] = $from_email_address; } $email_html = !is_array($block) && substr($block, 0, 6) == '<html>' ? $block : zen_build_html_email_from_template($module, $block); if (!is_array($block) && $block == '' || $block == 'none') { $email_html = ''; } // Build the email based on whether customer has selected HTML or TEXT, and whether we have supplied HTML or TEXT-only components // special handling for XML content if ($email_text == '') { $email_text = str_replace(array('<br>', '<br />'), "<br />\n", $block['EMAIL_MESSAGE_HTML']); $email_text = str_replace('</p>', "</p>\n", $email_text); $email_text = $module != 'xml_record' ? zen_output_string_protected(stripslashes(strip_tags($email_text))) : $email_text; } else { if ($module != 'xml_record') { $email_text = preg_replace('~</?([^(strong>|br ?\\/?>|a href=|p |span|script|li|ol|ul|em|b>|i>|u>)])~', '@lt@\\1', $email_text); $email_text = strip_tags($email_text); $email_text = str_replace('@lt@', '<', $email_text); } } if ($module != 'xml_record') { if (defined('EMAIL_DISCLAIMER') && EMAIL_DISCLAIMER != '' && !strstr($email_text, sprintf(EMAIL_DISCLAIMER, STORE_OWNER_EMAIL_ADDRESS)) && $to_email_address != STORE_OWNER_EMAIL_ADDRESS && !defined('EMAIL_DISCLAIMER_NEW_CUSTOMER')) { $email_text .= "\n" . sprintf(EMAIL_DISCLAIMER, STORE_OWNER_EMAIL_ADDRESS); } if (defined('EMAIL_SPAM_DISCLAIMER') && EMAIL_SPAM_DISCLAIMER != '' && !strstr($email_text, EMAIL_SPAM_DISCLAIMER) && $to_email_address != STORE_OWNER_EMAIL_ADDRESS) { $email_text .= "\n\n" . EMAIL_SPAM_DISCLAIMER; } } // bof: body of the email clean-up // clean up & and && from email text $email_text = preg_replace('/(&)+/', '&', $email_text); $email_text = preg_replace('/(&)+/', '&', $email_text); $email_text = preg_replace('/&{2,}/', '&', $email_text); // clean up currencies for text emails $zen_fix_currencies = preg_split("/[:,]/", CURRENCIES_TRANSLATIONS); $size = sizeof($zen_fix_currencies); for ($i = 0, $n = $size; $i < $n; $i += 2) { $zen_fix_current = $zen_fix_currencies[$i]; $zen_fix_replace = $zen_fix_currencies[$i + 1]; if (strlen($zen_fix_current) > 0) { while (strpos($email_text, $zen_fix_current)) { $email_text = str_replace($zen_fix_current, $zen_fix_replace, $email_text); } } } // fix double quotes $email_text = preg_replace('/(")+/', '"', $email_text); // fix symbols $email_text = preg_replace('/(<)+/', '<', $email_text); $email_text = preg_replace('/(>)+/', '>', $email_text); // prevent null characters $email_text = preg_replace('/\\0+/', ' ', $email_text); // fix slashes $text = stripslashes($email_text); $email_html = stripslashes($email_html); // eof: body of the email clean-up //determine customer's email preference type: HTML or TEXT-ONLY (HTML assumed if not specified) $sql = "select customers_email_format from " . TABLE_CUSTOMERS . " where customers_email_address= :custEmailAddress:"; $sql = $db->bindVars($sql, ':custEmailAddress:', $to_email_address, 'string'); $result = $db->Execute($sql); $customers_email_format = $result->RecordCount() > 0 ? $result->fields['customers_email_format'] : ''; if ($customers_email_format == 'NONE' || $customers_email_format == 'OUT') { return; } //if requested no mail, then don't send. // if ($customers_email_format == 'HTML') $customers_email_format = 'HTML'; // if they opted-in to HTML messages, then send HTML format // handling admin/"extra"/copy emails: if (ADMIN_EXTRA_EMAIL_FORMAT == 'TEXT' && substr($module, -6) == '_extra') { $email_html = ''; // just blank out the html portion if admin has selected text-only } //determine what format to send messages in if this is an admin email for newsletters: if ($customers_email_format == '' && ADMIN_EXTRA_EMAIL_FORMAT == 'HTML' && in_array($module, array('newsletters', 'product_notification')) && isset($_SESSION['admin_id'])) { $customers_email_format = 'HTML'; } // special handling for XML content if ($module == 'xml_record') { $email_html = ''; $customers_email_format = 'TEXT'; } //notifier intercept option $zco_notifier->notify('NOTIFY_EMAIL_AFTER_EMAIL_FORMAT_DETERMINED'); // now lets build the mail object with the phpmailer class $mail = new PHPMailer(); $mail->XMailer = 'PHPMailer ' . $mail->Version . ' for Zen Cart'; $lang_code = strtolower($_SESSION['languages_code'] == '' ? 'en' : $_SESSION['languages_code']); $mail->SetLanguage($lang_code, DIR_FS_CATALOG . DIR_WS_CLASSES . 'support/'); $mail->CharSet = defined('CHARSET') ? CHARSET : "iso-8859-1"; if (defined('EMAIL_ENCODING_METHOD') && EMAIL_ENCODING_METHOD != '') { $mail->Encoding = EMAIL_ENCODING_METHOD; } if ((int) EMAIL_SYSTEM_DEBUG > 0) { $mail->SMTPDebug = (int) EMAIL_SYSTEM_DEBUG; } if ((int) EMAIL_SYSTEM_DEBUG > 4) { $mail->Debugoutput = 'error_log'; } // $mail->WordWrap = 76; // set word wrap to 76 characters // set proper line-endings based on switch ... important for windows vs linux hosts: // $mail->LE = (EMAIL_LINEFEED == 'CRLF') ? "\r\n" : "\n"; switch (EMAIL_TRANSPORT) { case 'Gmail': $mail->IsSMTP(); $mail->SMTPAuth = true; $mail->SMTPSecure = 'ssl'; $mail->Port = 465; $mail->Host = 'smtp.gmail.com'; $mail->Username = zen_not_null(trim(EMAIL_SMTPAUTH_MAILBOX)) ? trim(EMAIL_SMTPAUTH_MAILBOX) : EMAIL_FROM; if (trim(EMAIL_SMTPAUTH_PASSWORD) != '') { $mail->Password = trim(EMAIL_SMTPAUTH_PASSWORD); } break; case 'smtpauth': $mail->IsSMTP(); $mail->SMTPAuth = true; $mail->Username = zen_not_null(trim(EMAIL_SMTPAUTH_MAILBOX)) ? trim(EMAIL_SMTPAUTH_MAILBOX) : EMAIL_FROM; if (trim(EMAIL_SMTPAUTH_PASSWORD) != '') { $mail->Password = trim(EMAIL_SMTPAUTH_PASSWORD); } $mail->Host = trim(EMAIL_SMTPAUTH_MAIL_SERVER) != '' ? trim(EMAIL_SMTPAUTH_MAIL_SERVER) : 'localhost'; if ((int) EMAIL_SMTPAUTH_MAIL_SERVER_PORT != 25 && (int) EMAIL_SMTPAUTH_MAIL_SERVER_PORT != 0) { $mail->Port = (int) EMAIL_SMTPAUTH_MAIL_SERVER_PORT; } if ((int) $mail->Port < 30 && $mail->Host == 'smtp.gmail.com') { $mail->Port = 465; } //set encryption protocol to allow support for secured email protocols if ($mail->Port == '465' || $mail->Host == 'smtp.gmail.com') { $mail->SMTPSecure = 'ssl'; } if ($mail->Port == '587') { $mail->SMTPSecure = 'tls'; } if (defined('SMTPAUTH_EMAIL_PROTOCOL') && SMTPAUTH_EMAIL_PROTOCOL != 'none') { $mail->SMTPSecure = SMTPAUTH_EMAIL_PROTOCOL; } // $mail->LE = "\r\n"; break; case 'smtp': $mail->IsSMTP(); $mail->Host = trim(EMAIL_SMTPAUTH_MAIL_SERVER); if ((int) EMAIL_SMTPAUTH_MAIL_SERVER_PORT != 25 && (int) EMAIL_SMTPAUTH_MAIL_SERVER_PORT != 0) { $mail->Port = (int) EMAIL_SMTPAUTH_MAIL_SERVER_PORT; } // $mail->LE = "\r\n"; break; case 'PHP': $mail->IsMail(); break; case 'Qmail': $mail->IsQmail(); break; case 'sendmail': case 'sendmail-f': // $mail->LE = "\n"; // $mail->LE = "\n"; default: $mail->IsSendmail(); if (defined('EMAIL_SENDMAIL_PATH') && file_exists(trim(EMAIL_SENDMAIL_PATH))) { $mail->Sendmail = trim(EMAIL_SENDMAIL_PATH); } break; } $mail->Subject = $email_subject; if (EMAIL_TRANSPORT == 'sendmail-f' || EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->Sender = EMAIL_FROM; } // set the reply-to address. If none set yet, then use Store's default email name/address. // If sending from checkout or contact-us or tell-a-friend page, use the supplied info $email_reply_to_address = isset($email_reply_to_address) && $email_reply_to_address != '' ? $email_reply_to_address : (in_array($module, array('contact_us', 'tell_a_friend', 'checkout_extra')) ? $from_email_address : EMAIL_FROM); $email_reply_to_name = isset($email_reply_to_name) && $email_reply_to_name != '' ? $email_reply_to_name : (in_array($module, array('contact_us', 'tell_a_friend', 'checkout_extra')) ? $from_email_name : STORE_NAME); $mail->AddReplyTo($email_reply_to_address, $email_reply_to_name); $mail->SetFrom($from_email_address, $from_email_name); // if mailserver requires that all outgoing mail must go "from" an email address matching domain on server, set it to store address if (EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->From = EMAIL_FROM; } $mail->AddAddress($to_email_address, $to_name); //$mail->AddAddress($to_email_address); // (alternate format if no name, since name is optional) //$mail->AddBCC(STORE_OWNER_EMAIL_ADDRESS, STORE_NAME); if (EMAIL_USE_HTML == 'true') { $email_html = processEmbeddedImages($email_html, $mail); } // PROCESS FILE ATTACHMENTS if ($attachments_list == '') { $attachments_list = array(); } if (is_string($attachments_list)) { if (file_exists($attachments_list)) { $attachments_list = array(array('file' => $attachments_list)); } elseif (file_exists(DIR_FS_CATALOG . $attachments_list)) { $attachments_list = array(array('file' => DIR_FS_CATALOG . $attachments_list)); } else { $attachments_list = array(); } } global $newAttachmentsList; $zco_notifier->notify('NOTIFY_EMAIL_BEFORE_PROCESS_ATTACHMENTS', array('attachments' => $attachments_list, 'module' => $module)); if (isset($newAttachmentsList) && is_array($newAttachmentsList)) { $attachments_list = $newAttachmentsList; } if (defined('EMAIL_ATTACHMENTS_ENABLED') && EMAIL_ATTACHMENTS_ENABLED && is_array($attachments_list) && sizeof($attachments_list) > 0) { foreach ($attachments_list as $key => $val) { $fname = isset($val['name']) ? $val['name'] : null; $mimeType = isset($val['mime_type']) && $val['mime_type'] != '' && $val['mime_type'] != 'application/octet-stream' ? $val['mime_type'] : ''; switch (true) { case isset($val['raw_data']) && $val['raw_data'] != '': $fdata = $val['raw_data']; if ($mimeType != '') { $mail->AddStringAttachment($fdata, $fname, "base64", $mimeType); } else { $mail->AddStringAttachment($fdata, $fname); } break; case isset($val['file']) && file_exists($val['file']): //'file' portion must contain the full path to the file to be attached $fdata = $val['file']; if ($mimeType != '') { $mail->AddAttachment($fdata, $fname, "base64", $mimeType); } else { $mail->AddAttachment($fdata, $fname); } break; } // end switch } //end foreach attachments_list } //endif attachments_enabled $zco_notifier->notify('NOTIFY_EMAIL_AFTER_PROCESS_ATTACHMENTS', sizeof($attachments_list)); // prepare content sections: if (EMAIL_USE_HTML == 'true' && trim($email_html) != '' && ($customers_email_format == 'HTML' || ADMIN_EXTRA_EMAIL_FORMAT != 'TEXT' && substr($module, -6) == '_extra')) { // Prepare HTML message $mail->MsgHTML($email_html); if ($text != '') { // apply the supplied text-only portion instead of the auto-generated portion $mail->AltBody = $text; } } else { // If we got here, then other rules specified to send a text-only message instead of HTML $mail->Body = $text; } // Handle auto-generated admin notices, or newsletters, or contact-us as bulk to avoid autoresponder responses and risk of spam flagging if (in_array($module, array('no_archive', 'admin_settings_changed', 'newsletters', 'product_notification', 'contact_us')) || substr($module, -6) == '_extra') { $mail->AddCustomHeader('Precedence: bulk'); $mail->AddCustomHeader('Auto-Submitted: auto-generated'); } $oldVars = array(); $tmpVars = array('REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'PHP_SELF', $mail->Mailer == 'smtp' ? NULL : 'SERVER_NAME'); foreach ($tmpVars as $key) { if (isset($_SERVER[$key])) { $oldVars[$key] = $_SERVER[$key]; $_SERVER[$key] = ''; } if ($key == 'REMOTE_ADDR') { $_SERVER[$key] = HTTP_SERVER; } if ($key == 'PHP_SELF') { $_SERVER[$key] = '/obf' . 'us' . 'cated'; } } @ini_set('mail.add_x_header', 0); $ErrorInfo = ''; $zco_notifier->notify('NOTIFY_EMAIL_READY_TO_SEND', array($mail), $mail); /** * Send the email. If an error occurs, trap it and display it in the messageStack */ if (!$mail->Send()) { $msg = sprintf(EMAIL_SEND_FAILED . ' ' . $mail->ErrorInfo, $to_name, $to_email_address, $email_subject); if ($messageStack !== NULL) { if (IS_ADMIN_FLAG === true) { $messageStack->add_session($msg, 'error'); } else { $messageStack->add('header', $msg, 'error'); } } else { error_log($msg); } $ErrorInfo .= $mail->ErrorInfo != '' ? $mail->ErrorInfo . '<br />' : ''; } $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND'); foreach ($oldVars as $key => $val) { $_SERVER[$key] = $val; } $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND_WITH_ALL_PARAMS', array($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $module, $ErrorInfo)); // Archive this message to storage log // don't archive pwd-resets and CC numbers if (EMAIL_ARCHIVE == 'true' && $module != 'password_forgotten_admin' && $module != 'cc_middle_digs' && $module != 'no_archive') { zen_mail_archive_write($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $module, $ErrorInfo); } // endif archiving } // end foreach loop thru possible multiple email addresses $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND_ALL_SPECIFIED_ADDRESSES'); if (EMAIL_FRIENDLY_ERRORS == 'false' && $ErrorInfo != '') { die('<br /><br />Email Error: ' . $ErrorInfo); } return $ErrorInfo; }
/** * Send email (text/html) using MIME. This is the central mail function. * The SMTP Server should be configured correctly in php.ini * * @param string $to_name The name of the recipient, e.g. "Jim Johanssen" * @param string $to_email_address The eMail address of the recipient, e.g. john.smith@hzq.com * (used as $to_email_address after validation) * @param string $email_subject The subject of the eMail * @param string $email_text The text of the eMail, may contain HTML entities * @param string $from_email_name The name of the sender, e.g. Shop Administration * @param string $from_email_adrdess The eMail address of the sender, e.g. info@myzenshop.com * @param array $block Array containing values to be inserted into HTML-based email template * @param string $module The module name of the routine calling zen_mail. Used for html template selection and email archiving. * This is passed to the archive function denoting what module initiated the sending of the email * @param array $attachments_list Array of attachment names/mime-types to be included (this portion still in testing, and not fully reliable) **/ function zen_mail($to_name, $to_address, $email_subject, $email_text, $from_email_name, $from_email_address, $block = array(), $module = 'default', $attachments_list = '') { global $db, $messageStack, $zco_notifier; if (SEND_EMAILS != 'true') { return false; } // if sending email is disabled in Admin, just exit // ignore sending emails for any of the following pages // (The EMAIL_MODULES_TO_SKIP constant can be defined in a new file in the "extra_configures" folder) if (defined('EMAIL_MODULES_TO_SKIP') && in_array($module, explode(",", constant('EMAIL_MODULES_TO_SKIP')))) { return false; } // check for injection attempts. If new-line characters found in header fields, simply fail to send the message foreach (array($from_email_address, $to_address, $from_email_name, $to_name, $email_subject) as $key => $value) { if (eregi("\r", $value) || eregi("\n", $value)) { return false; } } // if no text or html-msg supplied, exit if (!zen_not_null($email_text) && !zen_not_null($block['EMAIL_MESSAGE_HTML'])) { return false; } // Parse "from" addresses for "name" <*****@*****.**> structure, and supply name/address info from it. if (eregi(" *([^<]*) *<([^>]*)> *", $from_email_address, $regs)) { $from_email_name = trim($regs[1]); $from_email_address = $regs[2]; } // if email name is same as email address, use the Store Name as the senders 'Name' if ($from_email_name == $from_email_address) { $from_email_name = STORE_NAME; } // loop thru multiple email recipients if more than one listed --- (esp for the admin's "Extra" emails)... foreach (explode(',', $to_address) as $key => $value) { if (eregi(" *([^<]*) *<([^>]*)> *", $value, $regs)) { $to_name = str_replace('"', '', trim($regs[1])); $to_email_address = $regs[2]; } elseif (eregi(" *([^ ]*) *", $value, $regs)) { $to_email_address = trim($regs[1]); } if (!isset($to_email_address)) { $to_email_address = $to_address; } //if not more than one, just use the main one. //define some additional html message blocks available to templates, then build the html portion. if ($block['EMAIL_TO_NAME'] == '') { $block['EMAIL_TO_NAME'] = $to_name; } if ($block['EMAIL_TO_ADDRESS'] == '') { $block['EMAIL_TO_ADDRESS'] = $to_email_address; } if ($block['EMAIL_SUBJECT'] == '') { $block['EMAIL_SUBJECT'] = $email_subject; } if ($block['EMAIL_FROM_NAME'] == '') { $block['EMAIL_FROM_NAME'] = $from_email_name; } if ($block['EMAIL_FROM_ADDRESS'] == '') { $block['EMAIL_FROM_ADDRESS'] = $from_email_address; } $email_html = zen_build_html_email_from_template($module, $block); // if ($attachments_list == '') $attachments_list= array(); // bof: body of the email clean-up // clean up & and && from email text while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } while (strstr($email_text, '&')) { $email_text = str_replace('&', '&', $email_text); } while (strstr($email_text, '&&')) { $email_text = str_replace('&&', '&', $email_text); } // clean up currencies for text emails $zen_fix_currencies = split("[:,]", CURRENCIES_TRANSLATIONS); $size = sizeof($zen_fix_currencies); for ($i = 0, $n = $size; $i < $n; $i += 2) { $zen_fix_current = $zen_fix_currencies[$i]; $zen_fix_replace = $zen_fix_currencies[$i + 1]; if (strlen($zen_fix_current) > 0) { while (strpos($email_text, $zen_fix_current)) { $email_text = str_replace($zen_fix_current, $zen_fix_replace, $email_text); } } } // fix double quotes while (strstr($email_text, '"')) { $email_text = str_replace('"', '"', $email_text); } // fix slashes $email_text = stripslashes($email_text); $email_html = stripslashes($email_html); // eof: body of the email clean-up //determine customer's email preference type: HTML or TEXT-ONLY (HTML assumed if not specified) $customers_email_format_read = $db->Execute("select customers_email_format from " . TABLE_CUSTOMERS . " where customers_email_address= '" . $to_email_address . "'"); $customers_email_format = $customers_email_format_read->fields['customers_email_format']; if ($customers_email_format == 'NONE' || $customers_email_format == 'OUT') { return; } //if requested no mail, then don't send. if ($customers_email_format == 'HTML') { $customers_email_format = 'HTML'; } // if they opted-in to HTML messages, then send HTML format //determine what format to send messages in if this is an "extra"/admin-copy email: if (ADMIN_EXTRA_EMAIL_FORMAT == 'TEXT' && substr($module, -6) == '_extra') { $email_html = ''; // just blank out the html portion if admin has selected text-only } //notifier intercept option $zco_notifier->notify('NOTIFY_EMAIL_AFTER_EMAIL_FORMAT_DETERMINED'); // Build the email based on whether customer has selected HTML or TEXT, and whether we have supplied HTML or TEXT-only components if (!zen_not_null($email_text)) { $text = str_replace('<br[[:space:]]*/?[[:space:]]*>', "@CRLF", $block['EMAIL_MESSAGE_HTML']); $text = str_replace('</p>', '</p>@CRLF', $text); $text = htmlspecialchars(stripslashes(strip_tags($text))); } else { $text = strip_tags($email_text); } // now lets build the mail object with the phpmailer class $mail =& new PHPMailer(); $lang_code = $_SESSION['languages_code'] == '' ? 'en' : $_SESSION['languages_code']; $mail->SetLanguage($lang_code, DIR_WS_CLASSES . 'support/'); $mail->CharSet = defined('EMAIL_CHARSET') ? EMAIL_CHARSET : (defined('CHARSET') ? CHARSET : "iso-8859-1"); if (defined('EMAIL_ENCODING')) { $mail->Encoding = EMAIL_ENCODING; } if (defined('EMAIL_MIMEHEADER')) { $mail->MimeHeader = EMAIL_MIMEHEADER; } if (defined('EMAIL_IS_MULTIBYTE')) { $mail->MultibyteFlag = EMAIL_IS_MULTIBYTE; } if ($debug_mode == 'on') { $mail->SMTPDebug = true; } if (EMAIL_TRANSPORT == 'smtp' || EMAIL_TRANSPORT == 'smtpauth') { $mail->IsSMTP(); // set mailer to use SMTP $mail->Host = EMAIL_SMTPAUTH_MAIL_SERVER; // specify main (could also do backup server... future feature?) if (EMAIL_TRANSPORT == 'smtpauth') { $mail->SMTPAuth = true; // turn on SMTP authentication $mail->Username = zen_not_null(EMAIL_SMTPAUTH_MAILBOX) ? EMAIL_SMTPAUTH_MAILBOX : EMAIL_FROM; // SMTP username $mail->Password = EMAIL_SMTPAUTH_PASSWORD; // SMTP password } } $mail->Subject = $email_subject; $mail->From = $from_email_address; $mail->FromName = $from_email_name; $mail->AddAddress($to_email_address, $to_name); // $mail->AddAddress($to_email_address); // (alternate format if no name, since name is optional) $mail->WordWrap = 76; // set word wrap to 76 characters // set the reply-to address. If none set yet, then use Store's default email name/address. // If sending from contact-us or tell-a-friend page, use the supplied info $email_reply_to_address = $email_reply_to_address ? $email_reply_to_address : ($module == 'contact_us' || $module == 'tell_a_friend' ? $from_email_address : EMAIL_FROM); $email_reply_to_name = $email_reply_to_name ? $email_reply_to_name : ($module == 'contact_us' || $module == 'tell_a_friend' ? $from_email_name : STORE_NAME); $mail->AddReplyTo($email_reply_to_address, $email_reply_to_name); // if mailserver requires that all outgoing mail must go "from" an email address matching domain on server, set it to store address if (EMAIL_SEND_MUST_BE_STORE == 'Yes') { $mail->From = EMAIL_FROM; } // process attachments $zco_notifier->notify('NOTIFY_EMAIL_BEFORE_PROCESS_ATTACHMENTS'); // Note: $attachments_list array requires that the 'file' portion contains the full path to the file to be attached if (EMAIL_ATTACHMENTS_ENABLED && zen_not_null($attachments_list)) { // if ($attachments_list == '') $attachments_list = array(); // while ( list($key, $value) = each($attachments_list)) { // $mail->AddAttachment($value['file']); // add attachments $mail->AddAttachment($attachments_list['file']); // add attachments // $mail->AddAttachment("/tmp/image.jpg", "new.jpg"); // optional format if specifying filename // } //endwhile attach_list } //endif attachments $zco_notifier->notify('NOTIFY_EMAIL_AFTER_PROCESS_ATTACHMENTS'); if (EMAIL_USE_HTML == 'true' && trim($email_html) != '' && ($customers_email_format == 'HTML' || ADMIN_EXTRA_EMAIL_FORMAT != 'TEXT' && substr($module, -6) == '_extra')) { $mail->IsHTML(true); // set email format to HTML $mail->Body = $email_html; // HTML-content of message $mail->AltBody = $text; // text-only content of message } else { // use only text portion if not HTML-formatted $mail->Body = $text; // text-only content of message } $zco_notifier->notify('NOTIFY_EMAIL_READY_TO_SEND'); if (!$mail->Send()) { $messageStack->add('header', sprintf(EMAIL_SEND_FAILED . ' ' . $mail->ErrorInfo, $to_name, $to_email_address, $email_subject), 'error'); $ErrorInfo .= $mail->ErrorInfo . '<br />'; } $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND'); // Archive this message to storage log // don't archive pwd-resets and CC numbers if (EMAIL_ARCHIVE == 'true' && $module != 'password_forgotten_admin' && $module != 'cc_middle_digs' && $module != 'no_archive') { zen_mail_archive_write($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject, $email_html, $text, $module); } // endif archiving } // end foreach loop thru possible multiple email addresses $zco_notifier->notify('NOTIFY_EMAIL_AFTER_SEND_ALL_SPECIFIED_ADDRESSES'); return $ErrorInfo; }