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)); @@ -84,6 +133,11 @@ class SmtpMailSystem implements MailSystemInterface { } $headers['Reply-To'] = $reply; } + $properfrom = variable_get('smtp_from', ''); + if (!empty($properfrom)) { + $headers['From'] = $properfrom; + $from = $properfrom; + } // Blank value will let the e-mail address appear. @@ -93,42 +147,34 @@ class SmtpMailSystem implements MailSystemInterface { // If smtp_from config option is blank, use site_email. if (($from = variable_get('site_mail', '')) == '') { drupal_set_message(t('There is no submitted from address.'), 'error'); - watchdog('smtp', 'There is no submitted from address.', array(), WATCHDOG_ERROR); + if ($logging) { + watchdog('smtp', 'There is no submitted from address.', array(), WATCHDOG_ERROR); + } return FALSE; } } } - if (preg_match('/^"?.*"?\s*<.*>$/', $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;$i