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

/**
 * 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
function email_menu() {
  $items['email/%/%'] = array(
246
    'title' => 'Email Contact Form',
247
248
    '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
256
257
258
259
  $items['admin/settings/email'] = array(
    'title' => 'CCK Email Contact Form Settings',
    'description' => 'Administer flood control settings for email contact forms',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('email_admin_settings'),
    'access arguments' => array('administer site configuration'),
  );
260
261
262
  return $items;
}

263

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

297
298
299
300
301

  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 {
302
    $output = drupal_get_form('email_mail_page_form', $node, $field_name, $email);
303
304
305
306
307
  }

  return $output;
}

308
309
310
/**
 * Contact form
 */
311
function email_mail_page_form($form_state, $node, $field_name, $email) {
Matthias Hutterer's avatar
Matthias Hutterer committed
312
313
  global $user;

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

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

/**
 * Process the site-wide contact page form submission.
 */
376
377
function email_mail_page_form_submit($form, &$form_state) {
  $node = $form_state['values']['node'];
378
379
380
  $field_name = $form_state['values']['field_name'];
  $email = $form_state['values']['email'];
  
381
382
383
  // 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.

384
385
386
387
388
389
390
391
  $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));
   
392
  // Send the e-mail to the recipients:
393
394
  drupal_mail('email', 'contact', $email, language_default(), $params, $from);
 
395
396
  // Log the operation:
  flood_register_event('email');
397
398
  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)))));
 
399
400
  // Update user:
  drupal_set_message(t('Your message has been sent.'));
401
 
402
  // Jump to home page rather than back to contact page to avoid contradictory messages if flood control has been activated.
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
  $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;
  }
429
}
Matthias Hutterer's avatar
Matthias Hutterer committed
430
431
432
433
434
435
436


/**
 * Implementation of hook token_list
 */
function email_token_list($type = 'all') {
  if ($type == 'field' || $type == 'all') {
437
438
    $tokens['email']['raw']       = t('Raw email address');
    $tokens['email']['formatted'] = t('Formatted email address');
Matthias Hutterer's avatar
Matthias Hutterer committed
439
440
441
442
443
444
445
446
447
448
    return $tokens;
  }
}

/**
 * Implementation of hook token_values
 */ 
function email_token_values($type, $object = NULL, $options = array()) {
  if ($type == 'field') {
    $item = $object[0];
449
450
    $tokens['raw']       = $item['email'];
    $tokens['formatted'] = $item['view'];
Matthias Hutterer's avatar
Matthias Hutterer committed
451
452
453
    return $tokens;
  }
}
454
455
456
457
458
459
460
461
462
463
464
465
466

/**
 * Settings for contact form
 */
function email_admin_settings() {
  $form['email_hourly_threshold'] = array('#type' => 'select',
    '#title' => t('Hourly threshold for a CCK Email contact form'),
    '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50)),
    '#default_value' => variable_get('email_hourly_threshold', 3),
    '#description' => t('The maximum number of contact form submissions a user can perform per hour.'),
  );
  return system_settings_form($form);
}