diff -u contact.orig/contact.module contact/contact.module
--- contact.orig/contact.module	2010-01-21 20:45:01.000000000 +0100
+++ contact/contact.module	2009-12-17 23:05:12.000000000 +0100
@@ -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().
@@ -121,8 +121,7 @@
 function _contact_user_tab_access($account) {
   global $user;
 
-  // Anonymous users cannot use or have contact forms.
-  if (!$user->uid || !$account->uid) {
+  if (!$account->uid) {
     return FALSE;
   }
 
@@ -132,7 +131,7 @@
   }
 
   // Users may not contact themselves.
-  if ($user->uid == $account->uid) {
+  if ($user->uid && $user->uid == $account->uid) {
     return FALSE;
   }
 
@@ -142,7 +141,7 @@
     return FALSE;
   }
 
-  return TRUE;
+  return user_access('access personal contact form');
 }
 
 /**
@@ -189,13 +188,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':
@@ -209,5 +209,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;
   }
 }
diff -u contact.orig/contact.pages.inc contact/contact.pages.inc
--- contact.orig/contact.pages.inc	2010-01-21 20:45:01.000000000 +0100
+++ contact/contact.pages.inc	2009-09-28 03:38:57.000000000 +0200
@@ -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'];
-
-  // 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'];
+  $account = $values['recipient'];
   $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 from the current user to the requested user.
+  $to = $account->mail;
 
-  // 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));
-  drupal_set_message(t('The message has been sent.'));
+  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));
+  }
 
-  // Back to the requested users profile page.
-  $form_state['redirect'] = "user/$account->uid";
+  drupal_set_message(t('The message has been sent.'));
 }
Common subdirectories: contact.orig/translations and contact/translations
