email.module 11.2 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
32
33
34
35
36
37
38
    'email' => array(
      'label' => 'E-Mail',
      '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);
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 '<a href="mailto:'. $element['#item']['email'] .'">'. $element['#item']['safe'] .'</a>';
120
121
122
123
124
125
126
127
}

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

134
135
136
137
/**
 * Theme function for 'contact' email field formatter.
 */
function theme_email_formatter_contact($element) {
138
  return l(t('Email contact form'), 'email/'. $element['#node']->nid .'/'. $element['#field_name']);
139
140
}

Matthias Hutterer's avatar
Matthias Hutterer committed
141
142
143
144
145
146

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

158
159
160
161
162
163
164
165
166
167
168
169
170
/**
 * 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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

/**
 * 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'),
      );
186
      
Matthias Hutterer's avatar
Matthias Hutterer committed
187
      return $form;
Matthias Hutterer's avatar
Matthias Hutterer committed
188
      
Matthias Hutterer's avatar
Matthias Hutterer committed
189
190
191
192
193
194
195
    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':
196
      return array('size');
Matthias Hutterer's avatar
Matthias Hutterer committed
197
198
199
200
201
202
  }
}

/**
 * Implementation of hook_widget().
 */
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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'],
223
    '#maxlength' => 255,
224
225
226
227
228
229
230
231
232
233
    '#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
234
235
}

236
237
238
/**
 * Implementation of hook_menu().
 */
239
240
241
242
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),
    'access callback' => 'node_access',
    'access arguments' => array('view', 1),
    'type' => MENU_CALLBACK,
  );
248
249
250
  return $items;
}

251

252
253
254
/**
 * The contact form page.
 */
255
256
function email_mail_page($nid, $fieldname) {
  if (!is_numeric($nid)) {
257
258
259
    drupal_not_found();
    return;
  }
Matthias Hutterer's avatar
Matthias Hutterer committed
260
  $node = node_load(intval($nid));
261
262
263
264
  if (!$node) {
    drupal_not_found();
    return;
  }
265
  $types = content_types($node->type);
266
267
268
269
  // Validate field name
  $types = content_types($node->type);
  if (!isset($types['fields'][$fieldname]) ||
      $types['fields'][$fieldname]['type'] != 'email' ||
270
271
      ($types['fields'][$fieldname]['display_settings']['teaser']['format'] != 'contact' &&
      $types['fields'][$fieldname]['display_settings']['full']['format'] != 'contact')) {
272
273
274
    drupal_not_found();
    return;
  }
275

276
277
278
279
280

  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 {
281
    $output = drupal_get_form('email_mail_page_form', $node, $field);
282
283
284
285
286
  }

  return $output;
}

287
288
289
/**
 * Contact form
 */
290
function email_mail_page_form($form_state, $node, $field) {
Matthias Hutterer's avatar
Matthias Hutterer committed
291
292
  global $user;

293
294
295
296
297
298
299
300
301
302
303
  $form['node'] = array(
    '#type' => 'value',
    '#value' => $node,
  );
  $form['field'] = array(
    '#type' => 'value',
    '#value' => $field,
  );

  $form['name'] = array(
    '#type' => 'textfield',
Matthias Hutterer's avatar
Matthias Hutterer committed
304
305
    '#title' => t('Your name'),
    '#maxlength' => 255,
306
    '#default_value' => $user->uid ? $user->name : '',
Matthias Hutterer's avatar
Matthias Hutterer committed
307
308
    '#required' => TRUE,
  );
309
310
  $form['mail'] = array(
    '#type' => 'textfield',
Matthias Hutterer's avatar
Matthias Hutterer committed
311
312
    '#title' => t('Your e-mail address'),
    '#maxlength' => 255,
313
    '#default_value' => $user->uid ? $user->mail : '',
Matthias Hutterer's avatar
Matthias Hutterer committed
314
315
    '#required' => TRUE,
  );
316
317
  $form['subject'] = array(
    '#type' => 'textfield',
Matthias Hutterer's avatar
Matthias Hutterer committed
318
319
320
321
    '#title' => t('Subject'),
    '#maxlength' => 255,
    '#required' => TRUE,
  );
322
323
  $form['message'] = array(
    '#type' => 'textarea',
Matthias Hutterer's avatar
Matthias Hutterer committed
324
325
326
    '#title' => t('Message'),
    '#required' => TRUE,
  );
327
328
  $form['submit'] = array(
    '#type' => 'submit',
Matthias Hutterer's avatar
Matthias Hutterer committed
329
    '#value' => t('Send e-mail'),
330
331
    '#validate' => array('email_mail_page_form_validate'),
    '#submit' => array('email_mail_page_form_submit'),
Matthias Hutterer's avatar
Matthias Hutterer committed
332
333
334
335
  );
  return $form;
}

336
337
338
/**
 * Validate the site-wide contact page form submission.
 */
339
340
function email_mail_page_form_validate($form, &$form_state) {
  if (!valid_email_address($form_state['values']['mail'])) {
341
342
    form_set_error('mail', t('You must enter a valid e-mail address.'));
  }
343
  if (preg_match("/\r|\n/", $form_state['values']['subject'])) {
Matthias Hutterer's avatar
Matthias Hutterer committed
344
    form_set_error('subject', t('The subject cannot contain linebreaks.'));
345
    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
346
  }
347
348
349
350
351
}

/**
 * Process the site-wide contact page form submission.
 */
352
353
354
function email_mail_page_form_submit($form, &$form_state) {
  $node = $form_state['values']['node'];
  $field = $form_state['values']['field'];
355
  $email = $field[0]['email'];
356
357
  $types = content_types($node->type);
 
358
359
360
  // 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.

361
362
363
364
365
366
367
368
  $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));
   
369
  // Send the e-mail to the recipients:
370
371
  drupal_mail('email', 'contact', $email, language_default(), $params, $from);
 
372
373
  // Log the operation:
  flood_register_event('email');
374
375
  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)))));
 
376
377
  // Update user:
  drupal_set_message(t('Your message has been sent.'));
378
 
379
  // Jump to home page rather than back to contact page to avoid contradictory messages if flood control has been activated.
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  $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;
  }
406
}
Matthias Hutterer's avatar
Matthias Hutterer committed
407
408
409
410
411
412
413


/**
 * Implementation of hook token_list
 */
function email_token_list($type = 'all') {
  if ($type == 'field' || $type == 'all') {
414
415
    $tokens['email']['raw']       = t('Raw email address');
    $tokens['email']['formatted'] = t('Formatted email address');
Matthias Hutterer's avatar
Matthias Hutterer committed
416
417
418
419
420
421
422
423
424
425
    return $tokens;
  }
}

/**
 * Implementation of hook token_values
 */ 
function email_token_values($type, $object = NULL, $options = array()) {
  if ($type == 'field') {
    $item = $object[0];
426
427
    $tokens['raw']       = $item['email'];
    $tokens['formatted'] = $item['view'];
Matthias Hutterer's avatar
Matthias Hutterer committed
428
429
430
    return $tokens;
  }
}