'. t('Related tasks:') .'
    '. '
  1. '. l('Set Permissions', 'admin/user/access', array(), NULL, 'module-mass_contact') .'
  2. '. '
  3. '. l('List current categories', 'admin/build/mass_contact') .'
  4. '. '
  5. '. l('Add new category', 'admin/build/mass_contact/add') .'
  6. '. '
  7. '. l('Configure the module', 'admin/build/mass_contact/settings') .'
  8. '. '
  9. '. l('Send mass e-mail', 'mass_contact') .'
'; $output .= '

'. t('The Mass Contact module is simply a modified version of the core contact module. It works opposite the latter, in that it allows site moderators (or anyone with permission), to send mass e-mail to a set role or group of roles or even to all registered users.') .'

'; $output .= '

'. t("The sender's own address may be placed in the 'To:' field and all recipients placed in the 'BCC:' field, or the recipients simply placed in the 'To:' field. Note that the latter option leaves all recipients open to abuse due to their e-mail addresses being visible to all other recipients.") .'

'; $output .= '

'. t("The e-mail may be sent as HTML or plain text, and may include a single binary file attachment (if permitted by admin).") .'

'; $output .= '

'. t("At the option of the sender (if permitted by admin), a node may be created in order to keep a record of the e-mail sent. Do not try to send e-mails by creating nodes; it will not work.") .'

'; $output .= '

'. t('Users may opt-out of mass mailings on their profile page, but this may be overridden by the admin (or respected). The entire opt-out system may be disabled on the settings page.', array('@settings-page' => url('admin/build/mass_contact/settings'))) .'

'; $output .= '

'. t('Make sure to add at least one category and configure the module before trying to send mass e-mails.') .'

'; if (!module_exists('menu')) { $menu_note = t('The menu item can be customized and configured only once the menu module has been enabled.', array('@modules-page' => url('admin/build/modules'))); } else { $menu_note = ''; } $output .= '

'. t('The Mass Contact module also adds a menu item (disabled by default) to the navigation block.', array('@menu-settings' => url('admin/build/menu'))) .' '. $menu_note .'

'; return ($output); } } // End of mass_contact_help(). /** * Implementation of hook_perm * http://api.drupal.org/api/function/hook_perm * * @return * An array of permissions strings. */ function mass_contact_perm() { $permissions = array('administer mass contact', 'choose whether to archive mass contact messages', 'create mass_contact content', 'send mass contact attachments', 'send mass contact e-mails'); $result = db_query('SELECT category FROM {mass_contact}'); while ($category = db_fetch_object($result)) { $permissions[] = 'send to users in the '. $category->category .' category'; } return $permissions; } // End of mass_contact_perm(). /** * Implementation of hook_menu(). * http://api.drupal.org/api/function/hook_menu * * @param may_cache * A boolean indicating whether cacheable menu items should be returned. * @return * An array of menu items. */ function mass_contact_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'path' => 'admin/build/mass_contact', 'title' => t('Mass Contact form'), 'description' => t('Create a mass contact form and set up categories for the form to use.'), 'callback' => 'mass_contact_admin_categories', 'access' => user_access('administer mass contact'), ); $items[] = array( 'path' => 'admin/build/mass_contact/list', 'title' => t('Category list'), 'callback' => 'mass_contact_admin_categories', 'access' => user_access('administer mass contact'), 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/build/mass_contact/add', 'title' => t('Add category'), 'callback' => 'drupal_get_form', 'callback arguments' => array('mass_contact_admin_edit'), 'access' => user_access('administer mass contact'), 'type' => MENU_LOCAL_TASK, 'weight' => 1, ); $items[] = array( 'path' => 'admin/build/mass_contact/edit', 'title' => t('Edit Mass Contact category'), 'callback' => 'drupal_get_form', 'callback arguments' => array('mass_contact_admin_edit'), 'access' => user_access('administer mass contact'), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/build/mass_contact/delete', 'title' => t('Delete Mass Contact category'), 'callback' => 'drupal_get_form', 'callback arguments' => array('mass_contact_admin_delete'), 'access' => user_access('administer mass contact'), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/build/mass_contact/settings', 'title' => t('Settings'), 'callback' => 'drupal_get_form', 'callback arguments' => array('mass_contact_admin_settings'), 'access' => user_access('administer mass contact'), 'type' => MENU_LOCAL_TASK, 'weight' => 2, ); $items[] = array( 'path' => 'mass_contact', 'title' => t('Mass Contact'), 'callback' => 'mass_contact_site_page', 'access' => user_access('send mass contact e-mails'), 'type' => MENU_SUGGESTED_ITEM, ); $items[] = array( 'path' => 'node/add/mass_contact', 'title' => t('Mass Contact'), 'access' => user_access('create mass_contact content'), 'type' => MENU_SUGGESTED_ITEM, ); } return $items; } // End of mass_contact_menu(). /** * Displays a list of all existing categories. * * @return * The themed page listing all current categories. */ function mass_contact_admin_categories() { $result = db_query('SELECT cid, category, recipients, selected FROM {mass_contact}'); $rows = array(); while ($category = db_fetch_object($result)) { $rolenamesa = array(); foreach (explode(',', $category->recipients) as $rid) { $namerole = db_fetch_object(db_query('SELECT name FROM {role} WHERE rid = %d', $rid)); $rolenamesa[] = ($namerole->name); } $rolenames = implode(', ', $rolenamesa); $rows[] = array($category->category, $rolenames, ($category->selected ? t('Yes') : t('No')), l(t('edit'), 'admin/build/mass_contact/edit/'. $category->cid), l(t('delete'), 'admin/build/mass_contact/delete/'. $category->cid)); } $header = array(t('Category'), t('Recipients'), t('Selected'), array('data' => t('Operations'), 'colspan' => 2)); return theme('table', $header, $rows); } // End of mass_contact_admin_categories(). /** * Displays a form to add or edit a category. * * @param cid * The id of the category to edit. If NULL, then add rather than edit. * @return * An associative array that defines the form to be built. */ function mass_contact_admin_edit($cid = NULL) { $edit = array('category' => '', 'recipients' => '', 'selected' => '', 'cid' => ''); if (arg(3) == "edit" && $cid > 0) { $edit = db_fetch_array(db_query("SELECT * FROM {mass_contact} WHERE cid = %d", $cid)); } $form['category'] = array( '#type' => 'textfield', '#title' => t('Category'), '#maxlength' => 255, '#default_value' => $edit['category'], '#description' => t("Will appear in the subject of your e-mail as [category]."), '#required' => TRUE, ); // get all roles except anonymous $allroles = db_query('SELECT rid, name FROM {role} WHERE rid > 1'); while ($roleobj = db_fetch_object($allroles)) { $onerid = $roleobj->rid; $onename = $roleobj->name; $rolesarray[$onerid] = $onename; } $form['recipients'] = array( '#type' => 'checkboxes', '#title' => t('Roles to receive e-mail'), '#options' => $rolesarray, '#default_value' => explode(',', $edit['recipients']), '#description' => t('These roles will be added to the mailing list. Note: if you check "authenticated users", other roles will not be added, as they will receive the e-mail anyway.'), ); $form['selected_categories'] = array( '#type' => 'fieldset', '#title' => t('Selected categories'), ); $form['selected_categories']['selected'] = array( '#type' => 'select', '#title' => t('Selected'), '#options' => array('0' => t('No'), '1' => t('Yes')), '#default_value' => $edit['selected'], '#description' => t('Set this to Yes if you would like this category to be selected by default.'), ); $form['selected_categories']['reset_selected'] = array( '#type' => 'checkbox', '#title' => t('Reset all previously selected categories to No.'), ); $form['cid'] = array( '#type' => 'value', '#value' => $edit['cid'], ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Submit'), ); return $form; } // End of mass_contact_admin_edit(). /** * Validates the submission of the category add/edit page. * * @param form_id * The unique string identifying the form. * @param form_values * The array of values returned by the form. */ function mass_contact_admin_edit_validate($form_id, $form_values) { $recipients = $form_values['recipients']; foreach ($recipients as $checkr) { if ($checkr > 1) { return; } } form_set_error('recipients', t('You must check one or more recipients.')); } // End of mass_contact_admin_edit_validate(). /** * Processes the adding or editing of a category. * * @param form_id * The unique string identifying the form. * @param form_values * The array of values returned by the form. */ function mass_contact_admin_edit_submit($form_id, $form_values) { if ($form_values['reset_selected']) { // Unselect all other contact categories. db_query('UPDATE {mass_contact} SET selected = 0'); } // Remove 0s for unselected roles, convert to csv. $recipients = $form_values['recipients']; // If all authenticated users are already added, remove all roles. if ($recipients[2] == 2) { foreach ($recipients as $checkr) { if ($checkr > 2) { $recipients[$checkr] = 0; } } } // Remove roles that were not selected. foreach ($recipients as $recip) { if ($recip != 0) { $newformrec[] = $recip; } } $form_values['recipients'] = implode(',', $newformrec); if (arg(3) == 'add') { db_query("INSERT INTO {mass_contact} (category, recipients, reply, weight, selected) VALUES ('%s', '%s', '%s', %d, %d)", $form_values['category'], $form_values['recipients'], $form_values['reply'], $form_values['weight'], $form_values['selected']); drupal_set_message(t('Category %category has been added.', array('%category' => $form_values['category']))); watchdog('mass_contact', t('Mass Contact form: category %category added.', array('%category' => $form_values['category'])), WATCHDOG_NOTICE, l(t('view'), 'admin/build/mass_contact')); } else { db_query("UPDATE {mass_contact} SET category = '%s', recipients = '%s', reply = '%s', weight = %d, selected = %d WHERE cid = %d", $form_values['category'], $form_values['recipients'], $form_values['reply'], $form_values['weight'], $form_values['selected'], $form_values['cid']); drupal_set_message(t('Category %category has been updated.', array('%category' => $form_values['category']))); watchdog('mass_contact', t('Mass Contact form: category %category updated.', array('%category' => $form_values['category'])), WATCHDOG_NOTICE, l(t('view'), 'admin/build/mass_contact')); } return 'admin/build/mass_contact'; } // End of mass_contact_admin_edit_submit(). /** * Displays a form to select a category to delete. * * @param cid * The id of the category to delete. * @return * A confirmation form for the user to acknowledge. */ function mass_contact_admin_delete($cid = NULL) { if ($info = db_fetch_object(db_query("SELECT category FROM {mass_contact} WHERE cid = %d", $cid))) { $form['category'] = array( '#type' => 'value', '#value' => $info->category, ); return confirm_form($form, t('Are you sure you want to delete %category?', array('%category' => $info->category)), 'admin/build/mass_contact', t('This action cannot be undone.'), t('Delete'), t('Cancel')); } else { drupal_set_message(t('Category not found.'), 'error'); drupal_goto('admin/build/mass_contact'); } } // End of mass_contact_admin_delete(). /** * Does the actual deleting of the category. * * @param form_id * The unique string identifying the form. * @param form_values * The array of values returned by the form. */ function mass_contact_admin_delete_submit($form_id, $form_values) { db_query("DELETE FROM {mass_contact} WHERE cid = %d", arg(4)); drupal_set_message(t('Category %category has been deleted.', array('%category' => $form_values['category']))); watchdog('mass_contact', t('Mass Contact form: category %category deleted.', array('%category' => $form_values['category'])), WATCHDOG_NOTICE); return 'admin/build/mass_contact'; } // End of mass_contact_admin_delete_submit(). /** * Administration settings form. * * @return * An associative array that defines the form to be built. */ function mass_contact_admin_settings() { $form['mass_contact_form_information'] = array( '#type' => 'textarea', '#title' => t('Additional information for Mass Contact form'), '#default_value' => variable_get('mass_contact_form_information', t('Send e-mails using the following form.')), '#description' => t('Information to show on the Mass Contact page.', array('@form' => url('mass_contact'))), ); $form['mass_contact_character_set'] = array( '#type' => 'textfield', '#title' => t('Character set'), '#default_value' => variable_get('mass_contact_character_set', ''), '#description' => t('You may specify an alternate character set to use when sending e-mails. If left blank, the default of UTF-8 will be used. If you are unsure of what to put here, then leave it blank. Caution: setting this may not get you the results you desire. Other modules may come along and change that value after it has been set by this module.'), ); $form['mass_contact_default_sender'] = array( '#type' => 'fieldset', '#title' => t('Default sender information'), '#description' => t('If anything is specified in here, it is used in place of the "Your name" and "Your e-mail address" fileds when sending the mass e-mail. Otherwise, the sender\'s name and e-mail address will be the default values. You must fill in both values, if you want to specify a default.'), ); $form['mass_contact_default_sender']['mass_contact_default_sender_name'] = array( '#type' => 'textfield', '#title' => t('Default sender name'), '#default_value' => variable_get('mass_contact_default_sender_name', ''), '#size' => 60, '#maxlength' => 128, '#description' => t('The optional user name to send e-mail as. Replaces the "Your name" value when sending mass e-mails.'), ); $form['mass_contact_default_sender']['mass_contact_default_sender_email'] = array( '#type' => 'textfield', '#title' => t('Default sender e-mail address'), '#default_value' => variable_get('mass_contact_default_sender_email', ''), '#size' => 60, '#maxlength' => 128, '#description' => t('The optional user e-mail address to send e-mail as. Replaces the "Your e-mail address" value when sending mass e-mails.'), ); $form['mass_contact_default_sender']['mass_contact_default_sender_changable'] = array( '#type' => 'checkbox', '#title' => t('Allow the sender to change these values.'), '#default_value' => variable_get('mass_contact_default_sender_changable', 0), '#description' => t('If checked, gives the sender the ability of changing the default sender and e-mail address when creating the message. If unchecked, the fields will be disabled.'), ); $form['mass_contact_recipient_limit'] = array( '#type' => 'textfield', '#title' => t('Maximum number of recipients before splitting up the e-mail'), '#size' => 4, '#default_value' => variable_get('mass_contact_recipient_limit', 0), '#description' => t('This is a workaround for server-side limits on the number of recipients in a single mail message. Once this limit is reached, the recipient list will be broken up and multiple copies of the message will be sent out until all recipients receive the mail. Setting this to "0" will turn off this feature.'), '#required' => TRUE, ); $form['mass_contact_optout_d'] = array( '#type' => 'checkbox', '#title' => t('Allow users to opt-out of mass e-mails.'), '#default_value' => variable_get('mass_contact_optout_d', 0), ); $form['mass_contact_bcc_d'] = array( '#type' => 'checkbox', '#title' => t('Send as BCC (hide recipients) by default.'), '#default_value' => variable_get('mass_contact_bcc_d', 1), ); $form['mass_contact_bcc_d_override'] = array( '#type' => 'checkbox', '#title' => t('Allow sender to override BCC setting.'), '#default_value' => variable_get('mass_contact_bcc_d_override', 1), ); $form['mass_contact_category_override'] = array( '#type' => 'checkbox', '#title' => t('Include category in subject line.'), '#default_value' => variable_get('mass_contact_category_override', 1), ); $form['mass_contact_supplemental_texts'] = array( '#type' => 'fieldset', '#title' => t('Supplemental message body texts'), '#description' => t('You may specify additional text to insert before and/or after the message text of every mass e-mail that is sent.'), ); if (module_exists('token')) { $form['mass_contact_supplemental_texts']['mass_contact_message_prefix'] = array( '#type' => 'textarea', '#title' => t('Text to be prepended to all messages'), '#default_value' => variable_get('mass_contact_message_prefix', t('[user-name] has sent you a group e-mail from [site-name].')), '#description' => t('The text you specify above will be added to all e-mails sent out. The text will be placed before the message text enetered in by the sender.'), ); $form['mass_contact_supplemental_texts']['mass_contact_message_suffix'] = array( '#type' => 'textarea', '#title' => t('Text to be appended to all messages'), '#default_value' => variable_get('mass_contact_message_suffix', t('')), '#description' => t('The text you specify above will be added to all e-mails sent out. The text will be placed after the message text enetered in by the sender.'), ); $form['mass_contact_supplemental_texts']['mass_contact_replacement_tokens'] = array( '#type' => 'fieldset', '#title' => t('Replacement tokens'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('You may use any of the following replacements tokens for use in the prefix and/or suffix texts above.'), ); $form['mass_contact_supplemental_texts']['mass_contact_replacement_tokens']['token_help'] = array( '#value' => theme('token_help', 'global'), ); } else { $form['mass_contact_supplemental_texts']['mass_contact_message_prefix'] = array( '#type' => 'textarea', '#title' => t('Text to be prepended to all messages'), '#default_value' => variable_get('mass_contact_message_prefix', t('You were sent a group e-mail from !site.', array('!site' => url(NULL, NULL, NULL, TRUE)))), '#description' => t('The text you specify above will be added to all e-mails sent out. The text will be placed before the message text enetered in by the sender.'), ); $form['mass_contact_supplemental_texts']['mass_contact_message_suffix'] = array( '#type' => 'textarea', '#title' => t('Text to be appended to all messages'), '#default_value' => variable_get('mass_contact_message_suffix', t('')), '#description' => t('The text you specify above will be added to all e-mails sent out. The text will be placed after the message text enetered in by the sender.'), ); } $form['mass_contact_html_d'] = array( '#type' => 'checkbox', '#title' => t('Send as HTML by default.'), '#default_value' => variable_get('mass_contact_html_d', 1), '#description' => t('This will use the default input filter as specified on the Input formats settings page.', array('@formats_settings' => url('admin/settings/filters'))), ); $form['mass_contact_html_d_override'] = array( '#type' => 'checkbox', '#title' => t('Allow sender to override HTML setting.'), '#default_value' => variable_get('mass_contact_html_d_override', 1), ); $form['mass_contact_attachment_location'] = array( '#type' => 'textfield', '#title' => t('Attachment location'), '#default_value' => variable_get('mass_contact_attachment_location', file_directory_path() .'/mass_contact_attachments'), '#description' => t('If a copy of the message is saved as a node, this is the file path where to save the attachment so it can be viewed later.'), ); $form['mass_contact_nodecc_d'] = array( '#type' => 'checkbox', '#title' => t('Save a copy as a node by default.'), '#default_value' => variable_get('mass_contact_nodecc_d', 1), ); $form['mass_contact_nodecc_d_override'] = array( '#type' => 'checkbox', '#title' => t('Allow sender to override node copy setting.'), '#default_value' => variable_get('mass_contact_nodecc_d_override', 1), ); $form['mass_contact_hourly_threshold'] = array( '#type' => 'select', '#title' => t('Hourly threshold'), '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#default_value' => variable_get('mass_contact_hourly_threshold', 3), '#description' => t('The maximum number of Mass Contact form submissions a user can perform per hour.'), ); return system_settings_form($form); } // End of mass_contact_admin_settings(). /** * Validates the administration settings form. * * @param form_id * The unique string identifying the form. * @param form_values * The array of values returned by the form. */ function mass_contact_admin_settings_validate($form_id, $form_values) { if (!empty($form_values['mass_contact_default_sender_name'])) { if (empty($form_values['mass_contact_default_sender_email'])) { form_set_error('mass_contact_default_sender_email', t('If you are going to specify default user settings, you must specify both a user name and a user e-mail address.')); } } if (!empty($form_values['mass_contact_default_sender_email'])) { if (empty($form_values['mass_contact_default_sender_name'])) { form_set_error('mass_contact_default_sender_name', t('If you are going to specify default user settings, you must specify both a user name and a user e-mail address.')); } } } // End of mass_contact_admin_settings_validate(). /** * Implementation of hook_user(). * http://api.drupal.org/api/function/hook_user * * Provide form element to opt in to content mailouts. * * @param type * The type of action being performed. * @param edit * The array of form values submitted by the user. * @param user * The user object on which the operation is being performed. * @param category * The active category of user information being edited. */ function mass_contact_user($type, $edit, &$user, $category = NULL) { if (variable_get('mass_contact_optout_d', 0) == 1) { if ($type == 'register' || ($type == 'form' && $category == 'account')) { $form['mail'] = array( '#type' => 'fieldset', '#title' => t('Group e-mail settings'), '#weight' => 5, '#collapsible' => TRUE, ); $form['mail']['mass_contact_optout'] = array( '#type' => 'checkbox', '#title' => t('Opt-out of Mass E-mails'), '#default_value' => $edit['mass_contact_optout'], '#description' => t('Allows you to opt-out of group e-mails from privileged users. Note that site administrators are able to include you in mass e-mails even if you choose not to enable this feature, and the ability to opt-out may be removed by the administrator at any time.'), ); return $form; } elseif ($type == 'validate') { return array('mass_contact_optout' => $edit['mass_contact_optout']); } } } // End of mass_contact_user(). /** * The mail page * * @return * Either an error, if flood control is active and triggered, or a * rendered form. */ function mass_contact_site_page() { global $user; if (!user_access('administer mass contact') && !flood_is_allowed('mass_contact', variable_get('mass_contact_hourly_threshold', 3))) { $output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('mass_contact_hourly_threshold', 3))); } else { $output = drupal_get_form('mass_contact_mail_page'); } return $output; } // End of mass_contact_site_page(). /** * Generates the main Mass Contact mail form. * * @return * An associative array that defines the form to be built. */ function mass_contact_mail_page() { global $user; $categories = array(); $default_category = array(); $default_category_name = ''; $result = db_query('SELECT cid, category, selected FROM {mass_contact} ORDER BY weight, category'); while ($category = db_fetch_object($result)) { if (user_access('send to users in the '. $category->category .' category')) { $categories[$category->cid] = $category->category; if ($category->selected) { $default_category[] = $category->cid; $default_category_name = $category->category; } } } if (count($categories) == 1) { $default_category[] = $category->cid; $default_category_name = $category->category; } if (count($categories) > 0) { $form['#attributes'] = array( 'enctype' => "multipart/form-data" ); $form['#token'] = $user->name . $user->mail; $form['contact_information'] = array( '#value' => filter_xss_admin(variable_get('mass_contact_form_information', t('Send an e-mail message using the contact form below.'))) ); $mass_contact_default_sender_name = variable_get('mass_contact_default_sender_name', ''); if ($mass_contact_default_sender_name) { $form['name'] = array( '#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 255, '#default_value' => $mass_contact_default_sender_name, '#disabled' => !variable_get('mass_contact_default_sender_changable', 0), ); } else { $form['name'] = array( '#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 255, '#default_value' => $user->uid ? $user->name : '', '#required' => TRUE, ); } $mass_contact_default_sender_email = variable_get('mass_contact_default_sender_email', ''); if ($mass_contact_default_sender_email) { $form['mail'] = array( '#type' => 'textfield', '#title' => t('Your e-mail address'), '#maxlength' => 255, '#default_value' => $mass_contact_default_sender_email, '#disabled' => !variable_get('mass_contact_default_sender_changable', 0), ); } else { $form['mail'] = array( '#type' => 'textfield', '#title' => t('Your e-mail address'), '#maxlength' => 255, '#default_value' => $user->uid ? $user->mail : '', '#required' => TRUE, ); } if ((count($categories) > 1) || !isset($default_category)) { // Display a choice when one is needed. $form['cid'] = array( '#type' => 'select', '#title' => t('Category'), '#default_value' => $default_category, '#options' => $categories, '#required' => TRUE, '#multiple' => TRUE, ); } else { // Otherwise, just use the default category. $form['cid'] = array( '#type' => 'value', '#value' => $default_category, // This must be an array, otherwise the code breaks upon submit. ); $form['cid-info'] = array( '#type' => 'markup', '#value' => '

Sending to all users subscribed to the '. $default_category_name .' category.

', ); } if (variable_get('mass_contact_optout_d', 0) == 1) { // Allow to override or respect opt-outs if admin, otherwise use default. if (user_access('administer mass contact')) { $form['optout'] = array( '#type' => 'checkbox', '#title' => t('Respect user opt-outs.'), '#default_value' => 1, ); } else { $form['optout'] = array( '#type' => 'hidden', '#default_value' => 1, ); } } // Check if the user can override the BCC setting. if (variable_get('mass_contact_bcc_d_override', 1)) { $form['bcc'] = array( '#type' => 'checkbox', '#title' => t('Send as BCC (hide recipients).'), '#default_value' => variable_get('mass_contact_bcc_d', 1), ); } // If not, then just display the BCC info. else { $form['bcc'] = array( '#type' => 'value', '#value' => variable_get('mass_contact_bcc_d', 1), ); $form['bcc-info'] = array( '#type' => 'markup', '#value' => '

'. (variable_get('mass_contact_bcc_d', 1) ? t('Recipients will be hidden.') : t('Recipients will NOT be hidden.')) .'

', ); } $form['subject'] = array( '#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 255, '#required' => TRUE, ); $form['body_filter']['message'] = array( '#type' => 'textarea', '#title' => t('Message'), '#rows' => 12, '#required' => TRUE, ); $form['body_filter']['format'] = filter_form(FILTER_FORMAT_DEFAULT); if (user_access('send mass contact attachments')) { $form['attachment'] = array( '#type' => 'file', '#title' => t('Attachment'), '#size' => 40, ); } // Check if the user can override the HTML setting. if (variable_get('mass_contact_html_d_override', 1)) { $form['html'] = array( '#type' => 'checkbox', '#title' => t('Send as HTML.'), '#default_value' => variable_get('mass_contact_html_d', 1), '#description' => t('This will use the settings for the default input filter. More information about what is available is on the Input formats page.', array('@formats_settings' => url('filter/tips'))), ); } // If not, then just display the HTML info. else { $form['html'] = array( '#type' => 'value', '#value' => variable_get('mass_contact_html_d', 1), ); $form['html-info'] = array( '#type' => 'markup', '#value' => '

'. (variable_get('mass_contact_html_d', 1) ? t('The message will be sent as HTML.') : t('The message will be sent as plain text.')) .'

', ); } // We do not allow anonymous users to send themselves a copy because it // can be abused to spam people. if ($user->uid) { $form['copy'] = array( '#type' => 'checkbox', '#title' => t('Send yourself a copy.'), '#weight' => $i, ); } if (user_access('choose whether to archive mass contact messages')) { // Check if the user can override the node copy setting. if (variable_get('mass_contact_nodecc_d_override', 1)) { $form['nodecc'] = array( '#type' => 'checkbox', '#title' => t('Save a copy as a node.'), '#default_value' => variable_get('mass_contact_nodecc_d', 1), ); } // If not, then do it or not based on the administrative setting. else { $form['nodecc'] = array( '#type' => 'hidden', '#default_value' => variable_get('mass_contact_nodecc_d', 1), ); } } // If not, then do it or not based on the administrative setting. else { $form['nodecc'] = array( '#type' => 'hidden', '#default_value' => variable_get('mass_contact_nodecc_d', 1), ); } /* // Place hooder for future use. $form['preview'] = array( '#type' => 'button', '#value' => t('Preview') ); */ $form['submit'] = array( '#type' => 'submit', '#value' => t('Send e-mail'), ); } else { $form['error'] = array( '#value' => '

'. t('Either you have not created any categories, or you are not allowed to send to any of the existing categories.') .'

'. t('Either create at least one category of users to send to, or contact your system administer for access to the existing categories.') .'
', ); } if (user_access('administer mass contact')) { $form['tasklist'] = array( '#type' => 'fieldset', '#title' => t('Related tasks'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#prefix' => '

', ); $form['tasklist']['list'] = array( '#value' => '

    '. '
  1. '. l('Set Permissions', 'admin/user/access', array(), NULL, 'module-mass_contact') .'
  2. '. '
  3. '. l('List current categories', 'admin/build/mass_contact') .'
  4. '. '
  5. '. l('Add new category', 'admin/build/mass_contact/add') .'
  6. '. '
  7. '. l('Configure the module', 'admin/build/mass_contact/settings') .'
  8. '. '
  9. '. l('Help', 'admin/help/mass_contact') .'
', ); } return $form; } // End of mass_contact_mail_page(). /** * Validates the main Mass Contact mail form. * * @param form_id * The unique string identifying the form. * @param form_values * The array of values returned by the form. */ function mass_contact_mail_page_validate($form_id, $form_values) { if (!$form_values['cid']) { form_set_error('category', t('You must select a valid category.')); } if (!valid_email_address($form_values['mail'])) { form_set_error('mass_contact', t('You must enter a valid e-mail address.')); } } // End of mass_contact_mail_page_validate(). /** * Processes the main Mass Contact mail form. * * @param form_id * The unique string identifying the form. * @param form_values * The array of values returned by the form. */ function mass_contact_mail_page_submit($form_id, $form_values) { $bcc = $form_values['bcc']; $nodecc = $form_values['nodecc']; $send_error = 0; // 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_values['mail']; $boundary_attachment = md5(uniqid(mt_rand())); $boundary_html = md5(uniqid(mt_rand())); $character_set = variable_get('mass_contact_character_set', '') ? variable_get('mass_contact_character_set', '') : 'UTF-8'; $headers = array(); $body_plain = ''; $body_html = ''; $message = ''; $message_attachment = array(); // Set the "Content-Type" header based on the presence or absence of an // attachment and the HTML setting. if ($_FILES['files']['size']['attachment'] > 0) { $headers['Content-Type'] = 'multipart/mixed; boundary="'. $boundary_attachment .'"'; } elseif ($form_values['html']) { $headers['Content-Type'] = 'multipart/alternative; boundary="'. $boundary_html .'"'; } else { $headers['Content-Type'] = 'text/plain; charset='. $character_set .'; format=flowed'; } // Create the plain text body. We now always create a plain text body. if ($form_values['html']) { // If this is supposed to be an HTML e-mail, we need to process the plain // text part differently. // Make this process better, by utilizing existing modules. This will // become the norm, eliminating the need for the module check. if (module_exists('html_to_text')) { // Start with the message prefix. if (variable_get('mass_contact_message_prefix', '')) { if (module_exists('token')) { $body_plain .= drupal_html_to_text(check_markup(token_replace(variable_get('mass_contact_message_prefix', '')), $form_values['format'])) ."\n"; } else { $body_plain .= drupal_html_to_text(check_markup(variable_get('mass_contact_message_prefix', ''), $form_values['format'])) ."\n"; } } // Add in the actual message. $body_plain .= drupal_html_to_text(check_markup($form_values['message'], $form_values['format'])) ."\n"; // End with the message suffix. if (variable_get('mass_contact_message_suffix', '')) { if (module_exists('token')) { $body_plain .= drupal_html_to_text(check_markup(token_replace(variable_get('mass_contact_message_suffix', '')), $form_values['format'])); } else { $body_plain .= drupal_html_to_text(check_markup(variable_get('mass_contact_message_suffix', ''), $form_values['format'])); } } } else { // Start with the message prefix. if (variable_get('mass_contact_message_prefix', '')) { if (module_exists('token')) { $body_plain .= wordwrap(strip_tags(check_markup(token_replace(variable_get('mass_contact_message_prefix', '')), $form_values['format']))) ."\n"; } else { $body_plain .= wordwrap(strip_tags(check_markup(variable_get('mass_contact_message_prefix', ''), $form_values['format']))) ."\n"; } } // Add in the actual message. $body_plain .= wordwrap(strip_tags(check_markup($form_values['message'], $form_values['format']))) ."\n"; // End with the message suffix. if (variable_get('mass_contact_message_suffix', '')) { if (module_exists('token')) { $body_plain .= wordwrap(strip_tags(check_markup(token_replace(variable_get('mass_contact_message_suffix', '')), $form_values['format']))); } else { $body_plain .= wordwrap(strip_tags(check_markup(variable_get('mass_contact_message_suffix', ''), $form_values['format']))); } } } } else { // Start with the message prefix. if (variable_get('mass_contact_message_prefix', '')) { if (module_exists('token')) { $body_plain .= wordwrap(token_replace(variable_get('mass_contact_message_prefix', ''))) ."\n\n"; } else { $body_plain .= wordwrap(variable_get('mass_contact_message_prefix', '')) ."\n\n"; } } // Add in the actual message. $body_plain .= wordwrap($form_values['message']) ."\n"; // End with the message suffix. if (variable_get('mass_contact_message_suffix', '')) { if (module_exists('token')) { $body_plain .= wordwrap(token_replace(variable_get('mass_contact_message_suffix', ''))); } else { $body_plain .= wordwrap(variable_get('mass_contact_message_suffix', '')); } } } // If this is an HTML message, create the HTML body part. if ($form_values['html']) { // Start with the message prefix. if (variable_get('mass_contact_message_prefix', '')) { if (module_exists('token')) { $body_html .= check_markup(token_replace(variable_get('mass_contact_message_prefix', '')), $form_values['format']); } else { $body_html .= check_markup(variable_get('mass_contact_message_prefix', ''), $form_values['format']); } } // Add a spacer. $body_html .= '

'; // Add in the actual message. $body_html .= check_markup($form_values['message'], $form_values['format']); // Add a spacer. $body_html .= '

'; // End with the message suffix. if (variable_get('mass_contact_message_suffix', '')) { if (module_exists('token')) { $body_html .= check_markup(token_replace(variable_get('mass_contact_message_suffix', '')), $form_values['format']); } else { $body_html .= check_markup(variable_get('mass_contact_message_suffix', ''), $form_values['format']); } } } // Put it all together. // Check to see if we have either an attachment or an HTML message. if (($_FILES['files']['size']['attachment'] > 0) || $form_values['html']) { // If we have either, we need the following. $message .= "\nThis is a multi-part message in MIME format.\n"; // Add our boundary, based on the content. if ($_FILES['files']['size']['attachment'] > 0) { $message .= "\n--". $boundary_attachment ."\n"; } else { $message .= "\n--". $boundary_html ."\n"; } // If we have both an attachment and an HTML message, we need the following. if (($_FILES['files']['size']['attachment'] > 0) && $form_values['html']) { $message .= 'Content-Type: multipart/alternative; boundary="'. $boundary_html .'"'."\n"; $message .= "\n--". $boundary_html ."\n"; } // Add the plain text part to the message. $message .= "Content-Type: text/plain; charset=$character_set; format=flowed\n"; $message .= "Content-Transfer-Encoding: 8bit\n\n"; $message .= $body_plain; // If there is an HTML part, add it to the message. if ($form_values['html']) { $message .= "\n--". $boundary_html ."\n"; $message .= "Content-Type: text/html; charset=$character_set; format=flowed\n"; $message .= "Content-Transfer-Encoding: 8bit\n\n"; $message .= $body_html; } } else { // There is neither an attachment nor an HTML message, so this is not a // multipart message, and we just add the plain text part. $message = $body_plain; } // For the node copy, we want to handle attachments differently, so we'll // save the message as it currently stands. if (variable_get('mass_contact_nodecc_d', 1)) { $node_message = $message; } // If there is an attachment, add it. if ($_FILES['files']['size']['attachment'] > 0) { // Oy! If Mime Mail is installed and active, we have to do things // differently for it. (This may change when I refactor how attachments // are handled.) if (module_exists('mimemail') && variable_get('mimemail_alter', 0) == 1) { $message_attachment = array( array( 'filepath' => $_FILES['files']['tmp_name']['attachment'], 'filename' => $_FILES['files']['name']['attachment'], 'filemime' => $_FILES['files']['type']['attachment'], ) ); } else { $message_attachment = "\n--". $boundary_attachment ."\n"; $message_attachment .= 'Content-Type: '. $_FILES['files']['type']['attachment'] .'; name="'. basename($_FILES['files']['name']['attachment']) .'"'."\n"; $message_attachment .= "Content-Transfer-Encoding: base64\n"; $message_attachment .= 'Content-Disposition: attachment; filename="'. basename($_FILES['files']['name']['attachment']) .'"'."\n\n"; $message_attachment .= chunk_split(base64_encode(file_get_contents($_FILES['files']['tmp_name']['attachment']))); $message_attachment .= "\n--". $boundary_attachment ."--\n"; $message .= $message_attachment; } } /////////////////////////////////////////////////////////////////////////// // // @TODO: The whole rest of this function needs to be re-thought out and // refactored, possibly separating some of it out into other // functions. // /////////////////////////////////////////////////////////////////////////// /* Task order: Create the e-mail message, starting w/the header Get the list of categories Create the list of recipients Add the list of recipients to the e-mail message */ // Load the category information. foreach ($form_values['cid'] as $cid) { $cids .= $cid; if (next($form_values['cid'])) { $cids .= ", "; } } $result = db_query("SELECT * FROM {mass_contact} WHERE cid IN (%s)", $cids); while ($contact = db_fetch_object($result)) { $uidooa = array(); // Check for opt-out unless overridden by admin. if (variable_get('mass_contact_optout_d', 0) == 1) { $allow_oo = $form_values['optout']; if ($allow_oo == 1) { $ooresult = db_query('SELECT uid FROM {users} WHERE status <> 0'); while ($oouid = db_fetch_object($ooresult)) { $account = user_load(array('uid' => $oouid->uid, 'status' => 1)); if ($account->mass_contact_optout) { $uidoo = $oouid->uid; $uidooa[$uidoo] = 1; } } } } global $user; // Create the recipient list. $recipientouta = array(); $roles = explode(',', $contact->recipients); foreach ($roles as $r) { if ($r == 2) { // all users $recipients = db_query("SELECT name, mail, uid FROM {users} WHERE status <> 0 AND uid > 0"); while ($obj = db_fetch_object($recipients)) { $rname = $obj->name; $rmail = $obj->mail; $ruid = $obj->uid; if ($rname != $user->name && !$uidooa[$ruid]) { $recipientouta[$rname] = $rmail; } } break; } else { // Get from users_roles, then role -> user. $uids = db_query("SELECT ur.uid FROM {users_roles} ur LEFT JOIN {users} u ON ur.uid = u.uid WHERE ur.rid = %d AND u.status <> 0", $r); while ($obj = db_fetch_object($uids)) { $ruid = $obj->uid; $userobj = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid = %d", $ruid)); $rname = $userobj->name; $rmail = $userobj->mail; if (isset($uidooa[$ruid])) { if ($rname != $user->name && !$uidooa[$ruid]) { $recipientouta[$rname] = $rmail; } } else { if ($rname != $user->name) { $recipientouta[$rname] = $rmail; } } } } } } // Format the subject line. // if (variable_get('mass_contact_category_override', 1)) { // $subject = t('[!category] !subject', array('!category' => $contact->category, '!subject' => $form_values['subject'])); // } // else { // } // Prepare the body. $subject = $form_values['subject']; $body = $message; $node_body = $node_message; // Check for empty recipient list. if (count($recipientouta) == 0) { drupal_set_message(t('There are no users in this category. Mail not sent.')); return (''); } else { //remove duplicates $recipientouta = array_unique($recipientouta); } $headers['Return-Path'] = 'info@1031mree.com'; $recipientout = array(); // Check for recipient limit and break up recipient list, if necessary. $recip_limit = variable_get('mass_contact_recipient_limit', 0); if (count($recipientouta) > $recip_limit && $recip_limit != 0) { $countrecip = 0; $ccc = 0; foreach ($recipientouta as $rnamea => $rmaila) { // $recipientout[] = $rnamea ." <". $rmaila .">"; $recipientout[] = $rmaila; // $recipient_temp[] = $rnamea ." <". $rmaila .">"; $recipient_temp[] = $rmaila; $countrecip = count($recipient_temp); if ($countrecip == $recip_limit) { $recipient_send = implode(', ', $recipient_temp); // set bcc if ($bcc == 1) { // hidden recipients $headers['Bcc'] = $recipient_send; $to = $from; } else { $to = $recipient_send; } ++$ccc; // Send the e-mail to the recipients: if (module_exists('mimemail') && variable_get('mimemail_alter', 0) == 1) { if ($form_values['html']) { $success = mimemail($from, $to, $subject, $body_html, NULL, $headers, $body_plain, $message_attachment, 'mass-contact-page-mail'); } else { $success = mimemail($from, $to, $subject, $body_html, TRUE, $headers, $body_plain, $message_attachment, 'mass-contact-page-mail'); } } else { $success = drupal_mail('mass-contact-page-mail', $to, $subject, $body, $from, $headers); } if ($success) { drupal_set_message(t('[Success] Send #!ccc: -e-mails', array('!ccc' => $ccc, '-e-mails' => $recipient_send))); } else { ++$send_error; } // reset array $recipient_temp = array(); $countrecip = 0; } } // Send the remainder. if ($countrecip != 0) { $recipient_send = implode(', ', $recipient_temp); if ($bcc == 1) { // hidden recipients $headers['Bcc'] = $recipient_send; $to = $from; } else { $to = $recipient_send; } ++$ccc; // Send the e-mail to the recipients: if (module_exists('mimemail') && variable_get('mimemail_alter', 0) == 1) { if ($form_values['html']) { $success = mimemail($from, $to, $subject, $body_html, NULL, $headers, $body_plain, $message_attachment, 'mass-contact-page-mail'); } else { $success = mimemail($from, $to, $subject, $body_html, TRUE, $headers, $body_plain, $message_attachment, 'mass-contact-page-mail'); } } else { $success = drupal_mail('mass-contact-page-mail', $to, $subject, $body, $from, $headers); } // Send a copy to self, if requested. if ($form_values['copy'] && !$bcc) { drupal_mail('mass-contact-user-copy', $from, $subject, $body, $from, $headers); } if ($success) { drupal_set_message(t('[Success] Send Remainder: -e-mails', array('-e-mails' => $recipient_send))); } else { ++$send_error; } } $total_recip = count($recipientout); $recipientout = implode(', ', $recipientout); } else { foreach ($recipientouta as $rnamea => $rmaila) { // $recipientout[] = $rnamea ." <". $rmaila .">"; $recipientout[] = $rmaila; } $total_recip = count($recipientout); $recipientout = implode(', ', $recipientout); // set bcc if ($bcc == 1) { // hidden recipients $headers['Bcc'] = $recipientout; $to = $from; } else { $to = $recipientout; } // Send the e-mail to the recipients. if (module_exists('mimemail') && variable_get('mimemail_alter', 0) == 1) { if ($form_values['html']) { $success = mimemail($from, $to, $subject, $body_html, NULL, $headers, $body_plain, $message_attachment, 'mass-contact-page-mail'); } else { $success = mimemail($from, $to, $subject, $body_html, TRUE, $headers, $body_plain, $message_attachment, 'mass-contact-page-mail'); } } else { $success = drupal_mail('mass-contact-page-mail', $to, $subject, $body, $from, $headers); } // Send a copy to self, if requested. if ($form_values['copy'] && !$bcc) { drupal_mail('mass-contact-user-copy', $from, $subject, $body, $from, $headers); } if ($success) { drupal_set_message(t('[Success] Send Once: -e-mails', array('-e-mails' => $recipientout))); } else { ++$send_error; } } // Error checking & reporting and node saving. // Check for errors. if ($send_error == 0) { // If there are no errors, check to see if we need to save the message as a node. if ($nodecc == 1) { // Check to see if the node type exists. $check = db_fetch_array(db_query("SELECT * FROM {node_type} WHERE type = 'mass_contact'")); if (!$check) { // If the node type does not exist, create it. $info->type = "mass_contact"; $info->name = "Mass Contact Message"; $info->module = "node"; $info->description = "Archived copy of mass e-mails sent from this site"; $info->help = ""; $info->has_title = 1; $info->title_label = "Subject"; $info->has_body = 1; $info->body_label = "Message Body"; $info->min_word_count = 0; $info->custom = 1; $info->modified = 0; $info->locked = 0; $info->orig_type = 'mass_contact'; db_query("INSERT INTO {node_type} (type, name, module, description, help, has_title, title_label, has_body, body_label, min_word_count, custom, modified, locked, orig_type) VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s', %d, '%s', %d, %d, %d, %d, '%s')", $info->type, $info->name, $info->module, $info->description, $info->help, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->min_word_count, $info->custom, $info->modified, $info->locked, $info->orig_type); module_invoke_all('node_type', 'insert', $info); drupal_set_message(t('Node type created.')); } if ($_FILES['files']['size']['attachment'] > 0) { $file_data = fread(fopen($_FILES['files']['tmp_name']['attachment'], 'r'), filesize($_FILES['files']['tmp_name']['attachment'])); $file_dest = variable_get('mass_contact_attachment_location', file_directory_path() .'/mass_contact_attachments'); // .'/'; file_check_directory($file_dest, FILE_CREATE_DIRECTORY); $file_path = file_save_data($file_data, $file_dest .'/'. $_FILES['files']['name']['attachment'], FILE_EXISTS_RENAME); $file_url = file_create_url($file_path); $node_body .= '
Attachment:
'. l($_FILES['files']['name']['attachment'], $file_url); } // Save the message as a node. if (mass_contact_save_node($subject, $node_body, $recipientout, $contact->category, $roles, $user->uid)) { // Get new node id. $nidobj = db_fetch_object(db_query("SELECT nid FROM {node} WHERE type = 'mass_contact' ORDER BY changed DESC")); $nid = $nidobj->nid; // Log node creation. watchdog('content', t('Mass Contact content added "%title".', array('%title' => $subject)), WATCHDOG_NOTICE, l(t('View.'), "node/$nid")); // Inform the user. drupal_set_message(t('A carbon copy has been created as a node.')); } } // Log the operation. flood_register_event('mass_contact'); watchdog('mass_contact', t('%name-from sent an e-mail to the %category group.', array('%name-from' => $form_values['name'] ." <$from>", '%category' => $contact->category))); // Inform the user. drupal_set_message(t('Message sent successfully to !total users: -e-mails', array('!total' => $total_recip, '-e-mails' => $recipientout))); } else { drupal_set_message(t('!errors error(s) encountered sending message. Please check the logs and try again.', array('!errors' => $send_error))); } // Jump to home page rather than back to mail page to avoid // contradictory messages if flood control has been activated. return (''); } // End of mass_contact_mail_page_submit(). /** * Implementation of hook_nodeapi. * http://api.drupal.org/api/function/hook_nodeapi * * @param node * The node the action is being performed on. * @param op * The action that is being performed. * @param a3 * The third argument. Has specific functions based on $op. * @param a4 * The fourth argument. Has specific functions based on $op. * @return * Varies depending on the operation. */ function mass_contact_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { // If this is a delete operation and the node type is mass_contact, then // check for an attachment and delete the file if one exists. if ($op == 'delete' && $node->type == 'mass_contact') { // Look for the key phrase in the node body. If it exists, then there is // an attachment that needs to be deleted. $offset1 = strpos($node->body, '
Attachment:
'); if ($offset1) { // Using the saved attachment path, find the file name. $file_location = variable_get('mass_contact_attachment_location', file_directory_path() .'/mass_contact_attachments'); $file_location_start = strpos($node->body, $file_location, $offset1); if ($file_location_start) { // Get the attachment file name. $file_location_end = strpos($node->body, '">', $file_location_start); $file_path_name = substr($node->body, $file_location_start, $file_location_end - $file_location_start); if (file_exists($file_path_name)) { if (!file_delete($file_path_name)) { // Log an error. watchdog('mass_contact', t('There was an error deleting the attachment.'), WATCHDOG_ERROR); } } else { // Log an error. watchdog('mass_contact', t('There was an indication of an attachment within the node body, but the attachment was not found. If the attachment is still there, it was NOT deleted.'), WATCHDOG_WARNING); } } else { // Log an error. watchdog('mass_contact', t('There was an indication of an attachment within the node body, but the attachment path was not found. If the attachment is still there, it was NOT deleted.'), WATCHDOG_WARNING); } } } } // End of mass_contact_nodeapi(). /** * Save the sent mail as a node. * * @param subject * The subject of the message and the title of the node. * @param body * The body of the message and node. * @param recipients * The users who received a copy of the message. * @param category * The category of users sent to. * @param roles * The various roles the category represents. * @param uid * The user who sent the message is also the user who owns the node. */ function mass_contact_save_node($subject, $body, $recipients, $category, $roles, $uid) { // get role names foreach ($roles as $r) { $roletemp = db_fetch_object(db_query("SELECT name FROM {role} WHERE rid = %d", $r)); $rolesenta[] = $roletemp->name; } $rolesent = implode(', ', $rolesenta); $node->title = $subject; $node->body = '

'. t('Category: ') . $category .'

'. t('Roles: ') . $rolesent .'

'. t('Recipients: ') . $recipients .'

'. $body; $node->teaser = node_teaser($node->body); $node->type = 'mass_contact'; $node->uid = $uid; $node->format = 3; $node->status = 0; $node->comment = 2; $node->promote = 0; $node->sticky = 0; node_save($node); return TRUE; } // End of mass_contact_save_node().