email.module 11.8 KB
Newer Older
Matthias Hutterer's avatar
Matthias Hutterer committed
1 2
<?php

Matthias Hutterer's avatar
Matthias Hutterer committed
3
// $Id$
Matthias Hutterer's avatar
Matthias Hutterer committed
4 5


6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/**
 * Implementation of hook_theme().
 */
function email_theme() {
  return array(
    'email_textfield' => array(
      'arguments' => array('element' => NULL),
    ),
    'email_formatter_default' => array(
      'arguments' => array('element' => NULL),
    ),
    'email_formatter_spamspan' => array(
      'arguments' => array('element' => NULL),
    ),
    'email_formatter_contact' => array(
      'arguments' => array('element' => NULL),
    ),
  );
}
Matthias Hutterer's avatar
Matthias Hutterer committed
25 26 27 28 29 30

/**
 * Implementation of hook_field_info().
 */
function email_field_info() {
  return array(
31
    'email' => array(
32
      'label' => 'Email',
33 34 35 36 37 38
      'callbacks' => array(
        'tables' => CONTENT_CALLBACK_DEFAULT,
        'arguments' => CONTENT_CALLBACK_DEFAULT,
      ),
    ),
  );
Matthias Hutterer's avatar
Matthias Hutterer committed
39 40 41 42 43 44 45
}


/**
 * Implementation of hook_field_settings().
 */
function email_field_settings($op, $field) {
46
  switch ($op) {
Matthias Hutterer's avatar
Matthias Hutterer committed
47
    case 'database columns':
48
      $columns['email'] = array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'sortable' => TRUE);
Matthias Hutterer's avatar
Matthias Hutterer committed
49 50 51 52
      return $columns;
  }
}

53 54 55
/**
 * Implementation of hook_field().
 */
56
function email_field($op, &$node, $field, &$items, $teaser, $page) {
57
  switch ($op) {
58 59
    case 'validate':
      if (is_array($items)) {
60 61 62
        foreach ($items as $delta => $item) {
          if ($item['email'] != '' && !valid_email_address(trim($item['email']))) {
            form_set_error($field['field_name'],t('"%mail" is not a valid email address',array('%mail' => $item['email'])));
63
          }
64 65 66
        }
     }
     break;
67 68 69

    case 'sanitize':
      foreach ($items as $delta => $item) {
70
        $items[$delta]['safe'] = check_plain($item['email']);
71 72 73 74 75 76 77 78 79 80 81 82 83 84
      }
      break;
  }
}

/**
 * Implementation of hook_content_is_empty().
 */
function email_content_is_empty($item, $field) {
  if (empty($item['email'])) {
    return TRUE;
  }
  return FALSE;
}
Matthias Hutterer's avatar
Matthias Hutterer committed
85

86 87 88 89 90
/**
 * Implementation of hook_field_formatter_info().
 *
 */
function email_field_formatter_info() {
91
  $formats = array(
92
    'default' => array(
93
      'label' => t('Default email link'),
94
      'field types' => array('email'),
95
      'multiple values' => CONTENT_HANDLE_CORE,
96 97
    ),
    'contact' => array(
98
      'label' => t('Email contact form'),
99
      'field types' => array('email'),
100
      'multiple values' => CONTENT_HANDLE_CORE,
101 102
    ),
  );
103 104 105 106 107 108 109
  if (module_exists('spamspan')) {
    $formats += array(
      'spamspan' => array(
        'label' => t('Email SpamSpan'),
        'field types' => array('email'),
        'multiple values' => CONTENT_HANDLE_CORE,
      ),
110 111 112
    );
  }
  return $formats;
113
}
Matthias Hutterer's avatar
Matthias Hutterer committed
114

115 116 117 118
/**
 * Theme function for 'default' email field formatter.
 */
function theme_email_formatter_default($element) {
119
  return !empty($element['#item']['safe']) ? '<a href="mailto:'. $element['#item']['email'] .'">'. $element['#item']['safe'] .'</a>' : '';
120 121 122 123 124 125
}

/**
 * Theme function for 'spamspan' email field formatter.
 */
function theme_email_formatter_spamspan($element) {
126 127 128
  if (empty($element['#item']['safe'])) {
    return '';
  }
129 130
  if (module_exists('spamspan')) {
    return spamspan($element['#item']['email']);
Matthias Hutterer's avatar
Matthias Hutterer committed
131 132
  }
  else {
133
    return '<a href="mailto:'. $element['#item']['email'] .'">'. $element['#item']['safe'] .'</a>';
Matthias Hutterer's avatar
Matthias Hutterer committed
134 135 136
  }
}

137 138 139 140
/**
 * Theme function for 'contact' email field formatter.
 */
function theme_email_formatter_contact($element) {
141
  return !empty($element['#item']['safe']) ? l(t('Email contact form'), 'email/'. $element['#node']->nid .'/'. $element['#field_name']) : '';
142 143
}

Matthias Hutterer's avatar
Matthias Hutterer committed
144 145 146 147 148 149

/**
 * Implementation of hook_widget_info().
 */
function email_widget_info() {
  return array(
150 151
    'email_textfield' => array(
      'label' => t('Text field'),
Matthias Hutterer's avatar
Matthias Hutterer committed
152
      'field types' => array('email'),
153 154 155 156
      'multiple values' => CONTENT_HANDLE_CORE,
      'callbacks' => array(
        'default value' => CONTENT_CALLBACK_DEFAULT,
      ),
Matthias Hutterer's avatar
Matthias Hutterer committed
157 158 159 160
    ),
  );
}

161 162 163 164 165 166 167 168 169 170 171 172 173
/**
 * Implementation of FAPI hook_elements().
 */
function email_elements() {
  return array(
    'email_textfield' => array(
      '#input' => TRUE,
      '#columns' => array('email'),
      '#delta' => 0,
      '#process' => array('email_textfield_process'),
    ),
  );
}
Matthias Hutterer's avatar
Matthias Hutterer committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

/**
 * Implementation of hook_widget_settings().
 */
function email_widget_settings($op, $widget) {
  switch ($op) {
    case 'form':
      $form = array();
      $form['size'] = array(
        '#type' => 'textfield',
        '#title' => t('Size'),
        '#default_value' => isset($widget['size']) ? $widget['size'] : 60,
        '#required' => FALSE,
        '#description' => t('Size of textfield'),
      );
189
      
Matthias Hutterer's avatar
Matthias Hutterer committed
190
      return $form;
Matthias Hutterer's avatar
Matthias Hutterer committed
191
      
Matthias Hutterer's avatar
Matthias Hutterer committed
192 193 194 195 196 197 198
    case 'validate':
      if (!empty($widget['size']) && (!is_numeric($widget['size']) || intval($widget['size']) != $widget['size'] || $widget['size'] <= 0)) {
        form_set_error('size', t('"Size" must be a positive integer.'));
      }
      break;

    case 'save':
199
      return array('size');
Matthias Hutterer's avatar
Matthias Hutterer committed
200 201 202 203 204 205
  }
}

/**
 * Implementation of hook_widget().
 */
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
function email_widget(&$form, &$form_state, $field, $items, $delta = 0) {
  $element = array(
    '#type' => $field['widget']['type'],
    '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
  );
  return $element;
}

/**
 * Process an individual element.
 */
function email_textfield_process($element, $edit, $form_state, $form) {
  $field = $form['#field_info'][$element['#field_name']];
  $field_key = $element['#columns'][0];
  $delta = $element['#delta'];
  $element[$field_key] = array(
    '#type' => 'textfield',
    '#title' => t($field['widget']['label']),
    '#description' => t($field['widget']['description']),
    '#required' => $element['#required'],
226
    '#maxlength' => 255,
227
    '#size' => isset($field['widget']['size']) ? $field['widget']['size'] : 60,
228 229 230 231 232 233 234 235 236 237
    '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
  );
  return $element;
}

/**
 * FAPI theme for an individual text elements.
 */
function theme_email_textfield($element) {
  return $element['#children'];
Matthias Hutterer's avatar
Matthias Hutterer committed
238 239
}

240 241 242
/**
 * Implementation of hook_menu().
 */
243 244 245 246 247
function email_menu() {
  $items['email/%/%'] = array(
    'title' => t('Email Contact Form'),
    'page callback' => 'email_mail_page',
    'page arguments' => array(1, 2),
248 249
    'access callback' => 'user_access',
    'access arguments' => array('access content'),
250 251
    'type' => MENU_CALLBACK,
  );
252 253 254
  return $items;
}

255

256 257 258
/**
 * The contact form page.
 */
259
function email_mail_page($nid, $field_name) {
260
  if (!is_numeric($nid)) {
261 262 263
    drupal_not_found();
    return;
  }
264 265 266 267 268 269
  if (module_exists('content_permissions')) {
    if (!user_access('view '. $field_name)) {
      drupal_not_found();
      return;
    }
  }
Matthias Hutterer's avatar
Matthias Hutterer committed
270
  $node = node_load(intval($nid));
271 272 273 274
  if (!$node) {
    drupal_not_found();
    return;
  }
275 276
  $field = $node->$field_name;
  $email = $field[0]['email'];
277
  $types = content_types($node->type);
278 279
  // Validate field name
  $types = content_types($node->type);
280 281 282 283 284
  if (empty($email) ||
      !isset($types['fields'][$field_name]) ||
      $types['fields'][$field_name]['type'] != 'email' ||
      ($types['fields'][$field_name]['display_settings']['teaser']['format'] != 'contact' &&
      $types['fields'][$field_name]['display_settings']['full']['format'] != 'contact')) {
285 286 287
    drupal_not_found();
    return;
  }
288

289 290 291 292 293

  if (!flood_is_allowed('email', variable_get('email_hourly_threshold', 3))) {
    $output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('email_hourly_threshold', 3)));
  }
  else {
294
    $output = drupal_get_form('email_mail_page_form', $node, $field_name, $email);
295 296 297 298 299
  }

  return $output;
}

300 301 302
/**
 * Contact form
 */
303
function email_mail_page_form($form_state, $node, $field_name, $email) {
Matthias Hutterer's avatar
Matthias Hutterer committed
304 305
  global $user;

306 307 308 309
  $form['node'] = array(
    '#type' => 'value',
    '#value' => $node,
  );
310
  $form['field_name'] = array(
311
    '#type' => 'value',
312 313 314 315 316
    '#value' => $field_name,
  );
  $form['email'] = array(
    '#type' => 'value',
    '#value' => $email,
317 318 319
  );
  $form['name'] = array(
    '#type' => 'textfield',
Matthias Hutterer's avatar
Matthias Hutterer committed
320 321
    '#title' => t('Your name'),
    '#maxlength' => 255,
322
    '#default_value' => $user->uid ? $user->name : '',
Matthias Hutterer's avatar
Matthias Hutterer committed
323 324
    '#required' => TRUE,
  );
325 326
  $form['mail'] = array(
    '#type' => 'textfield',
Matthias Hutterer's avatar
Matthias Hutterer committed
327 328
    '#title' => t('Your e-mail address'),
    '#maxlength' => 255,
329
    '#default_value' => $user->uid ? $user->mail : '',
Matthias Hutterer's avatar
Matthias Hutterer committed
330 331
    '#required' => TRUE,
  );
332 333
  $form['subject'] = array(
    '#type' => 'textfield',
Matthias Hutterer's avatar
Matthias Hutterer committed
334 335 336 337
    '#title' => t('Subject'),
    '#maxlength' => 255,
    '#required' => TRUE,
  );
338 339
  $form['message'] = array(
    '#type' => 'textarea',
Matthias Hutterer's avatar
Matthias Hutterer committed
340 341 342
    '#title' => t('Message'),
    '#required' => TRUE,
  );
343 344
  $form['submit'] = array(
    '#type' => 'submit',
Matthias Hutterer's avatar
Matthias Hutterer committed
345
    '#value' => t('Send e-mail'),
346 347
    '#validate' => array('email_mail_page_form_validate'),
    '#submit' => array('email_mail_page_form_submit'),
Matthias Hutterer's avatar
Matthias Hutterer committed
348 349 350 351
  );
  return $form;
}

352 353 354
/**
 * Validate the site-wide contact page form submission.
 */
355 356
function email_mail_page_form_validate($form, &$form_state) {
  if (!valid_email_address($form_state['values']['mail'])) {
357 358
    form_set_error('mail', t('You must enter a valid e-mail address.'));
  }
359
  if (preg_match("/\r|\n/", $form_state['values']['subject'])) {
Matthias Hutterer's avatar
Matthias Hutterer committed
360
    form_set_error('subject', t('The subject cannot contain linebreaks.'));
361
    watchdog('mail', 'Email injection exploit attempted in email form subject: '. check_plain($form_state['values']['subject']), WATCHDOG_NOTICE);
Matthias Hutterer's avatar
Matthias Hutterer committed
362
  }
363 364 365 366 367
}

/**
 * Process the site-wide contact page form submission.
 */
368 369
function email_mail_page_form_submit($form, &$form_state) {
  $node = $form_state['values']['node'];
370 371 372
  $field_name = $form_state['values']['field_name'];
  $email = $form_state['values']['email'];
  
373 374 375
  // E-mail address of the sender: as the form field is a text field,
  // all instances of \r and \n have been automatically stripped from it.

376 377 378 379 380 381 382 383
  $from = $form_state['values']['mail'];
 
  $params['node'] = $node;
  $params['subject'] = $form_state['values']['subject'];
  $params['name'] = $form_state['values']['name'];
  $params['message'] = $form_state['values']['message'];
  $params['url'] = url('node/' . $node->nid, array('absolute' => TRUE));
   
384
  // Send the e-mail to the recipients:
385 386
  drupal_mail('email', 'contact', $email, language_default(), $params, $from);
 
387 388
  // Log the operation:
  flood_register_event('email');
389 390
  watchdog('mail', t('%name-from sent an e-mail at %form.', array('%name-from' => theme('placeholder', $form_state['values']['name'] ." <$from>"), '%form' => url($_GET['q'], array('absolute' => TRUE)))));
 
391 392
  // Update user:
  drupal_set_message(t('Your message has been sent.'));
393
 
394
  // Jump to home page rather than back to contact page to avoid contradictory messages if flood control has been activated.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
  $form_state['redirect'] = 'node/'. $node->nid;
}

/**
 * Implementation of hook_mail()
 */
function email_mail($key, &$message, $params) {
  $language = $message['language'];
  switch($key) {
    case 'contact':
      $node = $params['node'];
      // Compose the body:
      $msg[] = t('@name sent a message using the contact form at @node.', array('@name' => $params['name'], '@node' => $params['url']), $language->language);
      $msg[] = $params['message'];

      // Tidy up the body:
      foreach ($msg as $index_key => $value) {
        $msg[$index_key] = wordwrap($value);
      }

      // Prepare the body:
      $message['body'] = implode("\n\n", $msg);
      
      $message['subject'] = t('[@title] @subject', array('@title' => preg_replace("/\r|\n/",'', $node->title), '@subject' => $params['subject']), $language->language);
      break;
  }
421
}
Matthias Hutterer's avatar
Matthias Hutterer committed
422 423 424 425 426 427 428


/**
 * Implementation of hook token_list
 */
function email_token_list($type = 'all') {
  if ($type == 'field' || $type == 'all') {
429 430
    $tokens['email']['raw']       = t('Raw email address');
    $tokens['email']['formatted'] = t('Formatted email address');
Matthias Hutterer's avatar
Matthias Hutterer committed
431 432 433 434 435 436 437 438 439 440
    return $tokens;
  }
}

/**
 * Implementation of hook token_values
 */ 
function email_token_values($type, $object = NULL, $options = array()) {
  if ($type == 'field') {
    $item = $object[0];
441 442
    $tokens['raw']       = $item['email'];
    $tokens['formatted'] = $item['view'];
Matthias Hutterer's avatar
Matthias Hutterer committed
443 444 445
    return $tokens;
  }
}