Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.622
diff -u -p -r1.622 common.inc
--- includes/common.inc	26 Mar 2007 01:11:23 -0000	1.622
+++ includes/common.inc	26 Mar 2007 01:33:34 -0000
@@ -1983,58 +1983,96 @@ function page_set_cache() {
  *   FALSE otherwise.
  */
 function drupal_mail($mailkey, $to, $subject, $body, $from = NULL, $headers = array()) {
-  $defaults = array(
+  if (!valid_email_address($from)) {
+    $from = array(
+      'name' => variable_get('site_name', 'Drupal'),
+      'mail' => variable_get('site_mail', ini_get('sendmail_from')),
+    );
+  }
+
+  // Convert to a consistent address format.
+  $from = drupal_mail_address($from);
+  $to   = drupal_mail_address($to);
+
+  $default_headers = array(
     'MIME-Version' => '1.0',
     'Content-Type' => 'text/plain; charset=UTF-8; format=flowed',
     'Content-Transfer-Encoding' => '8Bit',
-    'X-Mailer' => 'Drupal'
+    'X-Mailer' => 'Drupal',
+    'From' => $from['address'],
+    'Reply-To' => $from['mail'], 
+    'Return-Path' => $from['mail'],
+    'Errors-To' => $from['mail'],
   );
-  if (isset($from)) {
-    $defaults['From'] = $defaults['Reply-To'] = $defaults['Return-Path'] = $defaults['Errors-To'] = $from;
+
+  // Assume multiple recipients.
+  if(!is_array($to)) {
+    $to = array($to);
   }
-  $headers = array_merge($defaults, $headers);
 
-  // Bundle up the variables into a structured array for altering.
-  $message = array('#mail_id' => $mailkey, '#to' => $to, '#subject' => $subject, '#body' => $body, '#from' => $from, '#headers' => $headers);
-  drupal_alter('mail', $message);
-  list($mailkey, $to, $subject, $body, $from, $headers) = $message;
+  $message = array(
+    '#mail_id' => $mailkey,
+    '#to' => $to,
+    '#subject' => $subject,
+    '#body' => $body,
+    '#from' => $from,
+    '#headers' => array_merge($default_headers, $headers),
+  );
 
-  // Allow for custom mail backend
-  if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) {
-    include_once './' . variable_get('smtp_library', '');
-    return drupal_mail_wrapper($mailkey, $to, $subject, $body, $from, $headers);
+  drupal_alter('mail', $message, $mailkey);
+
+  $message['#subject'] = mime_header_encode($subject);
+  foreach ($message['#headers'] as $key => $val) {
+    $message['#headers'][$key] = mime_header_encode($val);
   }
-  else {
-    /*
-    ** Note: if you are having problems with sending mail, or mails look wrong
-    ** when they are received you may have to modify the str_replace to suit
-    ** your systems.
-    **  - \r\n will work under dos and windows.
-    **  - \n will work for linux, unix and BSDs.
-    **  - \r will work for macs.
-    **
-    ** According to RFC 2646, it's quite rude to not wrap your e-mails:
-    **
-    ** "The Text/Plain media type is the lowest common denominator of
-    ** Internet e-mail, with lines of no more than 997 characters (by
-    ** convention usually no more than 80), and where the CRLF sequence
-    ** represents a line break [MIME-IMT]."
-    **
-    ** CRLF === \r\n
-    **
-    ** http://www.rfc-editor.org/rfc/rfc2646.txt
-    **
-    */
-    $mimeheaders = array();
-    foreach ($headers as $name => $value) {
-      $mimeheaders[] = $name .': '. mime_header_encode($value);
+
+  // Allow for custom mail backend
+  $engine = variable_get('mail_engine', 'system') .'_mailengine';
+  return $engine('send', $message, $mailkey);
+}
+
+/**
+ * Standardized mail address format
+ *
+ * @param $address
+ *   A user object, an  string containing an e-mail address.
+ * @return
+ *   An array containing mail, name, and address (RFC 822 format for use 
+ *   in mail headers)
+ */
+function drupal_mail_address($address) {
+  // It's a user object
+  if (is_object($address)) {
+    $address = array('name' => $address->name, 'mail' => $address->mail);
+  }
+  elseif (is_string($address)) {
+    $address = array('mail' => $address);
+  }
+
+  if (is_array($address)) {
+    // It's an array of address items
+    if (!isset($address['mail'])) {
+      $addresses = array();
+      foreach($address as $a) {
+        $addresses[] = drupal_mail_address($a);
+      }
+      return $addresses;
+    }
+    else {
+
+      // Already a valid address format.
+      if (isset($address['address'])) {
+        return $address;
+      }
+
+      if (!isset($address['name'])) {
+        $address['name'] = $address['mail'];
+      }
+
+      $address['address'] = '"'.addslashes($address['name']).'" <'.$address['mail'].'>';
+      return $address;
+
     }
-    return mail(
-      $to,
-      mime_header_encode($subject),
-      str_replace("\r", '', $body),
-      join("\n", $mimeheaders)
-    );
   }
 }
 
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.458
diff -u -p -r1.458 system.module
--- modules/system/system.module	26 Mar 2007 00:39:54 -0000	1.458
+++ modules/system/system.module	26 Mar 2007 01:33:35 -0000
@@ -231,6 +231,12 @@ function system_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_image_toolkit_settings'),
   );
+  $items['admin/settings/mail'] = array(
+    'title' => t('Mail'),
+    'description' => t('E-mail settings.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_mail_settings'),
+  );
   $items['admin/content/rss-publishing'] = array(
     'title' => t('RSS publishing'),
     'description' => t('Configure the number of items per feed and whether feeds should be titles/teasers/full-text.'),
@@ -528,12 +534,6 @@ function system_site_information_setting
     '#description' => t('The name of this website.'),
     '#required' => TRUE
   );
-  $form['site_mail'] = array(
-    '#type' => 'textfield',
-    '#title' => t('E-mail address'),
-    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
-    '#description' => t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.')
-  );
   $form['site_slogan'] = array(
     '#type' => 'textfield',
     '#title' => t('Slogan'),
@@ -753,6 +753,44 @@ function system_image_toolkit_settings()
   return system_settings_form($form);
 }
 
+function system_mail_settings() {
+
+  $form['site_mail'] = array(
+    '#type' => 'textfield',
+    '#title' => t('E-mail address'),
+    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
+    '#description' => t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.')
+  );
+
+  $mail_engines = array();
+  foreach (module_implements('mailengine') as $engine) {
+    $mail_engines[$engine] = array(
+      '#type' => 'radio',
+      '#name' => 'mail_engine',
+      '#return_value' => $engine,
+      '#value' => ($engine == variable_get('mail_engine', 'system')),
+      '#title' => module_invoke($engine, 'mailengine', 'name'),
+      '#description' => module_invoke($engine, 'mailengine', 'description'),
+    );
+  }
+
+  if (count($mail_engines) > 1) {
+    $form['mail_engine'] = array(
+      '#type' => 'radios',
+      '#title' => t('E-mail engine'),
+      '#description' => t('Choose an e-mail engine for sending mails from your site.'),
+      '#default_value' => variable_get('mail_engine', 'system'),
+      $mail_engines,
+    );
+  }
+  else {
+    $form['mail_engine'] = array( '#type' => 'value', '#value' => 'drupal');
+  }
+
+  $form['mail_settings'] = module_invoke(variable_get('mail_engine', 'system'), 'mailengine', 'settings');
+  return system_settings_form($form);
+}
+
 function system_rss_feeds_settings() {
 
   $form['feed_default_items'] = array(
@@ -2111,6 +2149,42 @@ function system_node_type($op, $info) {
 }
 
 /**
+ * Implementation of hook_mailengine().
+ *
+ * Delivers messages for drupal_mail() using mail().
+ */
+function system_mailengine($op, $message, $mailkey) {
+  switch ($op) {
+    case 'name':
+      return t('Drupal Mail');
+
+    case 'description':
+      return t("Default mailing engine using mail().");
+
+    case 'settings': 
+      return false;
+
+    case 'send':
+
+      $headers = '';
+      foreach ($message['#headers'] as $name => $value) {
+        $headers .= "$name: $value\n"; 
+      }
+
+      $status = true;
+      foreach ($message['#to'] as $a) {
+        $status = mail(
+          $a,
+          $message['#subject'],
+          $message['#body'],
+          $headers
+        ) && $status;
+      }
+      return $status;
+  }
+}
+
+/**
  * Output a confirmation form
  *
  * This function returns a complete form for confirming an action. A link is
