array( 'label' => 'Email', 'description' => t('This field stores and renderes email addresses.'), 'default_widget' => 'text_textfield', 'default_formatter' => 'default', 'property_type' => 'text', ), ); } /** * Implements hook_field_validate(). * * Possible error codes: * - 'email_invalid': The email address is not valid */ function email_field_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) { foreach ($items as $delta => $item) { if ($item['email'] != '' && !valid_email_address(trim($item['email']))) { $message = t('"%mail" is not a valid email address', array('%mail' => $item['email'])); $errors[$field['field_name']][$langcode][$delta][] = array( 'error' => "email_invalid", 'message' => $message, ); } } } /** * Implements of hook_content_is_empty(). */ function email_field_is_empty($item, $field) { if (empty($item['email'])) { return TRUE; } return FALSE; } /** * Implements hook_field_formatter_info(). * */ function email_field_formatter_info() { $formats = array( 'default' => array( 'label' => t('Default email link'), 'field types' => array('email'), ), 'contact' => array( 'label' => t('Email contact form'), 'field types' => array('email'), ), 'plain' => array( 'label' => t('Email plain text'), 'field types' => array('email'), ), ); if (module_exists('spamspan')) { $formats += array( 'spamspan' => array( 'label' => t('Email SpamSpan'), 'field types' => array('email'), ), ); } return $formats; } /** * Implements hook_field_formatter_view(). */ function email_field_formatter_view($object_type, $object, $field, $instance, $langcode, $items, $display) { $element = array(); switch ($display['type']) { case 'default': foreach ($items as $delta => $item) { $output = l($item['email'], 'mailto:'. $item['email']); $element[$delta] = array('#markup' => $output); } break; case 'contact': $ids = entity_extract_ids($object_type, $object); foreach ($items as $delta => $item) { $element[$delta] = l(t('Email contact form'), 'email/'. $object_type .'/'. $ids[0] .'/'. $instance['field_name']); } break; case 'plain': foreach ($items as $delta => $item) { $element[$delta] = array('#markup' => check_plain($item['email'])); } break; case 'spamspan': foreach ($items as $delta => $item) { if (module_exists('spamspan')) { $element[$delta] = spamspan($item['email']); } else { $output = l($item['email'], 'mailto:'. $item['email']); $element[$delta] = array('#markup' => $output); } } break; } return $element; } /** * Implements hook_field_widget_info(). */ function email_field_widget_info() { return array( 'email_textfield' => array( 'label' => t('Text field'), 'field types' => array('email'), 'settings' => array('size' => 60), ), ); } /** * Implements hook_field_widget_settings_form(). */ function email_field_widget_settings_form($field, $instance) { $widget = $instance['widget']; $settings = $widget['settings']; $form['size'] = array( '#type' => 'textfield', '#title' => t('Size of textfield'), '#default_value' => $settings['size'], '#required' => TRUE, '#element_validate' => array('_element_validate_integer_positive'), ); return $form; } /** * Implements hook_field_widget_form(). */ function email_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) { $element = $base; $element['email'] = $base + array( '#type' => 'textfield', '#default_value' => isset($items[$delta]['email']) ? $items[$delta]['email'] : NULL, '#size' => $instance['widget']['settings']['size'], '#prefix' => '
', '#suffix' => '
', ); return $element; } /** * Implementation of hook_menu(). */ function email_menu() { $items['email/%/%/%'] = array( 'title' => 'Email Contact Form', 'page callback' => 'email_mail_page', 'page arguments' => array(1, 2, 3), 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); $items['admin/config/content/email'] = array( 'title' => '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'), ); return $items; } /** * The contact form page. */ function email_mail_page($object_type, $object_id, $field_name) { global $user; if (!is_numeric($object_id)) { drupal_not_found(); return; } //verify this is an email field $field_info = field_info_field($field_name); if ($field_info['type'] != 'email') { drupal_not_found(); return; } $objects = entity_load($object_type, array($object_id)); $object = $objects[$object_id]; //verify the object really exists if (!$object) { drupal_not_found(); return; } //check field perm if (module_exists('field_permissions')) { if (!field_permissions_field_access('view', $field_info, $object_type, $object, $user)) { drupal_not_found(); return; } } //use the first email address as receiver $field = array_pop($object->$field_name); $email = $field[0]['email']; //verify that the email address is not empty if (empty($email)) { drupal_not_found(); return; } $entity_info = entity_extract_ids($object_type, $object); $settings = field_info_instance($object_type, $field_name, $entity_info[2]); //verify that the contact formatter is enabled if ($settings['display']['full']['type'] != 'contact' && $settings['display']['full']['teaser'] != 'contact') { drupal_not_found(); return; } if (!flood_is_allowed('email', variable_get('email_hourly_threshold', 3))) { return t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('email_hourly_threshold', 3))); } return drupal_get_form('email_mail_page_form', $object_type, $object_id, $field_name, $email); } /** * Contact form */ function email_mail_page_form($form, $form_state, $object_type, $object_id, $field_name, $email) { global $user; $form['object_id'] = array( '#type' => 'value', '#value' => $object_id, ); $form['object_type'] = array( '#type' => 'value', '#value' => $object_type, ); $form['field_name'] = array( '#type' => 'value', '#value' => $field_name, ); $form['email'] = array( '#type' => 'value', '#value' => $email, ); $form['name'] = array( '#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 255, '#default_value' => $user->uid ? $user->name : '', '#required' => TRUE, ); $form['mail'] = array( '#type' => 'textfield', '#title' => t('Your e-mail address'), '#maxlength' => 255, '#default_value' => $user->uid ? $user->mail : '', '#required' => TRUE, ); $form['subject'] = array( '#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 255, '#required' => TRUE, ); $form['message'] = array( '#type' => 'textarea', '#title' => t('Message'), '#required' => TRUE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Send e-mail'), '#validate' => array('email_mail_page_form_validate'), '#submit' => array('email_mail_page_form_submit'), ); return $form; } /** * Validate the site-wide contact page form submission. */ function email_mail_page_form_validate($form, &$form_state) { if (!valid_email_address($form_state['values']['mail'])) { form_set_error('mail', t('You must enter a valid e-mail address.')); } if (preg_match("/\r|\n/", $form_state['values']['subject'])) { form_set_error('subject', t('The subject cannot contain linebreaks.')); watchdog('mail', 'Email injection exploit attempted in email form subject: '. check_plain($form_state['values']['subject']), WATCHDOG_NOTICE); } } /** * Process the site-wide contact page form submission. */ function email_mail_page_form_submit($form, &$form_state) { $object_type = $form_state['values']['object_type']; $object_id = $form_state['values']['object_id']; $field_name = $form_state['values']['field_name']; $email = $form_state['values']['email']; //load entity $objects = entity_load($object_type, array($object_id)); $object = $objects[$object_id]; $object_info = entity_get_info($object_type); // 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. $from = $form_state['values']['mail']; $params['object'] = $object; $params['subject'] = $form_state['values']['subject']; $params['name'] = $form_state['values']['name']; $params['message'] = $form_state['values']['message']; $path = ""; if (isset($object_info['path callback']) && function_exists($object_info['path callback'])) { $path = $object_info['path callback']($object); } $params['url'] = url($path, array('absolute' => TRUE)); // Send the e-mail to the recipients: drupal_mail('email', 'contact', $email, language_default(), $params, $from); // Log the operation: flood_register_event('email'); watchdog('mail', t('%name-from sent an e-mail at %form.', array('%name-from' => $form_state['values']['name'], '%form' => url($_GET['q'], array('absolute' => TRUE))))); drupal_set_message(t('Your message has been sent.')); $form_state['redirect'] = $path; } /** * Implementation of hook_mail() */ function email_mail($key, &$message, $params) { $language = $message['language']; switch($key) { case 'contact': // Compose the body: $message['body'][] = t('@name sent a message using the contact form at @url.', array('@name' => $params['name'], '@url' => $params['url']), array('langcode' =>$language->language)); $message['body'][] = $params['message']; $message['subject'] = ""; //include the title of the entity, if one exists $object = $params['object']; if (isset($object->title) && !empty($object->title)) { $message['subject'] = "[". check_plain(preg_replace("/\r|\n/",'', $object->title)) ."]"; } $message['subject'] .= " " . check_plain($params['subject']); break; } } //TODO Token support /** * Implements of hook_token_list() * function email_token_list($type = 'all') { if ($type == 'field' || $type == 'all') { $tokens['email']['raw'] = t('Raw email address'); $tokens['email']['formatted'] = t('Formatted email address'); return $tokens; } } /** * Implements of hook token_values(). * function email_token_values($type, $object = NULL, $options = array()) { if ($type == 'field') { $item = $object[0]; $tokens['raw'] = $item['email']; $tokens['formatted'] = $item['view']; return $tokens; } } */ /** * 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); }