| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789 | <?php/** * @file * The code processing mail in the smtp module. * *//*** Modify the drupal mail system to use smtp when sending emails.* Include the option to choose between plain text or HTML*/class SmtpMailSystem implements MailSystemInterface {  protected $AllowHtml;  /**   * Concatenate and wrap the e-mail body for either   * plain-text or HTML emails.   *   * @param $message   *   A message array, as described in hook_mail_alter().   *   * @return   *   The formatted $message.   */  public function format(array $message) {    $this->AllowHtml = variable_get('smtp_allowhtml', 0);    // Join the body array into one string.    $message['body'] = implode("\n\n", $message['body']);    if ($this->AllowHtml == 0) {      // Convert any HTML to plain-text.      $message['body'] = drupal_html_to_text($message['body']);      // Wrap the mail body for sending.      $message['body'] = drupal_wrap_mail($message['body']);    }    return $message;  }  /**   * Send the e-mail message.   *   * @see drupal_mail()   *   * @param $message   *   A message array, as described in hook_mail_alter().   * @return   *   TRUE if the mail was successfully accepted, otherwise FALSE.   */  public function mail(array $message) {    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 ($logging == SMTP_LOGGING_ALL && user_access('administer smtp module')) {      $mailer->SMTPDebug = TRUE;    }    // 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, '');      }    }    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.    if (!isset($headers['Reply-To']) || empty($headers['Reply-To'])) {      if (strpos($from, '<')) {        $reply = preg_replace('/>.*/', '', preg_replace('/.*</', '', $from));      }      else {        $reply = $from;      }      $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.    if ($from == NULL || $from == '') {      // If from e-mail address is blank, use smtp_from config option.      if (($from = variable_get('smtp_from', '')) == '') {        // 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');          if ($logging) {            watchdog('smtp', 'There is no submitted from address.', array(), WATCHDOG_ERROR);          }          return FALSE;        }      }    }    $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_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) {      $to_comp = $this->_get_components($torecipient);      $mailer->AddAddress($to_comp['email'], $to_comp['name']);    }    // Parse the headers of the message and set the PHPMailer object's settings    // accordingly.    foreach ($headers as $key => $value) {      //watchdog('error', 'Key: ' . $key . ' Value: ' . $value);      switch (drupal_strtolower($key)) {        case 'from':          if ($from == NULL or $from == '') {            // If a from value was already given, then set based on header.            // Should be the most common situation since drupal_mail moves the            // from to headers.            $from           = $value;            $mailer->From     = $value;            // then from can be out of sync with from_name !            $mailer->FromName = '';            $mailer->Sender   = $value;          }          break;        case 'content-type':          // Parse several values on the Content-type header, storing them in an array like          // key=value -> $vars['key']='value'          $vars = explode(';', $value);          foreach ($vars as $i => $var) {            if ($cut = strpos($var, '=')) {              $new_var = trim(drupal_strtolower(drupal_substr($var, $cut + 1)));              $new_key = trim(drupal_substr($var, 0, $cut));              unset($vars[$i]);              $vars[$new_key] = $new_var;            }          }          // Set the charset based on the provided value, otherwise set it to UTF-8 (which is Drupals internal default).          $mailer->CharSet = isset($vars['charset']) ? $vars['charset'] : 'UTF-8';          // If $vars is empty then set an empty value at index 0 to avoid a PHP warning in the next statement          $vars[0] = isset($vars[0])?$vars[0]:'';          switch ($vars[0]) {            case 'text/plain':              // The message includes only a plain text part.              $mailer->IsHTML(FALSE);              $content_type = 'text/plain';              break;            case 'text/html':              // The message includes only an HTML part.              $mailer->IsHTML(TRUE);              $content_type = 'text/html';              break;            case 'multipart/related':              // Get the boundary ID from the Content-Type header.              $boundary = $this->_get_substring($value, 'boundary', '"', '"');              // The message includes an HTML part w/inline attachments.              $mailer->ContentType = $content_type = 'multipart/related; boundary="' . $boundary . '"';            break;            case 'multipart/alternative':              // The message includes both a plain text and an HTML part.              $mailer->ContentType = $content_type = 'multipart/alternative';              // Get the boundary ID from the Content-Type header.              $boundary = $this->_get_substring($value, 'boundary', '"', '"');            break;            case 'multipart/mixed':              // The message includes one or more attachments.              $mailer->ContentType = $content_type = 'multipart/mixed';              // Get the boundary ID from the Content-Type header.              $boundary = $this->_get_substring($value, 'boundary', '"', '"');            break;            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');              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';          }          break;        case 'reply-to':          // Only add a "reply-to" if it's not the same as "return-path".          if ($value != $headers['Return-Path']) {            $replyto_comp = $this->_get_components($value);            $mailer->AddReplyTo($replyto_comp['email'], $replyto_comp['name']);          }          break;        case 'content-transfer-encoding':          $mailer->Encoding = $value;          break;        case 'return-path':          $returnpath_comp = $this->_get_components($value);          $mailer->Sender = $returnpath_comp['email'];          break;        case 'mime-version':        case 'x-mailer':          // Let PHPMailer specify these.          break;        case 'errors-to':          $mailer->AddCustomHeader('Errors-To: ' . $value);          break;        case 'cc':          $ccrecipients = explode(',', $value);          foreach ($ccrecipients as $ccrecipient) {            $cc_comp = $this->_get_components($ccrecipient);            $mailer->AddCC($cc_comp['email'], $cc_comp['name']);          }          break;        case 'bcc':          $bccrecipients = explode(',', $value);          foreach ($bccrecipients as $bccrecipient) {            $bcc_comp = $this->_get_components($bccrecipient);            $mailer->AddBCC($bcc_comp['email'], $bcc_comp['name']);          }          break;        case 'message-id':          $mailer->MessageID = $value;          break;        default:          // The header key is not special - add it as is.          $mailer->AddCustomHeader($key . ': ' . $value);      }    }    /**     * TODO     * Need to figure out the following.     *     * Add one last header item, but not if it has already been added.     * $errors_to = FALSE;     * foreach ($mailer->CustomHeader as $custom_header) {     *   if ($custom_header[0] = '') {     *     $errors_to = TRUE;     *   }     * }     * if ($errors_to) {     *   $mailer->AddCustomHeader('Errors-To: '. $from);     * }     */    // Add the message's subject.    $mailer->Subject = $subject;    // Processes the message's body.    switch ($content_type) {      case 'multipart/related':        $mailer->Body = $body;        // TODO: Figure out if there is anything more to handling this type.        break;      case 'multipart/alternative':        // Split the body based on the boundary ID.        $body_parts = $this->_boundary_split($body, $boundary);        foreach ($body_parts as $body_part) {          // If plain/text within the body part, add it to $mailer->AltBody.          if (strpos($body_part, 'text/plain')) {            // Clean up the text.            $body_part = trim($this->_remove_headers(trim($body_part)));            // Include it as part of the mail object.            $mailer->AltBody = $body_part;          }          // If plain/html within the body part, add it to $mailer->Body.          elseif (strpos($body_part, 'text/html')) {            // Clean up the text.            $body_part = trim($this->_remove_headers(trim($body_part)));            // Include it as part of the mail object.            $mailer->Body = $body_part;          }        }        break;      case 'multipart/mixed':        // Split the body based on the boundary ID.        $body_parts = $this->_boundary_split($body, $boundary);        // Determine if there is an HTML part for when adding the plain text part.        $text_plain = FALSE;        $text_html  = FALSE;        foreach ($body_parts as $body_part) {          if (strpos($body_part, 'text/plain')) {            $text_plain = TRUE;          }          if (strpos($body_part, 'text/html')) {            $text_html = TRUE;          }        }        foreach ($body_parts as $body_part) {          // If test/plain within the body part, add it to either          // $mailer->AltBody or $mailer->Body, depending on whether there is          // also a text/html part ot not.          if (strpos($body_part, 'multipart/alternative')) {            // Get boundary ID from the Content-Type header.            $boundary2 = $this->_get_substring($body_part, 'boundary', '"', '"');            // Clean up the text.            $body_part = trim($this->_remove_headers(trim($body_part)));            // Split the body based on the boundary ID.            $body_parts2 = $this->_boundary_split($body_part, $boundary2);            foreach ($body_parts2 as $body_part2) {              // If plain/text within the body part, add it to $mailer->AltBody.              if (strpos($body_part2, 'text/plain')) {                // Clean up the text.                $body_part2 = trim($this->_remove_headers(trim($body_part2)));                // Include it as part of the mail object.                $mailer->AltBody = $body_part2;                $mailer->ContentType = 'multipart/mixed';              }              // If plain/html within the body part, add it to $mailer->Body.              elseif (strpos($body_part2, 'text/html')) {                // Get the encoding.                $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.                if (drupal_strtolower($body_part2_encoding) == 'base64') {                  // Include it as part of the mail object.                  $mailer->Body = base64_decode($body_part2);                  // Ensure the whole message is recoded in the base64 format.                  $mailer->Encoding = 'base64';                }                else {                  // Include it as part of the mail object.                  $mailer->Body = $body_part2;                }                $mailer->ContentType = 'multipart/mixed';              }            }          }          // If text/plain within the body part, add it to $mailer->Body.          elseif (strpos($body_part, 'text/plain')) {            // Clean up the text.            $body_part = trim($this->_remove_headers(trim($body_part)));            if ($text_html) {              $mailer->AltBody = $body_part;              $mailer->IsHTML(TRUE);              $mailer->ContentType = 'multipart/mixed';            }            else {              $mailer->Body = $body_part;              $mailer->IsHTML(FALSE);              $mailer->ContentType = 'multipart/mixed';            }          }          // If text/html within the body part, add it to $mailer->Body.          elseif (strpos($body_part, 'text/html')) {            // Clean up the text.            $body_part = trim($this->_remove_headers(trim($body_part)));            // Include it as part of the mail object.            $mailer->Body = $body_part;            $mailer->IsHTML(TRUE);            $mailer->ContentType = 'multipart/mixed';          }          // Add the attachment.          elseif (strpos($body_part, 'Content-Disposition: attachment;') && !isset($message['params']['attachments'])) {            $file_path     = $this->_get_substring($body_part, 'filename=', '"', '"');            $file_name     = $this->_get_substring($body_part, ' name=', '"', '"');            $file_encoding = $this->_get_substring($body_part, 'Content-Transfer-Encoding', ' ', "\n");            $file_type     = $this->_get_substring($body_part, 'Content-Type', ' ', ';');            if (file_exists($file_path)) {              if (!$mailer->AddAttachment($file_path, $file_name, $file_encoding, $file_type)) {                drupal_set_message(t('Attahment could not be found or accessed.'));              }            }            else {              // Clean up the text.              $body_part = trim($this->_remove_headers(trim($body_part)));              if (drupal_strtolower($file_encoding) == 'base64') {                $attachment = base64_decode($body_part);              }              elseif (drupal_strtolower($file_encoding) == 'quoted-printable') {                $attachment = quoted_printable_decode($body_part);              }              else {                $attachment = $body_part;              }              $attachment_new_filename = drupal_tempnam('temporary://', 'smtp');              $file_path = file_save_data($attachment, $attachment_new_filename, FILE_EXISTS_REPLACE);              $real_path = drupal_realpath($file_path->uri);              if (!$mailer->AddAttachment($real_path, $file_name)) {                drupal_set_message(t('Attachment could not be found or accessed.'));              }            }          }        }        break;      default:        $mailer->Body = $body;        break;    }    // Process mimemail attachments, which are prepared in mimemail_mail().    if (isset($message['params']['attachments'])) {      foreach ($message['params']['attachments'] as $attachment) {        if (isset($attachment['filecontent'])) {          $mailer->AddStringAttachment($attachment['filecontent'], $attachment['filename'], 'base64', $attachment['filemime']);        }        if (isset($attachment['filepath'])) {          $filename = isset($attachment['filename']) ? $attachment['filename'] : basename($attachment['filepath']);          $filemime = isset($attachment['filemime']) ? $attachment['filemime'] : file_get_mimetype($attachment['filepath']);          $mailer->AddAttachment($attachment['filepath'], $filename, 'base64', $filemime);        }      }    }    // Set the authentication settings.    $username = variable_get('smtp_username', '');    $password = variable_get('smtp_password', '');    // If username and password are given, use SMTP authentication.    if ($username != '' && $password != '') {      $mailer->SMTPAuth = TRUE;      $mailer->Username = $username;      $mailer->Password = $password;    }    // Set the protocol prefix for the smtp host.    switch (variable_get('smtp_protocol', 'standard')) {      case 'ssl':        $mailer->SMTPSecure = 'ssl';        break;      case 'tls':        $mailer->SMTPSecure = 'tls';        break;      default:        $mailer->SMTPSecure = '';    }    // Set other connection settings.    $mailer->Host = variable_get('smtp_host', '') . ';' . variable_get('smtp_hostbackup', '');    $mailer->Port = variable_get('smtp_port', '25');    $mailer->Mailer = 'smtp';    // 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');      }    }    $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;  }  /**   * Splits the input into parts based on the given boundary.   *   * Swiped from Mail::MimeDecode, with modifications based on Drupal's coding   * standards and this bug report: http://pear.php.net/bugs/bug.php?id=6495   *   * @param input   *   A string containing the body text to parse.   * @param boundary   *   A string with the boundary string to parse on.   * @return   *   An array containing the resulting mime parts   */  protected function _boundary_split($input, $boundary) {    $parts       = array();    $bs_possible = drupal_substr($boundary, 2, -2);    $bs_check    = '\"' . $bs_possible . '\"';    if ($boundary == $bs_check) {      $boundary = $bs_possible;    }    $tmp = explode('--' . $boundary, $input);    for ($i = 1; $i < count($tmp); $i++) {      if (trim($tmp[$i])) {        $parts[] = $tmp[$i];      }    }    return $parts;  }  //  End of _smtp_boundary_split().  /**   * Strips the headers from the body part.   *   * @param input   *   A string containing the body part to strip.   * @return   *   A string with the stripped body part.   */  protected function _remove_headers($input) {    $part_array = explode("\n", $input);    // will strip these headers according to RFC2045    $headers_to_strip = array( 'Content-Type', 'Content-Transfer-Encoding', 'Content-ID', 'Content-Disposition');    $pattern = '/^(' . implode('|', $headers_to_strip) . '):/';    while (count($part_array) > 0) {      // ignore trailing spaces/newlines      $line = rtrim($part_array[0]);      // if the line starts with a known header string      if (preg_match($pattern, $line)) {        $line = rtrim(array_shift($part_array));        // remove line containing matched header.        // if line ends in a ';' and the next line starts with four spaces, it's a continuation        // of the header split onto the next line. Continue removing lines while we have this condition.        while (substr($line, -1) == ';' && count($part_array) > 0 && substr($part_array[0], 0, 4) == '    ') {          $line = rtrim(array_shift($part_array));        }      }      else {        // no match header, must be past headers; stop searching.        break;      }    }    $output = implode("\n", $part_array);    return $output;  }  //  End of _smtp_remove_headers().  /**   * Returns a string that is contained within another string.   *   * Returns the string from within $source that is some where after $target   * and is between $beginning_character and $ending_character.   *   * @param $source   *   A string containing the text to look through.   * @param $target   *   A string containing the text in $source to start looking from.   * @param $beginning_character   *   A string containing the character just before the sought after text.   * @param $ending_character   *   A string containing the character just after the sought after text.   * @return   *   A string with the text found between the $beginning_character and the   *   $ending_character.   */  protected function _get_substring($source, $target, $beginning_character, $ending_character) {    $search_start     = strpos($source, $target) + 1;    $first_character  = strpos($source, $beginning_character, $search_start) + 1;    $second_character = strpos($source, $ending_character, $first_character) + 1;    $substring        = drupal_substr($source, $first_character, $second_character - $first_character);    $string_length    = drupal_strlen($substring) - 1;    if ($substring[$string_length] == $ending_character) {      $substring = drupal_substr($substring, 0, $string_length);    }    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 <address@example.com>    //  "another name" <address@example.com>    //  <address@example.com>    if (preg_match('/^"?([^"\t\n]*)"?\s*<([^>\t\n]*)>$/', $input, $matches)) {      $components['name'] = trim($matches[1]);      $components['email'] = trim($matches[2]);    }    return $components;  }}
 |