=== modified file 'modules/contact/contact.module'
--- modules/contact/contact.module	2008-12-06 09:02:33 +0000
+++ modules/contact/contact.module	2009-07-02 00:08:11 +0000
@@ -36,7 +36,7 @@
  * Implementation of hook_perm
  */
 function contact_perm() {
-  return array('access site-wide contact form', 'administer site-wide contact form');
+  return array('access site-wide contact form', 'administer site-wide contact form', 'access personal contact form');
 }
 /**
  * Implementation of hook_menu().
@@ -118,9 +118,9 @@
     $account->contact = FALSE;
   }
   return
-    $account && $user->uid &&
+    $account &&
     (
-      ($user->uid != $account->uid && $account->contact) ||
+      (user_access('access personal contact form') && ($user->uid != $account->uid) && $account->contact) ||
       user_access('administer users')
     );
 }
@@ -169,13 +169,14 @@
     case 'page_mail':
     case 'page_copy':
       $contact = $params['contact'];
-      $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language);
-      $message['body'][] = t("!name sent a message using the contact form at !form.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language))), $language->language);
+      $message['subject'] .= t('[!site/!category] !subject', array('!site' => variable_get('site_name', 'Drupal'), '!category' => $contact['category'], '!subject' => $params['subject']), $language->language);
+      $message['body'][] = t("!name sent a message using the contact form (!form) at !site.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language);
+      $message['body'][] = t('Message:', NULL, $language->language);
       $message['body'][] = $params['message'];
       break;
     case 'page_autoreply':
       $contact = $params['contact'];
-      $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language);
+      $message['subject'] .= t('[!site/!category] !subject', array('!site' => variable_get('site_name', 'Drupal'), '!category' => $contact['category'], '!subject' => $params['subject']), $language->language);
       $message['body'][] = $contact['reply'];
       break;
     case 'user_mail':
@@ -189,5 +190,14 @@
       $message['body'][] = t('Message:', NULL, $language->language);
       $message['body'][] = $params['message'];
       break;
+    case 'user_mail_anon':
+      $account = $params['account'];
+      $message['subject'] .= '['. variable_get('site_name', 'Drupal') .'] '. $params['subject'];
+      $message['body'][] = "$account->name,";
+      $message['body'][] = t("!name has sent you a message via your contact form (!form-url) at !site.", array('!name' => $params['name'], '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language);
+      $message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE, 'language' => $language))), $language->language);
+      $message['body'][] = t('Message:', NULL, $language->language);
+      $message['body'][] = $params['message'];
+      break;
   }
 }

=== modified file 'modules/contact/contact.pages.inc'
--- modules/contact/contact.pages.inc	2009-04-30 00:36:53 +0000
+++ modules/contact/contact.pages.inc	2009-07-04 19:49:08 +0000
@@ -157,7 +157,7 @@
 function contact_user_page($account) {
   global $user;
 
-  if (!valid_email_address($user->mail)) {
+  if ($user->uid && !valid_email_address($user->mail)) {
     $output = t('You need to provide a valid e-mail address to contact other users. Please update your <a href="@url">user information</a> and try again.', array('@url' => url("user/$user->uid/edit")));
   }
   else if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
@@ -173,12 +173,25 @@
 
 function contact_mail_user(&$form_state, $recipient) {
   global $user;
-  $form['#token'] = $user->name . $user->mail;
+  $form['#token'] = $user->uid ? $user->name . $user->mail : '';
   $form['recipient'] = array('#type' => 'value', '#value' => $recipient);
-  $form['from'] = array('#type' => 'item',
-    '#title' => t('From'),
-    '#value' => theme('username', $user) .' &lt;'. check_plain($user->mail) .'&gt;',
-  );
+  if (!($user->uid)) {
+    $form['name'] = array('#type' => 'textfield',
+      '#title' => t('Your name'),
+      '#maxlength' => 255,
+      '#required' => TRUE,
+    );
+    $form['mail'] = array('#type' => 'textfield',
+      '#title' => t('Your e-mail address'),
+      '#maxlength' => 255,
+      '#required' => TRUE,
+    );
+  } else {
+    $form['from'] = array('#type' => 'item',
+      '#title' => t('From'),
+      '#value' => theme('username', $user) .' &lt;'. check_plain($user->mail) .'&gt;',
+    );
+  }
   $form['to'] = array('#type' => 'item',
     '#title' => t('To'),
     '#value' => theme('username', $recipient),
@@ -193,9 +206,13 @@
     '#rows' => 15,
     '#required' => TRUE,
   );
-  $form['copy'] = array('#type' => 'checkbox',
-    '#title' => t('Send yourself a copy.'),
-  );
+  // We do not allow anonymous users to send themselves a copy
+  // because it can be abused to spam people.
+  if ($user->uid) {
+    $form['copy'] = array('#type' => 'checkbox',
+      '#title' => t('Send yourself a copy.'),
+    );
+  }
   $form['submit'] = array('#type' => 'submit',
     '#value' => t('Send e-mail'),
   );
@@ -203,34 +220,64 @@
 }
 
 /**
+ * Validate the personal contact page form submission.
+ */
+function contact_mail_user_validate($form, &$form_state) {
+  global $user;
+  if (!($user->uid) && !valid_email_address($form_state['values']['mail'])) {
+    form_set_error('mail', t('You must enter a valid e-mail address.'));
+  }
+}
+
+/**
  * Process the personal contact page form submission.
  */
 function contact_mail_user_submit($form, &$form_state) {
   global $user, $language;
 
-  $account = $form_state['values']['recipient'];
+  // Save both users and all form values for email composition.
+  $values = $form_state['values'];
+  $account = $values['recipient'];
+  $values['account'] = $account;
 
   // Send from the current user to the requested user.
   $to = $account->mail;
-  $from = $user->mail;
-
-  // Save both users and all form values for email composition.
-  $values = $form_state['values'];
-  $values['account'] = $account;
-  $values['user'] = $user;
-
-  // Send the e-mail in the requested user language.
-  drupal_mail('contact', 'user_mail', $to, user_preferred_language($account), $values, $from);
-
-  // Send a copy if requested, using current page language.
-  if ($form_state['values']['copy']) {
-    drupal_mail('contact', 'user_copy', $from, $language, $values, $from);
+
+  if ($user->uid) {
+    $from = $user->mail;
+    $values['user'] = $user;
+
+    // Send the e-mail in the requested user language.
+    drupal_mail('contact', 'user_mail', $to, user_preferred_language($account), $values, $from);
+
+    // Send a copy if requested, using current page language.
+    if ($form_state['values']['copy']) {
+      drupal_mail('contact', 'user_copy', $from, $language, $values, $from);
+    }
+
+    // Back to the requested users profile page.
+    $form_state['redirect'] = "user/$account->uid";
+
+  } else {
+    $from = $values['mail'];
+
+    // Send the e-mail in the requested user language.
+    drupal_mail('contact', 'user_mail_anon', $to, user_preferred_language($account), $values, $from);
+
+    // Jump to home page rather than back to contact page to avoid
+    // contradictory messages if flood control has been activated.
+    $form_state['redirect'] = '';
   }
 
   flood_register_event('contact');
-  watchdog('mail', '%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name));
+  if ($user->uid) {
+    watchdog('mail', '%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name));
+  }
+  else {
+    watchdog('mail', '%name-from sent %name-to an e-mail.', array(
+      '%name-from' => $form_state['values']['name'] . ' <' . $form_state['values']['mail'] . '>',
+      '%name-to' => $account->name));
+  }
+
   drupal_set_message(t('The message has been sent.'));
-
-  // Back to the requested users profile page.
-  $form_state['redirect'] = "user/$account->uid";
 }

