From ed483507e5217cfc1c3bb18c430646ff19509c65 Mon Sep 17 00:00:00 2001 From: Bachir Soussi Chiadmi Date: Tue, 25 Jul 2017 19:17:08 +0200 Subject: [PATCH] security update for smtp module --- .../all/modules/contrib/mail/smtp/README.txt | 4 +- .../modules/contrib/mail/smtp/smtp.admin.inc | 197 +++++++---- sites/all/modules/contrib/mail/smtp/smtp.info | 12 +- .../modules/contrib/mail/smtp/smtp.install | 82 ++++- .../modules/contrib/mail/smtp/smtp.mail.inc | 334 +++++++++++++----- .../all/modules/contrib/mail/smtp/smtp.module | 91 ++++- .../contrib/mail/smtp/smtp.phpmailer.inc | 108 +++--- .../contrib/mail/smtp/smtp.transport.inc | 64 ++-- .../contrib/mail/smtp/smtp.variable.inc | 40 +++ .../contrib/mail/smtp/tests/smtp.unit.test | 200 +++++++++++ .../contrib/mail/smtp/tests/smtp_tests.info | 12 + .../contrib/mail/smtp/tests/smtp_tests.module | 16 + 12 files changed, 872 insertions(+), 288 deletions(-) create mode 100644 sites/all/modules/contrib/mail/smtp/smtp.variable.inc create mode 100644 sites/all/modules/contrib/mail/smtp/tests/smtp.unit.test create mode 100644 sites/all/modules/contrib/mail/smtp/tests/smtp_tests.info create mode 100644 sites/all/modules/contrib/mail/smtp/tests/smtp_tests.module diff --git a/sites/all/modules/contrib/mail/smtp/README.txt b/sites/all/modules/contrib/mail/smtp/README.txt index 403afb67..40fb7adc 100644 --- a/sites/all/modules/contrib/mail/smtp/README.txt +++ b/sites/all/modules/contrib/mail/smtp/README.txt @@ -1,4 +1,3 @@ - SMTP Authentication Support module for Drupal 7.x. This module adds SMTP functionality to Drupal. @@ -41,3 +40,6 @@ extension is working. If the SMTP module detects openssl is available it will display the options in the modules settings page. Sending mail to Gmail requires SSL or TLS. + +If the Maillog module (https://www.drupal.org/project/maillog) is installed, it +can be used to keep copies of all messages sent through the site. diff --git a/sites/all/modules/contrib/mail/smtp/smtp.admin.inc b/sites/all/modules/contrib/mail/smtp/smtp.admin.inc index cee7c8cb..ede79758 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.admin.inc +++ b/sites/all/modules/contrib/mail/smtp/smtp.admin.inc @@ -3,41 +3,21 @@ /** * @file * Administrative page code for the smtp module. - * */ - /** * Administrative settings. - * - * @return - * An array containing form items to place on the module settings page. */ function smtp_admin_settings() { - // Override the smtp_library variable. - if (module_exists('mimemail') && - strpos(variable_get('smtp_library', ''), 'mimemail')) { - // don't touch smtp_library + if (variable_get('smtp_on', 0)) { + drupal_set_message(t('SMTP.module is active.')); } else { - if (variable_get('smtp_on', 0)) { - $smtp_path = drupal_get_filename('module', 'smtp'); - if ($smtp_path) { - variable_set('smtp_library', $smtp_path); - drupal_set_message(t('SMTP.module is active.')); - } - // If drupal can't find the path to the module, display an error. - else { - drupal_set_message(t("SMTP.module error: Can't find file."), 'error'); - } - } - // If this module is turned off, delete the variable. - else { - variable_del('smtp_library'); - drupal_set_message(t('SMTP.module is INACTIVE.')); - } + drupal_set_message(t('SMTP.module is INACTIVE.')); } + $logging = variable_get('smtp_debugging', SMTP_LOGGING_ERRORS); + $form['onoff'] = array( '#type' => 'fieldset', '#title' => t('Install options'), @@ -45,16 +25,29 @@ function smtp_admin_settings() { $form['onoff']['smtp_on'] = array( '#type' => 'radios', '#title' => t('Turn this module on or off'), - '#default_value' => variable_get('smtp_on', 0), + '#default_value' => variable_get('smtp_on', FALSE), '#options' => array(1 => t('On'), 0 => t('Off')), '#description' => t('To uninstall this module you must turn it off here first.'), ); + $form['onoff']['smtp_deliver'] = array( + '#type' => 'radios', + '#title' => t('Turn on delivery of emails'), + '#default_value' => variable_get('smtp_deliver', TRUE), + '#options' => array(1 => t('On'), 0 => t('Off')), + '#description' => t('With this option turned off, email messages will be queued up and processed as normal, but not actually delivered. This option should only be used for testing purposes.'), + ); $form['onoff']['smtp_queue'] = array( '#type' => 'checkbox', '#title' => t('Send mail by queue'), '#default_value' => variable_get('smtp_queue', FALSE), '#description' => t('Mails will be sent by drupal queue api.'), ); + $form['onoff']['smtp_queue_fail'] = array( + '#type' => 'checkbox', + '#title' => t('Retry sending mail on error.'), + '#default_value' => variable_get('smtp_queue_fail', FALSE), + '#description' => t('Mails will be added to the queue and sent by drupal queue api.'), + ); $form['server'] = array( '#type' => 'fieldset', @@ -80,6 +73,7 @@ function smtp_admin_settings() { '#default_value' => variable_get('smtp_port', '25'), '#description' => t('The default SMTP port is 25, if that is being blocked try 80. Gmail uses 465. See !url for more information on configuring for use with Gmail.', array('!url' => l(t('this page'), 'http://gmail.google.com/support/bin/answer.py?answer=13287'))), ); + // Only display the option if openssl is installed. if (function_exists('openssl_open')) { $encryption_options = array( @@ -87,7 +81,7 @@ function smtp_admin_settings() { 'ssl' => t('Use SSL'), 'tls' => t('Use TLS'), ); - $encryption_description = t('This allows connection to an SMTP server that requires SSL encryption such as Gmail.'); + $encryption_description = t('This allows connection to a SMTP server that requires SSL encryption such as Gmail.'); } // If openssl is not installed, use normal protocol. else { @@ -119,6 +113,9 @@ function smtp_admin_settings() { '#title' => t('Password'), '#default_value' => variable_get('smtp_password', ''), '#description' => t('SMTP password. If you have already entered your password before, you should leave this field blank, unless you want to change the stored password.'), + '#attributes' => array( + 'autocomplete' => 'off', + ), ); $form['email_options'] = array( @@ -139,22 +136,28 @@ function smtp_admin_settings() { ); $form['email_options']['smtp_allowhtml'] = array( '#type' => 'checkbox', - '#title' => t('Allow to send e-mails formated as Html'), + '#title' => t('Allow to send e-mails formatted as Html'), '#default_value' => variable_get('smtp_allowhtml', 0), - '#description' => t('Checking this box will allow Html formated e-mails to be sent with the SMTP protocol.'), + '#description' => t('Checking this box will allow Html formatted e-mails to be sent with the SMTP protocol.'), + ); + + $form['client'] = array( + '#type' => 'fieldset', + '#title' => t('SMTP client settings'), + ); + $form['client']['smtp_client_hostname'] = array( + '#type' => 'textfield', + '#title' => t('Hostname'), + '#default_value' => variable_get('smtp_client_hostname', ''), + '#description' => t('The hostname to use in the Message-Id and Received headers, and as the default HELO string. Leave blank for using %server_name.', array('%server_name' => isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain')), + ); + $form['client']['smtp_client_helo'] = array( + '#type' => 'textfield', + '#title' => t('HELO'), + '#default_value' => variable_get('smtp_client_helo', ''), + '#description' => t('The SMTP HELO/EHLO of the message. Defaults to hostname (see above).'), ); - // If an address was given, send a test e-mail message. - $test_address = variable_get('smtp_test_address', ''); - if ($test_address != '') { - // Clear the variable so only one message is sent. - variable_del('smtp_test_address'); - global $language; - $params['subject'] = t('Drupal SMTP test e-mail'); - $params['body'] = array(t('If you receive this message it means your site is capable of using SMTP to send e-mail.')); - drupal_mail('smtp', 'smtp-test', $test_address, $language, $params); - drupal_set_message(t('A test e-mail has been sent to @email. You may want to !check for any error messages.', array('@email' => $test_address, '!check' => l(t('check the logs'), 'admin/reports/dblog')))); - } $form['email_test'] = array( '#type' => 'fieldset', '#title' => t('Send test e-mail'), @@ -166,51 +169,76 @@ function smtp_admin_settings() { '#description' => t('Type in an address to have a test e-mail sent there.'), ); - $form['smtp_debugging'] = array( - '#type' => 'checkbox', - '#title' => t('Enable debugging'), - '#default_value' => variable_get('smtp_debugging', 0), - '#description' => t('Checking this box will print SMTP messages from the server for every e-mail that is sent.'), + $form['debugging'] = array( + '#type' => 'fieldset', + '#title' => t('Debugging and logging'), ); + $logging_options = array( + SMTP_LOGGING_ALL => t('Log everything'), + SMTP_LOGGING_ERRORS => t('Errors only'), + SMTP_LOGGING_NONE => t('No logging'), + ); + $form['debugging']['smtp_debugging'] = array( + '#type' => 'select', + '#title' => t('Logging'), + '#options' => $logging_options, + '#default_value' => $logging, + '#description' => t('Choose the appropriate log level. "Log everything" will log errors and informational messages when an email is sent. "Errors only" will only create a log entry when sending failed. "No logging" will disable all logging for this module.'), + ); + $form['email_test']['smtp_reroute_address'] = array( + '#type' => 'textfield', + '#title' => t('E-mail address to reroute all emails to'), + '#default_value' => variable_get('smtp_reroute_address', ''), + '#description' => t('All emails sent by the site will be rerouted to this email address; use with caution.'), + ); + + $form['debugging']['maillog'] = array( + '#type' => 'fieldset', + '#title' => t('Maillog integration'), + ); + + if (!module_exists('maillog')) { + $form['debugging']['maillog']['#description'] = t('Installing the Maillog module also allows keeping copies of all emails sent through the site.', array('@url' => 'https://www.drupal.org/project/maillog')); + } + else { + $form['debugging']['maillog']['#description'] = t('The Maillog module is installed, it can also be used to keep copies of all emails sent through the site.', array('@url' => url('admin/config/development/maillog'))); + + $form['debugging']['maillog']['maillog_log'] = array( + '#type' => 'checkbox', + '#title' => t("Create table entries in maillog table for each e-mail."), + '#default_value' => variable_get('maillog_log', TRUE), + ); + + $form['debugging']['maillog']['maillog_devel'] = array( + '#type' => 'checkbox', + '#title' => t("Display the e-mails on page using devel module (if enabled)."), + '#default_value' => variable_get('maillog_devel', TRUE), + '#disabled' => !module_exists('devel'), + ); + } + $form['#submit'][] = 'smtp_admin_settings_form_submit'; - - return system_settings_form($form); -} // End of smtp_admin_settings(). - - + $form = system_settings_form($form); + $form['#submit'][] = 'smtp_admin_settings_submit_post_system_settings'; + return $form; +} /** * Validation for the administrative settings form. - * - * @param form - * An associative array containing the structure of the form. - * @param form_state - * A keyed array containing the current state of the form. */ function smtp_admin_settings_validate($form, &$form_state) { if ($form_state['values']['smtp_on'] == 1 && $form_state['values']['smtp_host'] == '') { - form_set_error('smtp_host', t('You must enter an SMTP server address.')); + form_set_error('smtp_host', t('You must enter a SMTP server address.')); } if ($form_state['values']['smtp_on'] == 1 && $form_state['values']['smtp_port'] == '') { - form_set_error('smtp_port', t('You must enter an SMTP port number.')); + form_set_error('smtp_port', t('You must enter a SMTP port number.')); } if ($form_state['values']['smtp_from'] && !valid_email_address($form_state['values']['smtp_from'])) { form_set_error('smtp_from', t('The provided from e-mail address is not valid.')); } - - // If username is set empty, we must set both username/password empty as well. - if (empty($form_state['values']['smtp_username'])) { - $form_state['values']['smtp_password'] = ''; - } - - // A little hack. When form is presentend, the password is not shown (Drupal way of doing). - // So, if user submits the form without changing the password, we must prevent it from being reset. - elseif (empty($form_state['values']['smtp_password'])) { - unset($form_state['values']['smtp_password']); - } } // End of smtp_admin_settings_validate(). /** @@ -236,4 +264,37 @@ function smtp_admin_settings_form_submit($form, &$form_state) { variable_set('mail_system', $mail_modes); } + + // If username is set empty, we must set both username/password empty as well. + if (empty($form_state['values']['smtp_username'])) { + $form_state['values']['smtp_password'] = ''; + } + + // A little hack. When form is presentend, the password is not shown (Drupal + // way of doing). So, if user submits the form without changing the password, + // we must prevent it from being reset. + elseif (empty($form_state['values']['smtp_password'])) { + unset($form_state['values']['smtp_password']); + } + + // Save the test address to send an email after all the settings have been + // updated. + $form_state['storage']['smtp']['smtp_test_address'] = $form_state['values']['smtp_test_address']; + unset($form_state['values']['smtp_test_address']); +} + +/** + * Submit handler for the administrative settings form containing all + * functionality to be run after system_settings_form_submit. + */ +function smtp_admin_settings_submit_post_system_settings($form, &$form_state) { + // If an address was given, send a test e-mail message. + $test_address = $form_state['storage']['smtp']['smtp_test_address']; + if ($test_address != '') { + $language = language_default(); + $params['subject'] = t('Drupal SMTP test e-mail'); + $params['body'] = array(t('If you receive this message it means your site is capable of using SMTP to send e-mail.')); + drupal_mail('smtp', 'smtp-test', $test_address, $language, $params); + drupal_set_message(t('A test e-mail has been sent to @email. You may want to !check for any error messages.', array('@email' => $test_address, '!check' => l(t('check the logs'), 'admin/reports/dblog')))); + } } diff --git a/sites/all/modules/contrib/mail/smtp/smtp.info b/sites/all/modules/contrib/mail/smtp/smtp.info index 7986f1b9..50721bf1 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.info +++ b/sites/all/modules/contrib/mail/smtp/smtp.info @@ -7,9 +7,15 @@ files[] = smtp.mail.inc files[] = smtp.phpmailer.inc files[] = smtp.transport.inc -; Information added by Drupal.org packaging script on 2015-01-07 -version = "7.x-1.2" +; Test suite. +files[] = tests/smtp.unit.test + +; For the tests the Maillog module is also required. +test_dependencies[] = maillog + +; Information added by Drupal.org packaging script on 2017-06-27 +version = "7.x-1.7" core = "7.x" project = "smtp" -datestamp = "1420662781" +datestamp = "1498593247" diff --git a/sites/all/modules/contrib/mail/smtp/smtp.install b/sites/all/modules/contrib/mail/smtp/smtp.install index 61ab1356..609c807a 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.install +++ b/sites/all/modules/contrib/mail/smtp/smtp.install @@ -5,6 +5,34 @@ * The installation instructions for the SMTP Authentication Support. */ +/** + * Implements hook_requirements(). + */ +function smtp_requirements($phase) { + $requirements = array(); + + if ($phase == 'runtime') { + if (variable_get('smtp_queue', FALSE) || variable_get('smtp_queue_fail', FALSE)) { + $count = db_query("SELECT count('name') FROM {queue} WHERE name='smtp_send_queue'")->fetchField(); + $requirements['smtp_queue'] = array( + 'title' => t('SMTP Queue'), + 'value' => '', + 'severity' => REQUIREMENT_INFO, + ); + if ($count > 0) { + $requirements['smtp_queue']['value'] = format_plural($count, 'There is 1 message queued for delivery.', 'There are @count messages queued for delivery.', array('@count' => $count)) + . ' ' + . t('Delivery of the message(s) will be attempted the next time cron runs.'); + } + else { + $requirements['smtp_queue']['value'] = t('There are no messages queued for delivery.'); + } + } + } + + return $requirements; +} + /** * Implements hook_install(). */ @@ -16,6 +44,7 @@ * Implements hook_uninstall(). */ function smtp_uninstall() { + variable_del('smtp_allowhtml'); variable_del('smtp_from'); variable_del('smtp_fromname'); variable_del('smtp_host'); @@ -24,12 +53,14 @@ function smtp_uninstall() { variable_del('smtp_password'); variable_del('smtp_port'); variable_del('smtp_protocol'); - variable_del('smtp_test_address'); + variable_del('smtp_queue'); + variable_del('smtp_queue_fail'); variable_del('smtp_username'); - - if (variable_get('smtp_library', '') == drupal_get_path('module', 'smtp') . '/smtp.module') { - variable_del('smtp_library'); - } + variable_del('smtp_debugging'); + variable_del('smtp_client_hostname'); + variable_del('smtp_client_helo'); + variable_del('smtp_deliver'); + variable_del('smtp_reroute_address'); } /** @@ -42,18 +73,21 @@ function smtp_disable() { } /** - * Implements hook_update_N(). + * Implementations of hook_update_N(). + */ + +/** * Upgrade to Drupal 7.x */ function smtp_update_7000() { if (variable_get('smtp_on', 0) != 0) { variable_set('mail_system', array('default-system' => 'SmtpMailSystem')); } + // Not used any more in D7. + variable_del('smtp_library'); } /** - * Implements hook_update_N(). - * * Back to default mail system if the status flag is off. */ function smtp_update_7100() { @@ -63,3 +97,35 @@ function smtp_update_7100() { variable_set('mail_system', $mail_modes); } } + +/** + * Updating variable value now that new SMTP logging behavior has been + * implemented. + */ +function smtp_update_7101() { + $old_debugging_value = variable_get('smtp_debugging', 0); + + $logging = SMTP_LOGGING_NONE; + + if ($old_debugging_value == 1) { + $logging = SMTP_LOGGING_ERRORS; + } + + variable_set('smtp_debugging', $logging); +} + +/** + * Remove the unused 'smtp_library' variable. + */ +function smtp_update_7102() { + variable_del('smtp_library'); +} + +/** + * Delete the variable "smtp_test_address". It is unlikely that this would + * actually be set in the normal course of events, and it's no longer needed as + * it was replaced with a form submit handler. + */ +function smtp_update_7103() { + variable_del('smtp_test_address'); +} diff --git a/sites/all/modules/contrib/mail/smtp/smtp.mail.inc b/sites/all/modules/contrib/mail/smtp/smtp.mail.inc index b220eeb1..4887ddc1 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.mail.inc +++ b/sites/all/modules/contrib/mail/smtp/smtp.mail.inc @@ -46,35 +46,84 @@ class SmtpMailSystem implements MailSystemInterface { * TRUE if the mail was successfully accepted, otherwise FALSE. */ public function mail(array $message) { - $id = $message['id']; + if (variable_get('smtp_queue', FALSE) + && (!isset($message['params']['skip_queue']) || !$message['params']['skip_queue'])) { + smtp_send_queue($message); + if (variable_get('smtp_debugging', SMTP_LOGGING_ERRORS) == SMTP_LOGGING_ALL) { + watchdog('smtp', 'Queue sending mail to: @to', array('@to' => $message['to'])); + } + return TRUE; + } + else { + return $this->mailWithoutQueue($message); + } + } + + public function mailWithoutQueue(array $message) { $to = $message['to']; $from = $message['from']; $body = $message['body']; $headers = $message['headers']; $subject = $message['subject']; + // Optionally reroute all emails to a single address. + $reroute_address = variable_get('smtp_reroute_address', ''); + if (!empty($reroute_address)) { + $to = $reroute_address; + // Remove any CC and BCC headers that might have been set. + unset($headers['cc']); + unset($headers['bcc']); + } + // Create a new PHPMailer object - autoloaded from registry. $mailer = new PHPMailer(); + $logging = variable_get('smtp_debugging', SMTP_LOGGING_ERRORS); + // Turn on debugging, if requested. - if (variable_get('smtp_debugging', 0) == 1) { + if ($logging == SMTP_LOGGING_ALL && user_access('administer smtp module')) { $mailer->SMTPDebug = TRUE; } - // Set the from name. - if (variable_get('smtp_fromname', '') != '') { - $from_name = variable_get('smtp_fromname', ''); + // Set the from name. First we try to get the name from i18n, in the case + // that it has been translated. The name is set according to the language + // of the email being sent. + $from_name = FALSE; + if (function_exists('i18n_variable_get')) { + // The 'language' value may be stored as an object. + $langcode = $message['language']; + if (is_object($langcode)) { + $langcode = $langcode->language; + } + if (i18n_variable_get('smtp_fromname', $langcode, '') != '') { + $from_name = i18n_variable_get('smtp_fromname', $langcode, ''); + } + else { + // If value is not defined in settings, use site_name. + $from_name = i18n_variable_get('site_name', $langcode, ''); + } } - else { - // If value is not defined in settings, use site_name. - $from_name = variable_get('site_name', ''); + + if (variable_get('smtp_client_hostname', '') != '') { + $mailer->Hostname = variable_get('smtp_client_hostname', ''); + } + + if (variable_get('smtp_client_helo', '') != '') { + $mailer->Helo = variable_get('smtp_client_helo', ''); + } + + // If i18n is not enabled, we get the From Name through normal variables + if (!$from_name) { + if (variable_get('smtp_fromname', '') != '') { + $from_name = variable_get('smtp_fromname', ''); + } + else { + // If value is not defined in settings, use site_name. + $from_name = variable_get('site_name', ''); + } } //Hack to fix reply-to issue. - $properfrom = variable_get('site_mail', ''); - if (!empty($properfrom)) { - $headers['From'] = $properfrom; - } if (!isset($headers['Reply-To']) || empty($headers['Reply-To'])) { if (strpos($from, '<')) { $reply = preg_replace('/>.*/', '', preg_replace('/.*$/', $from)) { - // . == Matches any single character except line break characters \r and \n. - // * == Repeats the previous item zero or more times. - $from_name = preg_replace('/"?([^("\t\n)]*)"?.*$/', '$1', $from); // It gives: Name - $from = preg_replace("/(.*)\<(.*)\>/i", '$2', $from); // It gives: name@domain.tld - } - elseif (!valid_email_address($from)) { - drupal_set_message(t('The submitted from address (@from) is not valid.', array('@from' => $from)), 'error'); - watchdog('smtp', 'The submitted from address (@from) is not valid.', array('@from' => $from), WATCHDOG_ERROR); + $from_comp = $this->_get_components($from); + + if (!valid_email_address($from_comp['email'])) { + drupal_set_message(t('The submitted from address (@from) is not valid.', array('@from' => $from_comp['email'])), 'error'); + if ($logging) { + watchdog('smtp', 'The submitted from address (@from) is not valid.', array('@from' => $from_comp['email']), WATCHDOG_ERROR); + } return FALSE; } // Defines the From value to what we expect. - $mailer->From = $from; - $mailer->FromName = $from_name; - $mailer->Sender = $from; + $mailer->From = $from_comp['email']; + $mailer->FromName = empty($from_comp['name']) ? $from_name : $from_comp['name']; + $mailer->Sender = $from_comp['email']; // Create the list of 'To:' recipients. $torecipients = explode(',', $to); foreach ($torecipients as $torecipient) { - if (strpos($torecipient, '<') !== FALSE) { - $toparts = explode(' <', $torecipient); - $toname = $toparts[0]; - $toaddr = rtrim($toparts[1], '>'); - } - else { - $toname = ''; - $toaddr = $torecipient; - } - $mailer->AddAddress($toaddr, $toname); + $to_comp = $this->_get_components($torecipient); + $mailer->AddAddress($to_comp['email'], $to_comp['name']); } @@ -201,8 +247,9 @@ class SmtpMailSystem implements MailSystemInterface { default: // Everything else is unsuppored by PHPMailer. drupal_set_message(t('The %header of your message is not supported by PHPMailer and will be sent as text/plain instead.', array('%header' => "Content-Type: $value")), 'error'); - watchdog('smtp', 'The %header of your message is not supported by PHPMailer and will be sent as text/plain instead.', array('%header' => "Content-Type: $value"), WATCHDOG_ERROR); - + if ($logging) { + watchdog('smtp', 'The %header of your message is not supported by PHPMailer and will be sent as text/plain instead.', array('%header' => "Content-Type: $value"), WATCHDOG_ERROR); + } // Force the Content-Type to be text/plain. $mailer->IsHTML(FALSE); $content_type = 'text/plain'; @@ -212,16 +259,8 @@ class SmtpMailSystem implements MailSystemInterface { case 'reply-to': // Only add a "reply-to" if it's not the same as "return-path". if ($value != $headers['Return-Path']) { - if (strpos($value, '<') !== FALSE) { - $replyToParts = explode('<', $value); - $replyToName = trim($replyToParts[0]); - $replyToName = trim($replyToName, '"'); - $replyToAddr = rtrim($replyToParts[1], '>'); - $mailer->AddReplyTo($replyToAddr, $replyToName); - } - else { - $mailer->AddReplyTo($value); - } + $replyto_comp = $this->_get_components($value); + $mailer->AddReplyTo($replyto_comp['email'], $replyto_comp['name']); } break; @@ -230,14 +269,8 @@ class SmtpMailSystem implements MailSystemInterface { break; case 'return-path': - if (strpos($value, '<') !== FALSE) { - $returnPathParts = explode('<', $value); - $returnPathAddr = rtrim($returnPathParts[1], '>'); - $mailer->Sender = $returnPathAddr; - } - else { - $mailer->Sender = $value; - } + $returnpath_comp = $this->_get_components($value); + $mailer->Sender = $returnpath_comp['email']; break; case 'mime-version': @@ -252,32 +285,16 @@ class SmtpMailSystem implements MailSystemInterface { case 'cc': $ccrecipients = explode(',', $value); foreach ($ccrecipients as $ccrecipient) { - if (strpos($ccrecipient, '<') !== FALSE) { - $ccparts = explode(' <', $ccrecipient); - $ccname = $ccparts[0]; - $ccaddr = rtrim($ccparts[1], '>'); - } - else { - $ccname = ''; - $ccaddr = $ccrecipient; - } - $mailer->AddCC($ccaddr, $ccname); + $cc_comp = $this->_get_components($ccrecipient); + $mailer->AddCC($cc_comp['email'], $cc_comp['name']); } break; case 'bcc': $bccrecipients = explode(',', $value); foreach ($bccrecipients as $bccrecipient) { - if (strpos($bccrecipient, '<') !== FALSE) { - $bccparts = explode(' <', $bccrecipient); - $bccname = $bccparts[0]; - $bccaddr = rtrim($bccparts[1], '>'); - } - else { - $bccname = ''; - $bccaddr = $bccrecipient; - } - $mailer->AddBCC($bccaddr, $bccname); + $bcc_comp = $this->_get_components($bccrecipient); + $mailer->AddBCC($bcc_comp['email'], $bcc_comp['name']); } break; @@ -377,7 +394,7 @@ class SmtpMailSystem implements MailSystemInterface { // If plain/html within the body part, add it to $mailer->Body. elseif (strpos($body_part2, 'text/html')) { // Get the encoding. - $body_part2_encoding = $this->_get_substring($body_part2, 'Content-Transfer-Encoding', ':', "\n"); + $body_part2_encoding = trim($this->_get_substring($body_part2, 'Content-Transfer-Encoding', ':', "\n")); // Clean up the text. $body_part2 = trim($this->_remove_headers(trim($body_part2))); // Check whether the encoding is base64, and if so, decode it. @@ -509,20 +526,124 @@ class SmtpMailSystem implements MailSystemInterface { $mailer->Port = variable_get('smtp_port', '25'); $mailer->Mailer = 'smtp'; - $mailerArr = array( - 'mailer' => $mailer, - 'to' => $to, - 'from' => $from, - ); - if (variable_get('smtp_queue', FALSE)) { - watchdog('smtp', 'Queue sending mail to: @to', array('@to' => $to)); - smtp_send_queue($mailerArr); - } - else { - return _smtp_mailer_send($mailerArr); + // Integration with the Maillog module. + if (module_exists('maillog')) { + if (variable_get('maillog_log', TRUE)) { + $record = new stdClass; + + // In case the subject/from/to is already encoded, decode with + // mime_header_decode. + $record->header_message_id = isset($mailer->MessageID) ? $mailer->MessageID : NULL; + $record->subject = drupal_substr(mime_header_decode($mailer->Subject), 0, 255); + $record->header_from = $from; + $record->header_to = $to; + $record->header_reply_to = isset($headers['Reply-To']) ? $headers['Reply-To'] : ''; + $record->header_all = serialize($headers); + $record->sent_date = REQUEST_TIME; + + // Used to separate different portions of the body string. + $divider = str_repeat('-', 60) . "\n"; + + // Load the attachments. + $attachments = $mailer->GetAttachments(); + + $record->body = ''; + + // If there's more than one item to display, add a divider. + if (!empty($mailer->AltBody) || !empty($attachments)) { + $record->body .= t('Body') . ":\n"; + $record->body .= $divider; + } + + // Add the body field. + if (isset($mailer->Body)) { + $record->body .= $mailer->Body; + } + else { + $record->body .= t('*No message body*') . ":\n"; + } + + // The AltBody value is optional. + if (!empty($mailer->AltBody)) { + $record->body .= "\n"; + $record->body .= $divider; + $record->body .= t('Alternative body') . ":\n"; + $record->body .= $divider; + $record->body .= $mailer->AltBody; + } + + // List the attachments. + if (!empty($attachments)) { + $record->body .= "\n"; + $record->body .= $divider; + $record->body .= t('Attachments') . ":\n"; + $record->body .= $divider; + foreach ($attachments as $file) { + $record->body .= t('Filename') . ':' . $file[1] . "\n"; + $record->body .= t('Name') . ':' . $file[2] . "\n"; + $record->body .= t('Encoding') . ':' . $file[3] . "\n"; + $record->body .= t('Type') . ':' . $file[4] . "\n"; + $record->body .= "\n"; + } + } + + drupal_write_record('maillog', $record); + } + + // Display the e-mail using Devel module. + if (variable_get('maillog_devel', TRUE) && function_exists('dpm')) { + $devel_msg = array(); + $devel_msg[t('Subject')] = $mailer->Subject; + $devel_msg[t('From')] = $from; + $devel_msg[t('To')] = $to; + $devel_msg[t('Reply-To')] = isset($headers['Reply-To']) ? $headers['Reply-To'] : NULL; + $devel_msg[t('Headers')] = $headers; + $devel_msg[t('Body')] = $mailer->Body; + $devel_msg[t('Alternative body')] = $mailer->AltBody; + $devel_msg[t('Attachments')] = $mailer->GetAttachments(); + + dpm($devel_msg, 'maillog'); + } } - return TRUE; + $error = FALSE; + + // Email delivery was disabled. + if (!variable_get('smtp_deliver', TRUE)) { + if ($logging) { + $params = array( + '@from' => $from, + '@to' => $to, + ); + watchdog('smtp', 'Email delivery is disabled, did not send email from @from to @to.', $params); + } + } + else { + if (!$mailer->send()) { + $params = array( + '@from' => $from, + '@to' => $to, + '!error_message' => $mailer->ErrorInfo + ); + + if (variable_get('smtp_queue_fail', FALSE)) { + if ($logging) { + watchdog('smtp', 'Error sending e-mail from @from to @to, will retry on cron run : !error_message.', $params, WATCHDOG_ERROR); + } + smtp_failed_messages($message); + } + elseif ($logging) { + $error = TRUE; + watchdog('smtp', 'Error sending e-mail from @from to @to : !error_message', $params, WATCHDOG_ERROR); + } + } + elseif (variable_get('smtp_debugging', SMTP_LOGGING_ERRORS) == SMTP_LOGGING_ALL) { + watchdog('smtp', 'Sent mail to: @to', array('@to' => $to)); + } + } + + $mailer->SmtpClose(); + return !$error; } /** @@ -628,6 +749,41 @@ class SmtpMailSystem implements MailSystemInterface { $substring = drupal_substr($substring, 0, $string_length); } - return $substring; + return trim($substring); } // End of _smtp_get_substring(). + + /** + * Returns an array of name and email address from a string. + * + * @param $input + * A string that contains different possible combinations of names and + * email address. + * @return + * An array containing a name and an email address. + */ + protected function _get_components($input) { + $components = array( + 'input' => $input, + 'name' => '', + 'email' => '', + ); + + // If the input is a valid email address in its entirety, then there is + // nothing to do, just return that. + if (valid_email_address($input)) { + $components['email'] = trim($input); + return $components; + } + + // Check if $input has one of the following formats, extract what we can: + // some name + // "another name" + // + if (preg_match('/^"?([^"\t\n]*)"?\s*<([^>\t\n]*)>$/', $input, $matches)) { + $components['name'] = trim($matches[1]); + $components['email'] = trim($matches[2]); + } + + return $components; + } } diff --git a/sites/all/modules/contrib/mail/smtp/smtp.module b/sites/all/modules/contrib/mail/smtp/smtp.module index 9c15c530..0fe18eb0 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.module +++ b/sites/all/modules/contrib/mail/smtp/smtp.module @@ -15,6 +15,22 @@ * This module uses array('default-system' => 'SmtpMailSystem'). */ +/** + * SMTP logging -- logging is disabled + */ +define('SMTP_LOGGING_NONE', 0); + +/** + * SMTP logging -- all messages are logged + */ +define('SMTP_LOGGING_ALL', 1); + +/** + * SMTP logging -- only errors are logged + */ +define('SMTP_LOGGING_ERRORS', 2); + + /** * Implements hook_help(). */ @@ -68,8 +84,14 @@ function smtp_mail($key, &$message, $params) { function smtp_cron_queue_info() { $queues['smtp_send_queue'] = array( 'worker callback' => 'smtp_send_queue_runner', - 'time' => 60, // This is the max run time per cron run in seconds. + 'time' => 60, ); + + $queues['smtp_failure_queue'] = array( + 'worker callback' => 'smtp_failure_queue_runner', + 'time' => 30, + ); + return $queues; } @@ -81,24 +103,55 @@ function smtp_send_queue($mailerObj) { $queue->createItem($mailerObj); } -function smtp_send_queue_runner($variables) { - _smtp_mailer_send($variables); -} +function smtp_send_queue_runner($message) { + $logging = variable_get('smtp_debugging', SMTP_LOGGING_ERRORS); -function _smtp_mailer_send($variables) { - $mailer = $variables['mailer']; - $to = $variables['to']; - $from = $variables['from']; - - // Let the people know what is going on. - watchdog('smtp', 'Sending mail to: @to', array('@to' => $to)); - - // Try to send e-mail. If it fails, set watchdog entry. - if (!$mailer->Send()) { - watchdog('smtp', 'Error sending e-mail from @from to @to : !error_message', array('@from' => $from, '@to' => $to, '!error_message' => $mailer->ErrorInfo), WATCHDOG_ERROR); - return FALSE; + // Legacy for mails queued before 7.x-v1.3 + // What was passed to the runner used to be a PHPMailer object, not a message array. + if (!empty($message['mailer']) && is_object($message['mailer'])) { + if (!$message['mailer']->Send()) { + if ($logging == SMTP_LOGGING_ALL || $logging == SMTP_LOGGING_ERRORS) { + watchdog('smtp', 'Error sending e-mail from @from to @to, will retry on cron run : !error_message.', + array( + '@from' => $message['from'], + '@to' => $message['to'], + '!error_message' => $message['mailer']->ErrorInfo, + ), WATCHDOG_ERROR); + } + } + return; } - $mailer->SmtpClose(); - return TRUE; -} \ No newline at end of file + // Let the people know what is going on. + if ($logging == SMTP_LOGGING_ALL) { + watchdog('smtp', 'Sending mail to: @to', array('@to' => $message['to'])); + } + + // Send the message. + $mail_system = new SmtpMailSystem(); + $mail_system->mailWithoutQueue($message); +} + +/** + * Store failed messages for later. + * + * @param array $new_message + * + * @return array + * All messages that have been saved. + */ +function smtp_failed_messages($message) { + $queue = DrupalQueue::get('smtp_failure_queue'); + $queue->createItem($message); +} + +/** + * Queue runner for smtp_failure_queue. + * + * @param $message + * A drupal_mail-formatted message. + */ +function smtp_failure_queue_runner($message) { + $queue = DrupalQueue::get('smtp_send_queue'); + $queue->createItem($message); +} diff --git a/sites/all/modules/contrib/mail/smtp/smtp.phpmailer.inc b/sites/all/modules/contrib/mail/smtp/smtp.phpmailer.inc index e0c0747c..95420d2e 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.phpmailer.inc +++ b/sites/all/modules/contrib/mail/smtp/smtp.phpmailer.inc @@ -7,7 +7,7 @@ */ /*~ class.phpmailer.php -Orginal release information: +Original release information: .---------------------------------------------------------------------------. | Software: PHPMailer - PHP email class | | Version: 5.1 | @@ -325,6 +325,7 @@ class PHPMailer { private $sign_key_file = ""; private $sign_key_pass = ""; private $exceptions = FALSE; + private $logging; ///////////////////////////////////////////////// // CONSTANTS @@ -343,6 +344,7 @@ class PHPMailer { * @param boolean $exceptions Should we throw external exceptions? */ public function __construct($exceptions = FALSE) { + $this->logging = variable_get('smtp_debugging', SMTP_LOGGING_ERRORS); $this->exceptions = ($exceptions == TRUE); } @@ -455,7 +457,9 @@ class PHPMailer { */ private function AddAnAddress($kind, $address, $name = '') { if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) { - echo 'Invalid recipient array: ' . kind; + if ($this->logging) { + watchdog('smtp', 'Invalid recipient array: %kind', array('%kind' => $kind), WATCHDOG_ERROR); + } return FALSE; } $address = trim($address); @@ -465,7 +469,9 @@ class PHPMailer { if ($this->exceptions) { throw new phpmailerException(t('Invalid address') . ': ' . $address); } - echo t('Invalid address') . ': ' . $address; + if ($this->logging) { + watchdog('smtp', 'Invalid address: %address', array('%address' => $address), WATCHDOG_ERROR); + } return FALSE; } if ($kind != 'ReplyTo') { @@ -498,7 +504,9 @@ class PHPMailer { if ($this->exceptions) { throw new phpmailerException(t('Invalid address') . ': ' . $address); } - echo t('Invalid address') . ': ' . $address; + if ($this->logging) { + watchdog('smtp', 'Invalid address: %address', array('%address' => $address), WATCHDOG_ERROR); + } return FALSE; } $this->From = $address; @@ -577,8 +585,6 @@ class PHPMailer { // Choose the mailer and send through it switch ($this->Mailer) { - case 'sendmail': - return $this->SendmailSend($header, $body); case 'smtp': return $this->SmtpSend($header, $body); default: @@ -590,59 +596,13 @@ class PHPMailer { if ($this->exceptions) { throw $e; } - echo $e->getMessage() . "\n"; + if ($this->logging) { + watchdog_exception('smtp', $e); + } return FALSE; } } - /** - * Sends mail using the $Sendmail program. - * @param string $header The message headers - * @param string $body The message body - * @access protected - * @return bool - */ - protected function SendmailSend($header, $body) { - if ($this->Sender != '') { - $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); - } - else { - $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); - } - if ($this->SingleTo === TRUE) { - foreach ($this->SingleToArray as $key => $val) { - if (!@$mail = popen($sendmail, 'w')) { - throw new phpmailerException(t('Could not execute: !smail', array('!smail' => $this->Sendmail)), self::STOP_CRITICAL); - } - fputs($mail, "To: " . $val . "\n"); - fputs($mail, $header); - fputs($mail, $body); - $result = pclose($mail); - // implement call back function if it exists - $isSent = ($result == 0) ? 1 : 0; - $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body); - if ($result != 0) { - throw new phpmailerException(t('Could not execute: !smail', array('!smail' => $this->Sendmail)), self::STOP_CRITICAL); - } - } - } - else { - if (!@$mail = popen($sendmail, 'w')) { - throw new phpmailerException(t('Could not execute: !smail', array('!smail' => $this->Sendmail)), self::STOP_CRITICAL); - } - fputs($mail, $header); - fputs($mail, $body); - $result = pclose($mail); - // implement call back function if it exists - $isSent = ($result == 0) ? 1 : 0; - $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body); - if ($result != 0) { - throw new phpmailerException(t('Could not execute: !smail', array('!smail' => $this->Sendmail)), self::STOP_CRITICAL); - } - } - return TRUE; - } - /** * Sends mail using the PHP mail() function. * @param string $header The message headers @@ -662,7 +622,7 @@ class PHPMailer { $old_from = ini_get('sendmail_from'); ini_set('sendmail_from', $this->Sender); if ($this->SingleTo === TRUE && count($toArr) > 1) { - foreach ($toArr as $key => $val) { + foreach ($toArr as $val) { $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); // implement call back function if it exists $isSent = ($rt == 1) ? 1 : 0; @@ -678,7 +638,7 @@ class PHPMailer { } else { if ($this->SingleTo === TRUE && count($toArr) > 1) { - foreach ($toArr as $key => $val) { + foreach ($toArr as $val) { $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); // implement call back function if it exists $isSent = ($rt == 1) ? 1 : 0; @@ -792,10 +752,11 @@ class PHPMailer { $hosts = explode(';', $this->Host); $index = 0; $connection = $this->smtp->Connected(); + $lastexception = NULL; // Retry while there is no connection - try { - while ($index < count($hosts) && !$connection) { + while ($index < count($hosts) && !$connection) { + try { $hostinfo = array(); if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { $host = $hostinfo[1]; @@ -830,14 +791,24 @@ class PHPMailer { } } } - $index++; - if (!$connection) { - throw new phpmailerException(t('SMTP Error: Could not connect to SMTP host.')); + } catch (phpmailerException $e) { + if ($connection) { + $this->SmtpClose(); + $connection = FALSE; } + + $lastexception = $e; + } + + $index++; + } + if (!$connection) { + if ($lastexception != NULL) { + throw $lastexception; + } + else { + throw new phpmailerException(t('SMTP Error: Could not connect to SMTP host.')); } - } catch (phpmailerException $e) { - $this->smtp->Reset(); - throw $e; } return TRUE; } @@ -1361,7 +1332,9 @@ class PHPMailer { if ($this->exceptions) { throw $e; } - echo $e->getMessage() . "\n"; + if ($this->logging) { + watchdog_exception('smtp', $e); + } if ( $e->getCode() == self::STOP_CRITICAL ) { return FALSE; } @@ -2217,7 +2190,6 @@ class PHPMailer { * @param string $key_pass Password for private key */ public function DKIM_QP($txt) { - $tmp=""; $line=""; for ($i=0;$igetMessage() . "
\n"; return $errorMsg; } -} \ No newline at end of file +} diff --git a/sites/all/modules/contrib/mail/smtp/smtp.transport.inc b/sites/all/modules/contrib/mail/smtp/smtp.transport.inc index 01013d5a..dfecfb00 100644 --- a/sites/all/modules/contrib/mail/smtp/smtp.transport.inc +++ b/sites/all/modules/contrib/mail/smtp/smtp.transport.inc @@ -6,7 +6,7 @@ * */ /*~ class.smtp.php -Orginal release information: +Original release information: .---------------------------------------------------------------------------. | Software: PHPMailer - PHP email class | | Version: 5.1 | @@ -141,7 +141,7 @@ class SMTP { "errno" => $errno, "errstr" => $errstr); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @errstr (@errno)", array("@error" => $this->error["error"], "@errstr" => $errstr, "@errno" => $errno))); } return FALSE; } @@ -155,7 +155,7 @@ class SMTP { $announce = $this->get_lines(); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @announce", array("@announce" => $announce))); } return TRUE; @@ -184,7 +184,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 220) { @@ -193,7 +193,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -225,7 +225,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -242,7 +242,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -259,7 +259,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -278,7 +278,7 @@ class SMTP { if ($sock_status["eof"]) { // the socket is valid but we are not connected if ($this->do_debug >= 1) { - echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; + drupal_set_message(t("SMTP -> NOTICE: EOF caught while checking if connected")); } $this->Close(); return FALSE; @@ -314,7 +314,7 @@ class SMTP { * finializing the mail transaction. $msg_data is the message * that is to be send with the headers. Each header needs to be * on a single line followed by a with the message headers - * and the message body being seperated by and additional . + * and the message body being separated by and additional . * * Implements rfc 821: DATA * @@ -343,7 +343,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 354) { @@ -352,7 +352,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -437,7 +437,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 250) { @@ -446,7 +446,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -502,7 +502,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 250) { @@ -511,7 +511,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -551,7 +551,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 250) { @@ -560,7 +560,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -594,7 +594,7 @@ class SMTP { $byemsg = $this->get_lines(); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @byemsg", array("@rply" => $byemsg))); } $rval = TRUE; @@ -608,7 +608,7 @@ class SMTP { "smtp_rply" => substr($byemsg, 4)); $rval = FALSE; if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } } @@ -646,7 +646,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 250 && $code != 251) { @@ -655,7 +655,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -689,7 +689,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 250) { @@ -698,7 +698,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -736,7 +736,7 @@ class SMTP { $code = substr($rply, 0, 3); if ($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> FROM SERVER: @rply", array("@rply" => $rply))); } if ($code != 250) { @@ -745,7 +745,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply, 4)); if ($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> ERROR: @error: @rply", array("@error" => $this->error["error"], "@rply" => $rply))); } return FALSE; } @@ -755,7 +755,7 @@ class SMTP { /** * This is an optional command for SMTP that this class does not * support. This method is here to make the RFC821 Definition - * complete for this class and __may__ be implimented in the future + * complete for this class and __may__ be implemented in the future * * Implements from rfc 821: TURN * @@ -768,7 +768,7 @@ class SMTP { public function Turn() { $this->error = array("error" => "This method, TURN, of the SMTP is not implemented"); if ($this->do_debug >= 1) { - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> NOTICE: @error", array("@error" => $this->error["error"]))); } return FALSE; } @@ -799,12 +799,12 @@ class SMTP { $data = ""; while ($str = @fgets($this->smtp_conn, 515)) { if ($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '
'; - echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> get_lines(): \$data was \"@data\"", array("@data" => $data))); + drupal_set_message(t("SMTP -> get_lines(): \$str is \"@str\"", array("@str" => $str))); } $data .= $str; if ($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '
'; + drupal_set_message(t("SMTP -> get_lines(): \$data was \"@data\"", array("@data" => $data))); } // if 4th character is a space, we are done reading, break the loop if (substr($str, 3, 1) == " ") { @@ -813,4 +813,4 @@ class SMTP { } return $data; } -} \ No newline at end of file +} diff --git a/sites/all/modules/contrib/mail/smtp/smtp.variable.inc b/sites/all/modules/contrib/mail/smtp/smtp.variable.inc new file mode 100644 index 00000000..76cbf57d --- /dev/null +++ b/sites/all/modules/contrib/mail/smtp/smtp.variable.inc @@ -0,0 +1,40 @@ + t('SMTP Authentication Support'), + 'access' => 'administer smtp module', + 'description' => t('Configure SMTP server for site emails to be sent from different names.'), + ); + + return $groups; +} + +/** + * Implements hook_variable_info(). + * + * Allows for the SMTP from name to be translated if/when the Variable module is + * enabled. + * + * @link http://api.drupalhelp.net/api/variable/variable.api.php/function/hook_variable_info/7 + * @param array $options + */ +function smtp_variable_info($options) { + $variable['smtp_fromname'] = array ( + 'title' => t('Email from name (SMTP module)'), + 'type' => 'string', + 'description' => t('Allow for site emails to be sent from a different name.'), + 'group' => 'smtp', + 'multidomain' => TRUE, + 'localize' => TRUE, + ); + + return $variable; +} diff --git a/sites/all/modules/contrib/mail/smtp/tests/smtp.unit.test b/sites/all/modules/contrib/mail/smtp/tests/smtp.unit.test new file mode 100644 index 00000000..88f9ad4a --- /dev/null +++ b/sites/all/modules/contrib/mail/smtp/tests/smtp.unit.test @@ -0,0 +1,200 @@ + 'SMTP unit tests', + 'description' => 'Test the SMTP module.', + 'group' => 'SMTP', + ); + } + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + // Requirements. + $modules[] = 'smtp'; + + // Some extra logic for fully testing the module. + $modules[] = 'smtp_tests'; + + // This module is used to log all emails so that the delivery can be + // confirmed. + $modules[] = 'maillog'; + + parent::setUp($modules); + + // Take over the email system. + variable_set('mail_system', array('default-system' => 'SmtpMailSystem')); + + // Turn on the mail module. + variable_set('smtp_on', TRUE); + + // Do not actually deliver the emails. + variable_set('smtp_deliver', FALSE); + + // Use Maillog to log all emails. + variable_set('maillog_log', TRUE); + } + + /** + * Confirm that SMTP has taken over the 'mail_system' variable. + */ + function testSetup() { + $enabled = variable_get('mail_system', array()); + $should_be = array( + 'default-system' => 'SmtpMailSystem', + ); + $this->assertEqual($enabled, $should_be, 'SMTP is controlling mail delivery.'); + + $delivery = variable_get('smtp_on', TRUE); + $this->assertEqual($delivery, TRUE, 'SMTP is enabled.'); + + $delivery = variable_get('smtp_deliver', FALSE); + $this->assertEqual($delivery, FALSE, 'Email delivery is disabled.'); + + $logging = variable_get('maillog_log', TRUE); + $this->assertEqual($logging, TRUE, 'Email delivery is being logged.'); + } + + /** + * Tests logging mail with maillog module. + */ + public function testLogging() { + $langcode = language_default('language'); + + // This is automatically assigned by Simpletest. + $sender = 'simpletest@example.com'; + + // Send an email. + $to_email = 'to_test@example.com'; + $reply_email = 'reply_test@example.com'; + $params = array(); + drupal_mail('smtp_tests', 'smtp_basic_test', $to_email, $langcode, $params); + + // The SMTP module controls the 'from' address but defaults to using the + // site's system email address. + $from_email = variable_get('site_mail', ''); + + // Compare the maillog db entry with the sent mail. + $logged_email = $this->getLatestMaillogEntry(); + $this->assertTrue(!empty($logged_email), 'The test email was captured.'); + $this->assertEqual($to_email, $logged_email['header_to']);//, 'Email "to" address is correct.'); + $this->assertEqual($from_email, $logged_email['header_from']);//, 'Email "from" address is correct.'); + $this->assertEqual($from_email, $logged_email['header_all']['From']);//, 'Email "from" header is correct.'); + $this->assertEqual($sender, $logged_email['header_all']['Sender']);//, 'Email "sender" header is correct.'); + $this->assertEqual($sender, $logged_email['header_all']['Return-Path']);//, 'Email "return-path" header is correct.'); + $this->assertEqual('Drupal', $logged_email['header_all']['X-Mailer']);//, 'Email "x-mailer" header is correct.'); + $this->assertEqual(t('Test email subject'), $logged_email['subject']);//, 'Email subject is correct.'); + $this->assertEqual(t('Test email body.') . "\n", $logged_email['body']);//, 'Email body is correct.'); + } + + /** + * Confirm the queue works. + */ + public function testQueue() { + // Turn on the queue. + variable_set('smtp_queue', TRUE); + + // Send a test message. + $langcode = language_default('language'); + $sender = 'simpletest@example.com'; + $to_email = 'to_test@example.com'; + $reply_email = 'reply_test@example.com'; + $params = array(); + drupal_mail('smtp_tests', 'smtp_basic_test', $to_email, $langcode, $params); + + // Check the queue for messages. + $queue_count = $this->getQueueCount(); + $this->assertEqual($queue_count, 1, 'An email was found in the send queue.'); + } + + /** + * Confirm the queue works. + */ + public function testFailQueue() { + // Turn on the queue failover. + variable_set('smtp_queue_fail', TRUE); + + // Make sure the queue is disabled. + variable_set('smtp_queue', FALSE); + + // Turn on email delivery. + variable_set('smtp_deliver', TRUE); + + // Set some fake values for the delivery, it should fail and then cause the + // email to go in to the queue. + variable_set('smtp_from', 'drupal@example.com'); + variable_set('smtp_fromname', 'Drupal Simpletest'); + variable_set('smtp_host', 'smtp.gmail.com'); + variable_set('smtp_hostbackup', ''); + variable_set('smtp_password', 'THIS WILL NOT WORK!'); + variable_set('smtp_port', '465'); + variable_set('smtp_protocol', 'ssl'); + variable_set('smtp_username', 'hello@example.com'); + + // Send a test message. + $langcode = language_default('language'); + $sender = 'simpletest@example.com'; + $to_email = 'to_test@example.com'; + $reply_email = 'reply_test@example.com'; + $params = array(); + drupal_mail('smtp_tests', 'smtp_basic_test', $to_email, $langcode, $params); + + // Check the queue for messages. + $queue_count = $this->getQueueCount('smtp_failure_queue'); + $this->assertEqual($queue_count, 1, 'An email was found in the failure queue.'); + $queue_count = $this->getQueueCount(); + $this->assertEqual($queue_count, 0, 'An email was not found in the regular email queue.'); + + // Run the queue so that messages can be moved to the normal email queue. + drupal_cron_run(); + + // Check the queue for messages. + $queue_count = $this->getQueueCount(); + $this->assertEqual($queue_count, 1, 'An email was found in the regular email queue.'); + $queue_count = $this->getQueueCount('smtp_failure_queue'); + $this->assertEqual($queue_count, 0, 'An email was not found in the failure queue.'); + } + + /** + * Gets the latest Maillog entry. + * + * @return array + * Maillog entry. + */ + protected function getLatestMaillogEntry() { + $query = 'SELECT idmaillog, header_from, header_to, header_reply_to, header_all, subject, body FROM {maillog} ORDER BY idmaillog DESC'; + $result = db_query_range($query, 0, 1); + + if ($maillog = $result->fetchAssoc()) { + // Unserialize values. + $maillog['header_all'] = unserialize($maillog['header_all']); + } + return $maillog; + } + + /** + * Get the number of emails in a specific queue. + * + * @param string $queue + * The name of the queue to add the emails to. + * + * @return int + * The number of messages found in the requested queue. + */ + protected function getQueueCount($queue = 'smtp_send_queue') { + return db_query("SELECT count('name') FROM {queue} WHERE name = :queue", + array(':queue' => $queue)) + ->fetchField(); + } + +} diff --git a/sites/all/modules/contrib/mail/smtp/tests/smtp_tests.info b/sites/all/modules/contrib/mail/smtp/tests/smtp_tests.info new file mode 100644 index 00000000..8269c55b --- /dev/null +++ b/sites/all/modules/contrib/mail/smtp/tests/smtp_tests.info @@ -0,0 +1,12 @@ +name = SMTP tests +description = Contains helper logic for the SMTP tests. +package = Mail +core = 7.x +hidden = TRUE + +; Information added by Drupal.org packaging script on 2017-06-27 +version = "7.x-1.7" +core = "7.x" +project = "smtp" +datestamp = "1498593247" + diff --git a/sites/all/modules/contrib/mail/smtp/tests/smtp_tests.module b/sites/all/modules/contrib/mail/smtp/tests/smtp_tests.module new file mode 100644 index 00000000..ec7ce119 --- /dev/null +++ b/sites/all/modules/contrib/mail/smtp/tests/smtp_tests.module @@ -0,0 +1,16 @@ +