Index: mimemail.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/mimemail/mimemail.inc,v retrieving revision 1.21 diff -u -r1.21 mimemail.inc --- mimemail.inc 26 Feb 2007 23:57:43 -0000 1.21 +++ mimemail.inc 26 Nov 2007 18:12:23 -0000 @@ -3,34 +3,34 @@ /** * @file - * Common mail functions for sending e-mail. Originally written by Gerhard. - * + * 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 - * + * TODO could use some enhancement and stress testing + * * @param $headers An array of headers * @return header string */ function mimemail_rfc_headers($headers) { $header = ''; - $crlf = variable_get("mimemail_crlf","\n"); + $crlf = variable_get('mimemail_crlf', "\n"); 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); - + $value = preg_replace('/(\s+|\n|\r|^\s|\s$)/', ' ', $value); + //fold headers if they're too long if (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); + $value = wordwrap($value, 50, "$crlf ", false); } } $header .= "$key: $value$crlf"; @@ -39,16 +39,16 @@ } /** - * Formats an address string - * TODO could use some enhancement and stress testing - * + * Formats an address string + * TODO could use some enhancement and stress testing + * * @param $address - a user object, a text email address or an array containing name, mail * @return formatted address string */ function mimemail_address($address) { - + if (is_array($address)) { - + // it's an array containing 'mail' and/or 'name' if (isset($address['mail'])) { $output = ''; @@ -58,7 +58,7 @@ return '"'.addslashes($address['name']).'" <'.$address['mail'].'>'; } } - + // it's an array of address items $addresses = array(); foreach($address as $a) { @@ -66,12 +66,12 @@ } return $addresses; } - + // it's a user object if (is_object($address) && isset($address->mail)) { return '"'.addslashes($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)) { @@ -95,7 +95,7 @@ * @param $headers An array of headers * @return header string. */ -function mimemail_headers($headers, $from='') { +function mimemail_headers($headers, $from = '') { // Note: This may not work. The MTA may rewrite the Return-Path, and Errors-To is deprecated. if (!$from) { $from = variable_get('site_mail', ini_get('sendmail_from')); @@ -112,7 +112,7 @@ * Converts html to utf-8 encoded text. * * @param $txt html text that needs formatting. - * @param $inline Optional. If TRUE put links in the text, + * @param $inline Optional. If TRUE put links in the text, * if FALSE put a footnote into the text and * a list of links below it. Default: FALSE * @@ -160,7 +160,7 @@ * 'name' => file name, * 'file' => reference to local file, * 'Content-ID' => generated Content-ID, - * 'Content-Type' => derived using mime_content_type + * 'Content-Type' => derived using mime_content_type * if available, educated guess otherwise * ) * ) @@ -168,15 +168,15 @@ function mimemail_extract_files($html) { $pattern = '/(]+href="?|]+codebase="?|@import |src="?)\/?([^"]+)("?)/emis'; $html = preg_replace($pattern,'"\\1". _mimemail_file("\\2") ."\\3"', $html); - + $document = array(array( 'Content-Type' => "text/html; charset=utf-8", 'Content-Transfer-Encoding' => 'base64', 'content' => chunk_split(base64_encode($html)), )); - + $files = _mimemail_file(); - + return array_merge($document, $files); } @@ -193,22 +193,23 @@ if ($file && !preg_match('@://|mailto:@', $file) && file_exists($file)) { $content_id = md5($file) .'@'. $_SERVER['HTTP_HOST']; - $new_file = array('name' => substr($file, strrpos($file, '/') + 1), - 'file' => $file, - 'Content-ID' => $content_id, - 'Content-Disposition' => $disposition, - ); - $new_file['Content-Type'] = _mimemail_mimetype($file,$type); + $new_file = array( + 'name' => substr($file, strrpos($file, '/') + 1), + 'file' => $file, + 'Content-ID' => $content_id, + 'Content-Disposition' => $disposition, + ); + $new_file['Content-Type'] = _mimemail_mimetype($file, $type); $files[] = $new_file; return 'cid:'. $content_id; } - + if ($file) { return $file; } - + $ret = $files; $files = array(); return $ret; @@ -216,7 +217,7 @@ /** * - * @param $parts + * @param $parts * an array of parts to be included * each part is itself an array: * array( @@ -245,39 +246,40 @@ * 'body' is the mime encoded multipart body of a mail. * 'headers' is 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) { +function mimemail_multipart_body($parts, $content_type = 'multipart/mixed; charset=utf-8', $sub_part = false) { $boundary = md5(uniqid(time())); $body = ''; + $part_body = ''; $headers = array( 'Content-Type' => "$content_type; boundary=\"$boundary\"", ); if (!$sub_part) { - $headers['MIME-Version'] = '1.0'; + $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']; } - else { + else { $part_headers['Content-Disposition'] = 'inline'; } - - if ($part['Content-Transfer-Encoding']) { + + if (!empty($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'])) { @@ -288,14 +290,14 @@ $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'] = _mimemail_mimetype($part['file'],$type); } @@ -304,10 +306,12 @@ $part_headers['Content-Type'] .= '; name="'.$part['name'].'"'; $part_headers['Content-Disposition'] .= '; filename="'.$part['name'].'"'; } - - $part_body = chunk_split(base64_encode(file_get_contents($part['file']))); + + if (isset($part['file'])) { + $part_body = chunk_split(base64_encode(file_get_contents($part['file']))); + } } - + $body .= "\n--$boundary\n"; $body .= mimemail_rfc_headers($part_headers)."\n\n"; $body .= $part_body; @@ -322,7 +326,7 @@ * @param $body An HTML message body * @param $subject The message subject * @param $plaintext Whether the recipient prefers plaintext-only messages (default false) - * + * * @return * an array containing the elements 'header' and 'body'. * 'body' is the mime encoded multipart body of a mail. @@ -332,30 +336,30 @@ * sub-parts for HTML and plaintext. Each subsequent part is the required * image/attachment */ -function mimemail_html_body($body, $subject, $plaintext=false, $text=null, $attachments = array()) { +function mimemail_html_body($body, $subject, $plaintext = false, $text = NULL, $attachments = array()) { if (is_null($text)) { //generate plaintext alternative $text = mimemail_html_to_text($body); } if ($plaintext) { return array( - 'body' => $text, - 'headers' => array('Content-Type' => 'text/plain; charset=utf-8'), + 'body' => $text, + 'headers' => array('Content-Type' => 'text/plain; charset=utf-8') ); } $content_type = 'multipart/alternative'; - $text_part = array('Content-Type'=>'text/plain; charset=utf-8','content'=>$text); - + $text_part = array('Content-Type' => 'text/plain; charset=utf-8', 'content' => $text); + //expand all local links $pattern = '/(]+href=")([^"]*)/emi'; $body = preg_replace($pattern, '"\\1"._mimemail_url("\2")', $body); - + $mime_parts = mimemail_extract_files($body); - $content = array($text_part,array_shift($mime_parts)); + $content = array($text_part, array_shift($mime_parts)); $content = mimemail_multipart_body($content, $content_type, true); - $parts = array(array('Content-Type'=>$content['headers']['Content-Type'],'content'=>$content['body'])); + $parts = array(array('Content-Type' => $content['headers']['Content-Type'], 'content' => $content['body'])); if ($mime_parts) { $content_type = 'multipart/related'; @@ -369,7 +373,7 @@ $parts = array_merge($parts, _mimemail_file()); } - return mimemail_multipart_body($parts,"$content_type; charset=utf-8"); + return mimemail_multipart_body($parts, "$content_type; charset=utf-8"); } /** @@ -379,10 +383,10 @@ function _mimemail_uri($href, $link) { $href = _mimemail_url($href); if ($href == $link) { - $output = '['.$href.']'; + $output = "[$href]"; } else { - $output = $link.' ['.$href.']'; + $output = "$link [$href]"; } return $output; } @@ -398,22 +402,22 @@ if (strpos($url, '://')) { return $url; } - + if (preg_match('!mailto:!i', $url)) { return str_replace('mailto:', '', $url); } - + $url = str_replace('?q=', '', ltrim($url, base_path())); list($url, $fragment) = explode('#', $url, 2); list($path, $query) = explode('?', $url, 2); - + return url($path, $query, $fragment, TRUE); } /** * Helper function to store processed urls. * - * @param $url Optional. + * @param $url Optional. * @param $refresh Optional. If TRUE refresh the cache. * * @return a count of stored if $url evaluates to false, the stored urls ortherwise. @@ -421,7 +425,7 @@ function _mimemail_urls($url = 0, $refresh = FALSE) { static $urls = array(); - if($refresh) { + if ($refresh) { $urls = array(); } @@ -482,25 +486,25 @@ } /** - * Attempt to determine the mimetime from or filename . While not ideal, + * Attempt to determine the mimetime from or filename . While not ideal, * using the filename as a fallback ensures that images will appear inline * in HTML messages * * @param $name Name of the file - * + * * @return best-guess mimetype string */ -function _mimemail_mimetype($file,$type='') { +function _mimemail_mimetype($file, $type = '') { if ($type) { return $type; - } + } if (function_exists('mime_content_type')) { return mime_content_type($file); } // some common embedded/attachment types - $types = Array( + $types = array( 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif', Index: mimemail.info =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/mimemail/mimemail.info,v retrieving revision 1.1 diff -u -r1.1 mimemail.info --- mimemail.info 5 Jan 2007 05:44:09 -0000 1.1 +++ mimemail.info 26 Nov 2007 18:12:23 -0000 @@ -1,4 +1,5 @@ ; $Id: mimemail.info,v 1.1 2007/01/05 05:44:09 vauxia Exp $ name = Mime Mail -description = E-mail with HTML and attachments +description = "E-mail with HTML and attachments" package = Mail +core = 6.x \ No newline at end of file Index: mimemail.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/mimemail/mimemail.module,v retrieving revision 1.18 diff -u -r1.18 mimemail.module --- mimemail.module 9 Apr 2007 17:03:24 -0000 1.18 +++ mimemail.module 26 Nov 2007 18:12:23 -0000 @@ -1,27 +1,28 @@ - 'admin/settings/mimemail', - 'title' => t('Mail'), - 'description' => t('HTML E-mail settings'), - 'callback' => 'drupal_get_form', - 'callback arguments' => 'mimemail_settings', - 'access' => user_access('administer site configuration'), + $items['admin/settings/mimemail'] = array( + 'title' => 'Mime Mail', + 'description' => 'HTML E-mail settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('mimemail_admin_settings'), + 'access callback' => 'user_access', + 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, - ); + ); return $items; } -function mimemail_settings() { +function mimemail_admin_settings() { // override the smtp_library value if mimemail is chosen to handle all mail // this will cause drupal_mail to call mimemail() @@ -37,14 +38,14 @@ } $engines = mimemail_get_engines(); - + $form = array(); $form['site_mail'] = array( - '#type' => 'textfield', - '#title' => t('E-mail address'), - '#default_value' => variable_get('site_mail', ini_get('sendmail_from')), - '#size' => 60, - '#maxlength' => 128, + '#type' => 'textfield', + '#title' => t('E-mail address'), + '#default_value' => variable_get('site_mail', ini_get('sendmail_from')), + '#size' => 60, + '#maxlength' => 128, '#description' => t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.') ); $form['mimemail']['mimemail_alter'] = array( @@ -59,34 +60,34 @@ '#default_value' => variable_get('mimemail_textonly', 0), '#description' => t('This option disables the use of email messages with graphics and styles. All messages will be converted to plain text.'), ); - + // hide the settings if only 1 engine is available if (count($engines) == 1) { variable_set('mimemail_engine',key($engines)); $form['mimemail_engine'] = array( - '#type' => 'hidden', - '#title' => t('E-mail engine'), - '#default_value' => variable_get('mimemail_engine', 'mail'), - '#options' => $engines, - '#description' => t('Choose an e-mail engine for sending mails from your site.') + '#type' => 'hidden', + '#title' => t('E-mail engine'), + '#default_value' => variable_get('mimemail_engine', 'mail'), + '#options' => $engines, + '#description' => t('Choose an e-mail engine for sending mails from your site.') ); } else { $form['mimemail_engine'] = array( - '#type' => 'select', - '#title' => t('E-mail engine'), - '#default_value' => variable_get('mimemail_engine', 'mail'), - '#options' => $engines, - '#description' => t('Choose an e-mail engine for sending mails from your site.') + '#type' => 'select', + '#title' => t('E-mail engine'), + '#default_value' => variable_get('mimemail_engine', 'mail'), + '#options' => $engines, + '#description' => t('Choose an e-mail engine for sending mails from your site.') ); } if (variable_get('mimemail_engine', 0)) { $settings = module_invoke(variable_get('mimemail_engine', 'mail'), 'mailengine', 'settings'); if ($settings) { - $form['mimemail_engine_settings'] = array( - '#type' => 'fieldset', - '#title' => t('Engine specific settings'), + $form['mimemail_engine_settings'] = array( + '#type' => 'fieldset', + '#title' => t('Engine specific settings'), ); foreach ($settings as $name => $value) { $form['mimemail_engine_settings'][$name] = $value; @@ -103,53 +104,52 @@ /** * Implementation of hook_user() */ -function mimemail_user($op, &$edit, &$user, $category='') { - if ( $op == 'form' && $category == 'account') { +function mimemail_user($op, &$edit, &$user, $category = '') { + if ($op == 'form' && $category == 'account') { $form = array(); - $form['mimemail'] = array( - '#type' => 'fieldset', - '#title' => t('Email settings'), - '#weight' => 5, - '#collapsible' => true, + $form['mail'] = array( + '#type' => 'fieldset', + '#title' => t('Email settings'), + '#weight' => 5, + '#collapsible' => true, ); - $form['mimemail']['mimemail_textonly'] = array( - '#type' => 'checkbox', - '#title' => t('Plaintext email only'), - '#default_value' => $user->mimemail_textonly, - '#description' => t('Check this option if you do not wish to receive email messages with graphics and styles'), + $form['mail']['mimemail_textonly'] = array( + '#type' => 'checkbox', + '#title' => t('Plaintext email only'), + '#default_value' => empty($user->mimemail_textonly) ? false : $user->mimemail_textonly, + '#description' => t('Check this option if you do not wish to receive email messages with graphics and styles'), ); return $form; - } - return; + } } /** * Send a mime-encoded email - * + * * @param $sender The email address or user object * @param $recipient An email address or user object * @param $subject An subject line string * @param $body An HTML body * @param $plaintext Whether to send message as plaintext only * @param $headers Optional e-mail headers in a keyed array * @param $text Optional plaintext portion of a multipart e-mail (instead of auto-generated) - * + * * @return result from mail() call */ -function mimemail_prepare($sender, $recipient, $subject, $body, $plaintext=null, $headers=array(), $text=null, $attachments=array()) { +function mimemail_prepare($sender, $recipient, $subject, $body, $plaintext = NULL, $headers = array(), $text = NULL, $attachments = array()) { require_once dirname(__FILE__).'/mimemail.inc'; if (is_null($sender)) { // use site default for sender $sender = array( - 'name' => variable_get('site_name', 'Drupal'), - 'mail' => variable_get('site_mail', ini_get('sendmail_from')), + 'name' => variable_get('site_name', 'Drupal'), + 'mail' => variable_get('site_mail', ini_get('sendmail_from')), ); } - + // try to determine recpient's text mail preference if (is_null($plaintext)) { if (is_object($recipient)) { - if(isset($recipient->mimemail_textonly)) { + if (isset($recipient->mimemail_textonly)) { $plaintext = $recipient->mimemail_textonly; } } @@ -161,10 +161,11 @@ } } $subject = mime_header_encode($subject); - + $plaintext = $plaintext || variable_get('mimemail_textonly', 0); $sender = mimemail_address($sender); - $mail = mimemail_html_body(theme('mimemail_message', $body), $subject, $plaintext, $text, $attachments); + $body = theme('mimemail_message', $body); + $mail = mimemail_html_body($body, $subject, $plaintext, $text, $attachments); $headers = array_merge($headers, $mail['headers']); $message = array( 'address' => mimemail_address($recipient), @@ -177,12 +178,26 @@ return $message; } -function mimemail($sender, $recipient, $subject, $body, $plaintext=null, $headers=array(), $text=null, $attachments=array()) { +/** + * Entrance function for processing mail information. Calls hook_mailengine(), + * which is custom to this module. + * + * @param string $sender + * @param string $recipient + * @param string $subject + * @param string $body + * @param ? $plaintext + * @param array $headers + * @param ? $text + * @param array $attachments + * @return bool + */ +function mimemail($sender, $recipient, $subject, $body, $plaintext = NULL, $headers = array(), $text = NULL, $attachments = array()) { $message = mimemail_prepare($sender, $recipient, $subject, $body, $plaintext, $headers, $text, $attachments); $engine = variable_get('mimemail_engine', 'mimemail') .'_mailengine'; - + if (!function_exists($engine)) { return false; } @@ -214,27 +229,27 @@ function mimemail_mailengine($op, $message = array()) { //default values $message = array_merge( array( - 'address' => '', - 'subject' => '', - 'body' => '', - 'sender' => '', - 'headers' => '', + 'address' => '', + 'subject' => '', + 'body' => '', + 'sender' => '', + 'headers' => '', ), $message); - + switch ($op) { case 'name': return t('Mime Mail'); - + case 'description': - return t("Default mailing engine using drupal_mail()."); - + return t('Default mailing engine using drupal_mail().'); + case 'settings': //not implemented return false; - + case 'multiple': case 'single': case 'send': - if(!is_array($message['address'])) { + if (!is_array($message['address'])) { $message['address'] = array($message['address']); } $status = true; @@ -245,7 +260,20 @@ $message['body'], mimemail_rfc_headers($message['headers']) ) && $status; - + + if ($status) { + watchdog('mail', 'Mail to %recipient was accepted for delivery', array('%recipient' => $a), WATCHDOG_DEBUG); + } + else { + watchdog('mail', + 'Mail to %recipient was not accepted for delivery. Message subject: %subject Message body: %body Message headers: %headers', + array( + '%recipient' => $a, + '%subject' => serialize($message['subject']), + '%body' => serialize($message['body']), + '%headers' => serialize(mimemail_rfc_headers($message['headers']))), + WATCHDOG_ERROR); + } } return $status; } @@ -259,27 +287,23 @@ function drupal_mail_wrapper($mailkey, $to, $subject, $body, $from, $headers) { return mimemail($from, $to, $subject, $body, null, $headers); } -} +} -function mimemail_mail_alter($mailkey, &$recipient, &$subject, &$body, &$sender, &$headers) { +function mimemail_mail_alter(&$message) { if (!variable_get('mimemail_alter', 0)) return; -/* - if ($mailkey == 'mimemail') return; - - $m = mimemail_prepare($sender, $recipient, $subject, $body, null, $headers); - - $body = $m['body']; - $headers = $m['headers']; - $recipient = $m['recipient']; - $sender = $m['sender']; - -*/ // attempt to fixup non-html messages that are being sent through drupal_mail // I'm open to suggestions for better ways of doing this - $body = check_markup($body, FILTER_FORMAT_DEFAULT); - return; + $message['body'] = check_markup($message['body'], FILTER_FORMAT_DEFAULT); +} + +function mimemail_theme() { + return array( + 'mimemail_message' => array( + 'arguments' => array('body' => NULL) + ) + ); } /** @@ -294,12 +318,12 @@ if (!file_exists($styles)) { // embed a version of all style definitions - $styles = preg_replace('|'; // compress output - return preg_replace('/\s+|\n|\r|^\s|\s$/',' ',$output); + return preg_replace('/\s+|\n|\r|^\s|\s$/', ' ', $output); }