email.module 11.9 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

/**
 * Implementation of hook_widget_settings().
 */
function email_widget_settings($op, $widget) {
  switch ($op) {
    case 'form':
181
      $size = (isset($widget['size']) && is_numeric($widget['size'])) ? $widget['size'] : 60;
Matthias Hutterer's avatar
Matthias Hutterer committed
182
183
      $form['size'] = array(
        '#type' => 'textfield',
184
185
186
187
        '#title' => t('Size of textfield'),
        '#default_value' => $size,
        '#element_validate' => array('_email_widget_settings_size_validate'),
        '#required' => TRUE,
Matthias Hutterer's avatar
Matthias Hutterer committed
188
189
      );
      return $form;
Matthias Hutterer's avatar
Matthias Hutterer committed
190
      
Matthias Hutterer's avatar
Matthias Hutterer committed
191
    case 'save':
192
      return array('size');
Matthias Hutterer's avatar
Matthias Hutterer committed
193
194
195
  }
}

196
197
198
199
200
201
202
function _email_widget_settings_size_validate($element, &$form_state) {
  $value = $form_state['values']['size'];
  if (!is_numeric($value) || intval($value) != $value || $value <= 0) {
    form_error($element, t('"Size" must be a positive integer.'));
  }
}

Matthias Hutterer's avatar
Matthias Hutterer committed
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
228
    '#size' => !empty($field['widget']['size']) ? $field['widget']['size'] : 60,
    '#attributes' => array('class' => 'text'),
229
230
231
232
233
234
235
236
237
238
    '#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
239
240
}

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

256

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

290
291
292
293
294

  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 {
295
    $output = drupal_get_form('email_mail_page_form', $node, $field_name, $email);
296
297
298
299
300
  }

  return $output;
}

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

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

353
354
355
/**
 * Validate the site-wide contact page form submission.
 */
356
357
function email_mail_page_form_validate($form, &$form_state) {
  if (!valid_email_address($form_state['values']['mail'])) {
358
359
    form_set_error('mail', t('You must enter a valid e-mail address.'));
  }
360
  if (preg_match("/\r|\n/", $form_state['values']['subject'])) {
Matthias Hutterer's avatar
Matthias Hutterer committed
361
    form_set_error('subject', t('The subject cannot contain linebreaks.'));
362
    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
363
  }
364
365
366
367
368
}

/**
 * Process the site-wide contact page form submission.
 */
369
370
function email_mail_page_form_submit($form, &$form_state) {
  $node = $form_state['values']['node'];
371
372
373
  $field_name = $form_state['values']['field_name'];
  $email = $form_state['values']['email'];
  
374
375
376
  // 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.

377
378
379
380
381
382
383
384
  $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));
   
385
  // Send the e-mail to the recipients:
386
387
  drupal_mail('email', 'contact', $email, language_default(), $params, $from);
 
388
389
  // Log the operation:
  flood_register_event('email');
390
391
  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)))));
 
392
393
  // Update user:
  drupal_set_message(t('Your message has been sent.'));
394
 
395
  // Jump to home page rather than back to contact page to avoid contradictory messages if flood control has been activated.
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
421
  $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;
  }
422
}
Matthias Hutterer's avatar
Matthias Hutterer committed
423
424
425
426
427
428
429


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

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