| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572 | 
							- <?php
 
- /**
 
-  * @file
 
-  * Common mail functions for sending e-mail. Originally written by Gerhard.
 
-  *
 
-  *   Allie Micka <allie at pajunas dot com>
 
-  */
 
- /**
 
-  * Attempts to RFC822-compliant headers for the mail message or its MIME parts.
 
-  *
 
-  * @todo Could use some enhancement and stress testing.
 
-  *
 
-  * @param array $headers
 
-  *   An array of headers.
 
-  *
 
-  * @return string
 
-  *   A string containing the headers.
 
-  */
 
- function mimemail_rfc_headers($headers) {
 
-   $header = '';
 
-   $crlf = variable_get('mimemail_crlf', MAIL_LINE_ENDINGS);
 
-   foreach ($headers as $key => $value) {
 
-     $key = trim($key);
 
-     // Collapse spaces and get rid of newline characters.
 
-     $value = preg_replace('/(\s+|\n|\r|^\s|\s$)/', ' ', $value);
 
-     // Fold headers if they're too long.
 
-     // A CRLF may be inserted before any WSP.
 
-     // @see http://tools.ietf.org/html/rfc2822#section-2.2.3
 
-     if (drupal_strlen($value) > 60) {
 
-       // If there's a semicolon, use that to separate.
 
-       if (count($array = preg_split('/;\s*/', $value)) > 1) {
 
-         $value = trim(join(";$crlf ", $array));
 
-       }
 
-       else {
 
-         $value = wordwrap($value, 50, "$crlf ", FALSE);
 
-       }
 
-     }
 
-     $header .= $key . ":" . $value . $crlf;
 
-   }
 
-   return trim($header);
 
- }
 
- /**
 
-  * Gives useful defaults for standard email headers.
 
-  *
 
-  * @param array $headers
 
-  *   Message headers.
 
-  * @param string $from
 
-  *   The address of the sender.
 
-  *
 
-  * @return array
 
-  *   Overwrited headers.
 
-  */
 
- function mimemail_headers($headers, $from = NULL) {
 
-   $default_from = variable_get('site_mail', ini_get('sendmail_from'));
 
-   // Overwrite standard headers.
 
-   if ($from) {
 
-     if (!isset($headers['From']) || $headers['From'] == $default_from) {
 
-       $headers['From'] = $from;
 
-     }
 
-     if (!isset($headers['Sender']) || $headers['Sender'] == $default_from) {
 
-       $headers['Sender'] = $from;
 
-     }
 
-     // This may not work. The MTA may rewrite the Return-Path.
 
-     if (!isset($headers['Return-Path']) || $headers['Return-Path'] == $default_from) {
 
-       if (preg_match('/[a-z\d\-\.\+_]+@(?:[a-z\d\-]+\.)+[a-z\d]{2,4}/i', $from, $matches)) {
 
-         $headers['Return-Path'] = "<$matches[0]>";
 
-       }
 
-     }
 
-   }
 
-   // Convert From header if it is an array.
 
-   if (is_array($headers['From'])) {
 
-     $headers['From'] = mimemail_address($headers['From']);
 
-   }
 
-   // Run all headers through mime_header_encode() to convert non-ascii
 
-   // characters to an rfc compliant string, similar to drupal_mail().
 
-   foreach ($headers as $key => $value) {
 
-     $headers[$key] = mime_header_encode($value);
 
-   }
 
-   return $headers;
 
- }
 
- /**
 
-  * Extracts links to local images from HTML documents.
 
-  *
 
-  * @param string $html
 
-  *   A string containing the HTML source of the message.
 
-  *
 
-  * @return array
 
-  *   An array containing the document body and the extracted files like the following.
 
-  *     array(
 
-  *       array(
 
-  *         'name' => document name
 
-  *         'content' => html text, local image urls replaced by Content-IDs,
 
-  *         'Content-Type' => 'text/html; charset=utf-8')
 
-  *       array(
 
-  *         'name' => file name,
 
-  *         'file' => reference to local file,
 
-  *         'Content-ID' => generated Content-ID,
 
-  *         'Content-Type' => derived using mime_content_type if available, educated guess otherwise
 
-  *        )
 
-  *     )
 
-  */
 
- function mimemail_extract_files($html) {
 
-   $pattern = '/(<link[^>]+href=[\'"]?|<object[^>]+codebase=[\'"]?|@import |[\s]src=[\'"]?)([^\'>"]+)([\'"]?)/mis';
 
-   $content = preg_replace_callback($pattern, '_mimemail_replace_files', $html);
 
-   $encoding = '8Bit';
 
-   $body = explode("\n", $content);
 
-   foreach ($body as $line) {
 
-     if (drupal_strlen($line) > 998) {
 
-       $encoding = 'base64';
 
-       break;
 
-     }
 
-   }
 
-   if ($encoding == 'base64') {
 
-     $content = rtrim(chunk_split(base64_encode($content)));
 
-   }
 
-   $document = array(array(
 
-     'Content-Type' => "text/html; charset=utf-8",
 
-     'Content-Transfer-Encoding' => $encoding,
 
-     'content' => $content,
 
-   ));
 
-   $files = _mimemail_file();
 
-   return array_merge($document, $files);
 
- }
 
- /**
 
-  * Callback function for preg_replace_callback().
 
-  */
 
- function _mimemail_replace_files($matches) {
 
-   return stripslashes($matches[1]) . _mimemail_file($matches[2]) . stripslashes($matches[3]);
 
- }
 
- /**
 
-  * Helper function to extract local files.
 
-  *
 
-  * @param string $url
 
-  *   (optional) The URI or the absolute URL to the file.
 
-  * @param string $content
 
-  *   (optional) The actual file content.
 
-  * @param string $name
 
-  *   (optional) The file name.
 
-  * @param string $type
 
-  *   (optional) The file type.
 
-  * @param string $disposition
 
-  *   (optional) The content disposition. Defaults to inline.
 
-  *
 
-  * @return
 
-  *   The Content-ID and/or an array of the files on success or the URL on failure.
 
-  */
 
- function _mimemail_file($url = NULL, $content = NULL, $name = '', $type = '', $disposition = 'inline') {
 
-   static $files = array();
 
-   static $ids = array();
 
-   if ($url) {
 
-     $image = preg_match('!\.(png|gif|jpg|jpeg)$!i', $url);
 
-     $linkonly = variable_get('mimemail_linkonly', 0);
 
-     // The file exists on the server as-is. Allows for non-web-accessible files.
 
-     if (@is_file($url) && $image && !$linkonly) {
 
-       $file = $url;
 
-     }
 
-     else {
 
-       $url = _mimemail_url($url, 'TRUE');
 
-       // The $url is absolute, we're done here.
 
-       $scheme = file_uri_scheme($url);
 
-       if ($scheme == 'http' || $scheme == 'https' || preg_match('!mailto:!', $url)) {
 
-         return $url;
 
-       }
 
-       // The $url is a non-local URI that needs to be converted to a URL.
 
-       else {
 
-         $file = (drupal_realpath($url)) ? drupal_realpath($url) : file_create_url($url);
 
-       }
 
-     }
 
-   }
 
-   // We have the actual content.
 
-   elseif ($content) {
 
-     $file = $content;
 
-   }
 
-   if (isset($file) && (@is_file($file) || $content)) {
 
-     $public_path = file_default_scheme() . '://';
 
-     $no_access = !user_access('send arbitrary files');
 
-     $not_in_public_path = strpos(drupal_realpath($file), drupal_realpath($public_path)) !== 0;
 
-     if (@is_file($file) && $not_in_public_path && $no_access) {
 
-       return $url;
 
-     }
 
-     if (!$name) {
 
-       $name = (@is_file($file)) ? basename($file) : 'attachment.dat';
 
-     }
 
-     if (!$type) {
 
-       $type = ($name) ? file_get_mimetype($name) : file_get_mimetype($file);
 
-     }
 
-     $id = md5($file) .'@'. $_SERVER['HTTP_HOST'];
 
-     // Prevent duplicate items.
 
-     if (isset($ids[$id])) {
 
-       return 'cid:'. $ids[$id];
 
-     }
 
-     $new_file = array(
 
-       'name' => $name,
 
-       'file' => $file,
 
-       'Content-ID' => $id,
 
-       'Content-Disposition' => $disposition,
 
-       'Content-Type' => $type,
 
-     );
 
-     $files[] = $new_file;
 
-     $ids[$id] = $id;
 
-     return 'cid:' . $id;
 
-   }
 
-   // The $file does not exist and no $content, return the $url if possible.
 
-   elseif ($url) {
 
-     return $url;
 
-   }
 
-   $ret = $files;
 
-   $files = array();
 
-   $ids = array();
 
-   return $ret;
 
- }
 
- /**
 
-  * Build a multipart body.
 
-  *
 
-  * @param array $parts
 
-  *   An associative array containing the parts to be included:
 
-  *   - name: A string containing the name of the attachment.
 
-  *   - content: A string containing textual content.
 
-  *   - file: A string containing file content.
 
-  *   - Content-Type: A string containing the content type of either file or content. Mandatory
 
-  *     for content, optional for file. If not present, it will be derived from file the file if
 
-  *     mime_content_type is available. If not, application/octet-stream is used.
 
-  *   - Content-Disposition: (optional) A string containing the disposition. Defaults to inline.
 
-  *   - Content-Transfer-Encoding: (optional) Base64 is assumed for files, 8bit for other content.
 
-  *   - Content-ID: (optional) for in-mail references to attachements.
 
-  *   Name is mandatory, one of content and file is required, they are mutually exclusive.
 
-  * @param string $content_type
 
-  *   (optional) A string containing the content-type for the combined message. Defaults to
 
-  *   multipart/mixed.
 
-  *
 
-  * @return array
 
-  *   An associative array containing the following elements:
 
-  *   - body: A string containing the MIME-encoded multipart body of a mail.
 
-  *   - headers: An array that includes some headers for the mail to be sent.
 
-  */
 
- function mimemail_multipart_body($parts, $content_type = 'multipart/mixed; charset=utf-8', $sub_part = FALSE) {
 
-   // Control variable to avoid boundary collision.
 
-   static $part_num = 0;
 
-   $boundary = sha1(uniqid($_SERVER['REQUEST_TIME'], TRUE)) . $part_num++;
 
-   $body = '';
 
-   $headers = array(
 
-     'Content-Type' => "$content_type; boundary=\"$boundary\"",
 
-   );
 
-   if (!$sub_part) {
 
-     $headers['MIME-Version'] = '1.0';
 
-     $body = "This is a multi-part message in MIME format.\n";
 
-   }
 
-   foreach ($parts as $part) {
 
-     $part_headers = array();
 
-     if (isset($part['Content-ID'])) {
 
-       $part_headers['Content-ID'] = '<' . $part['Content-ID'] . '>';
 
-     }
 
-     if (isset($part['Content-Type'])) {
 
-       $part_headers['Content-Type'] = $part['Content-Type'];
 
-     }
 
-     if (isset($part['Content-Disposition'])) {
 
-       $part_headers['Content-Disposition'] = $part['Content-Disposition'];
 
-     }
 
-     elseif (strpos($part['Content-Type'], 'multipart/alternative') === FALSE) {
 
-       $part_headers['Content-Disposition'] = 'inline';
 
-     }
 
-     if (isset($part['Content-Transfer-Encoding'])) {
 
-       $part_headers['Content-Transfer-Encoding'] = $part['Content-Transfer-Encoding'];
 
-     }
 
-     // Mail content provided as a string.
 
-     if (isset($part['content']) && $part['content']) {
 
-       if (!isset($part['Content-Transfer-Encoding'])) {
 
-         $part_headers['Content-Transfer-Encoding'] = '8bit';
 
-       }
 
-       $part_body = $part['content'];
 
-       if (isset($part['name'])) {
 
-         $part_headers['Content-Type'] .= '; name="' . $part['name'] . '"';
 
-         $part_headers['Content-Disposition'] .= '; filename="' . $part['name'] . '"';
 
-       }
 
-     // Mail content references in a filename.
 
-     }
 
-     else {
 
-       if (!isset($part['Content-Transfer-Encoding'])) {
 
-         $part_headers['Content-Transfer-Encoding'] = 'base64';
 
-       }
 
-       if (!isset($part['Content-Type'])) {
 
-         $part['Content-Type'] = file_get_mimetype($part['file']);
 
-       }
 
-       if (isset($part['name'])) {
 
-         $part_headers['Content-Type'] .= '; name="' . $part['name'] . '"';
 
-         $part_headers['Content-Disposition'] .= '; filename="' . $part['name'] . '"';
 
-       }
 
-       if (isset($part['file'])) {
 
-         $file = (is_file($part['file'])) ? file_get_contents($part['file']) : $part['file'];
 
-         $part_body = chunk_split(base64_encode($file), 76, variable_get('mimemail_crlf', "\n"));
 
-       }
 
-     }
 
-     $body .= "\n--$boundary\n";
 
-     $body .= mimemail_rfc_headers($part_headers) . "\n\n";
 
-     $body .= isset($part_body) ? $part_body : '';
 
-   }
 
-   $body .= "\n--$boundary--\n";
 
-   return array('headers' => $headers, 'body' => $body);
 
- }
 
- /**
 
-  * Callback for preg_replace_callback().
 
-  */
 
- function _mimemail_expand_links($matches) {
 
-   return $matches[1] . _mimemail_url($matches[2]);
 
- }
 
- /**
 
-  * Generate a multipart message body with a text alternative for some HTML text.
 
-  *
 
-  * @param string $body
 
-  *   The HTML message body.
 
-  * @param string $subject
 
-  *   The message subject.
 
-  * @param boolean $plain
 
-  *   (optional) Whether the recipient prefers plaintext-only messages. Defaults to FALSE.
 
-  * @param string $plaintext
 
-  *   (optional) The plaintext message body.
 
-  * @param array $attachments
 
-  *   (optional) The files to be attached to the message.
 
-  *
 
-  * @return array
 
-  *   An associative array containing the following elements:
 
-  *   - body: A string containing the MIME-encoded multipart body of a mail.
 
-  *   - headers: An array that includes some headers for the mail to be sent.
 
-  *
 
-  * The first mime part is a multipart/alternative containing mime-encoded sub-parts for
 
-  * HTML and plaintext. Each subsequent part is the required image or attachment.
 
-  */
 
- function mimemail_html_body($body, $subject, $plain = FALSE, $plaintext = NULL, $attachments = array()) {
 
-   if (empty($plaintext)) {
 
-     // @todo Remove once filter_xss() can handle direct descendant selectors in inline CSS.
 
-     // @see http://drupal.org/node/1116930
 
-     // @see http://drupal.org/node/370903
 
-     // Pull out the message body.
 
-     preg_match('|<body.*?</body>|mis', $body, $matches);
 
-     $plaintext = drupal_html_to_text($matches[0]);
 
-   }
 
-   if ($plain) {
 
-     // Plain mail without attachment.
 
-     if (empty($attachments)) {
 
-       $content_type = 'text/plain';
 
-       return array(
 
-         'body' => $plaintext,
 
-         'headers' => array('Content-Type' => 'text/plain; charset=utf-8'),
 
-       );
 
-     }
 
-     // Plain mail with attachement.
 
-     else {
 
-       $content_type = 'multipart/mixed';
 
-       $parts = array(array(
 
-       'content' => $plaintext,
 
-         'Content-Type' => 'text/plain; charset=utf-8',
 
-       ));
 
-     }
 
-   }
 
-   else {
 
-     $content_type = 'multipart/mixed';
 
-     $plaintext_part = array('Content-Type' => 'text/plain; charset=utf-8', 'content' => $plaintext);
 
-     // Expand all local links.
 
-     $pattern = '/(<a[^>]+href=")([^"]*)/mi';
 
-     $body = preg_replace_callback($pattern, '_mimemail_expand_links', $body);
 
-     $mime_parts = mimemail_extract_files($body);
 
-     $content = array($plaintext_part, array_shift($mime_parts));
 
-     $content = mimemail_multipart_body($content, 'multipart/alternative', TRUE);
 
-     $parts = array(array('Content-Type' => $content['headers']['Content-Type'], 'content' => $content['body']));
 
-     if ($mime_parts) {
 
-       $parts = array_merge($parts, $mime_parts);
 
-       $content = mimemail_multipart_body($parts, 'multipart/related; type="multipart/alternative"', TRUE);
 
-       $parts = array(array('Content-Type' => $content['headers']['Content-Type'], 'content' => $content['body']));
 
-     }
 
-   }
 
-   if (is_array($attachments) && !empty($attachments)) {
 
-     foreach ($attachments as $a) {
 
-       $a = (object) $a;
 
-       $path = isset($a->uri) ? $a->uri : (isset($a->filepath) ? $a->filepath : NULL);
 
-       $content = isset($a->filecontent) ? $a->filecontent : NULL;
 
-       $name = isset($a->filename) ? $a->filename : NULL;
 
-       $type = isset($a->filemime) ? $a->filemime : NULL;
 
-       _mimemail_file($path, $content, $name, $type, 'attachment');
 
-       $parts = array_merge($parts, _mimemail_file());
 
-     }
 
-   }
 
-   return mimemail_multipart_body($parts, $content_type);
 
- }
 
- /**
 
-  * Helper function to format URLs.
 
-  *
 
-  * @param string $url
 
-  *   The file path.
 
-  * @param boolean $to_embed
 
-  *   (optional) Wheter the URL is used to embed the file. Defaults to NULL.
 
-  *
 
-  * @return string
 
-  *   A processed URL.
 
-  */
 
- function _mimemail_url($url, $to_embed = NULL) {
 
-   global $base_url;
 
-   $url = urldecode($url);
 
-   $to_link = variable_get('mimemail_linkonly', 0);
 
-   $is_image = preg_match('!\.(png|gif|jpg|jpeg)!i', $url);
 
-   $is_absolute = file_uri_scheme($url) != FALSE || preg_match('!(mailto|callto|tel)\:!', $url);
 
-   if (!$to_embed) {
 
-     if ($is_absolute) {
 
-       return str_replace(' ', '%20', $url);
 
-     }
 
-   }
 
-   else {
 
-     $url = preg_replace('!^' . base_path() . '!', '', $url, 1);
 
-     if ($is_image) {
 
-       if ($to_link) {
 
-         // Exclude images from embedding if needed.
 
-         $url = file_create_url($url);
 
-         $url = str_replace(' ', '%20', $url);
 
-       }
 
-       else {
 
-         // Remove security token from URL, this allows for styled image embedding.
 
-         // @see https://drupal.org/drupal-7.20-release-notes
 
-         $url = preg_replace('/\\?itok=.*$/', '', $url);
 
-       }
 
-     }
 
-     return $url;
 
-   }
 
-   $url = str_replace('?q=', '', $url);
 
-   @list($url, $fragment) = explode('#', $url, 2);
 
-   @list($path, $query) = explode('?', $url, 2);
 
-   // If we're dealing with an intra-document reference, return it.
 
-   if (empty($path)) {
 
-     return '#' . $fragment;
 
-   }
 
-   // Get a list of enabled languages.
 
-   $languages = language_list('enabled');
 
-   $languages = $languages[1];
 
-   // Default language settings.
 
-   $prefix = '';
 
-   $language = language_default();
 
-   // Check for language prefix.
 
-   $args = explode('/', $path);
 
-   foreach ($languages as $lang) {
 
-     if ($args[0] == $lang->prefix) {
 
-       $prefix = array_shift($args);
 
-       $language = $lang;
 
-       $path = implode('/', $args);
 
-       break;
 
-     }
 
-   }
 
-   $options = array(
 
-     'query' => ($query) ? drupal_get_query_array($query) : array(),
 
-     'fragment' => $fragment,
 
-     'absolute' => TRUE,
 
-     'language' => $language,
 
-     'prefix' => $prefix,
 
-   );
 
-   $url = url($path, $options);
 
-   // If url() added a ?q= where there should not be one, remove it.
 
-   if (preg_match('!^\?q=*!', $url)) {
 
-     $url = preg_replace('!\?q=!', '', $url);
 
-   }
 
-   $url = str_replace('+', '%2B', $url);
 
-   return $url;
 
- }
 
- /**
 
-  * Formats an address string.
 
-  *
 
-  * @todo Could use some enhancement and stress testing.
 
-  *
 
-  * @param mixed $address
 
-  *   A user object, a text email address or an array containing name, mail.
 
-  * @param boolean $simplify
 
-  *   Determines if the address needs to be simplified. Defaults to FALSE.
 
-  *
 
-  * @return string
 
-  *   A formatted address string or FALSE.
 
-  */
 
- function mimemail_address($address, $simplify = FALSE) {
 
-   if (is_array($address)) {
 
-     // It's an array containing 'mail' and/or 'name'.
 
-     if (isset($address['mail'])) {
 
-       $output = '';
 
-       if (empty($address['name']) || $simplify) {
 
-         return $address['mail'];
 
-       }
 
-       else {
 
-         return '"' . addslashes(mime_header_encode($address['name'])) . '" <' . $address['mail'] . '>';
 
-       }
 
-     }
 
-     // It's an array of address items.
 
-     $addresses = array();
 
-     foreach ($address as $a) {
 
-       $addresses[] = mimemail_address($a);
 
-     }
 
-     return $addresses;
 
-   }
 
-   // It's a user object.
 
-   if (is_object($address) && isset($address->mail)) {
 
-     if (empty($address->name) || $simplify) {
 
-       return $address->mail;
 
-     }
 
-     else {
 
-       return '"' . addslashes(mime_header_encode($address->name)) . '" <' . $address->mail . '>';
 
-     }
 
-   }
 
-   // It's formatted or unformatted string.
 
-   // @todo: shouldn't assume it's valid - should try to re-parse
 
-   if (is_string($address)) {
 
-     return $address;
 
-   }
 
-   return FALSE;
 
- }
 
 
  |