mailhandler.module in Mailhandler 6
Same filename and directory in other branches
Mailhandler module code.
Mailhandler module allows content submission via email: create or edit nodes and comments. Authentication is flexible allowing additional plugins to grant authorization, but a default authentication method is provided based on the "From:" field of the email, the origin address. Users may define additional submission attributes like: taxonomy terms, teasers and others, using the Commands capability.
See also
http://drupal.org/node/38943 Command documentation.
File
mailhandler.moduleView source
<?php
/**
* @file
* Mailhandler module code.
*
* Mailhandler module allows content submission via email: create or edit nodes
* and comments. Authentication is flexible allowing additional plugins to grant
* authorization, but a default authentication method is provided based on the
* "From:" field of the email, the origin address. Users may define additional
* submission attributes like: taxonomy terms, teasers and others, using the
* Commands capability.
*
* @see http://drupal.org/node/38943 Command documentation.
*/
/**
* @defgroup mailhandler_drupal_hooks Mailhandler Drupal hooks
* @{
* Drupal hook implementations used by Mailhandler.
*/
/**
* Implementation of hook_cron().
*
* Retrieve and process mesages from all enabled mailboxes.
*/
function mailhandler_cron() {
// @todo: remove this include when the retriever gets decoupled.
// @todo: add mailhandler_watchdog_record functions.
module_load_include('inc', 'mailhandler', 'mailhandler.retrieve');
// Get only enabled for cron mailboxes.
$mailboxes = mailhandler_mailbox_load_multiple(array(), array(
'enabled' => TRUE,
));
// Process mailboxes.
foreach ($mailboxes as $mid => $mailbox) {
mailhandler_node_process_mailbox((array) $mailbox, 'auto');
}
}
/**
* Implementation of hook_perm().
*/
function mailhandler_perm() {
return array(
'administer mailhandler',
);
}
/**
* Implementation of hook_menu().
*/
function mailhandler_menu() {
$items = array();
$items['admin/content/mailhandler'] = array(
'title' => 'Mailhandler Mailboxes',
'description' => 'Manage mailboxes and retrieve messages.',
'page callback' => 'mailhandler_list_mailboxes',
'access arguments' => array(
'administer mailhandler',
),
'file' => 'mailhandler.admin.inc',
);
$items['admin/content/mailhandler/list'] = array(
'title' => 'List',
'description' => 'Manage mailboxes and retrieve messages.',
'type' => MENU_DEFAULT_LOCAL_TASK,
'access arguments' => array(
'administer mailhandler',
),
'weight' => -10,
);
$items['admin/content/mailhandler/add'] = array(
'title' => 'Add mailbox',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailhandler_add_edit_mailbox',
NULL,
),
'access arguments' => array(
'administer mailhandler',
),
'type' => MENU_LOCAL_TASK,
'file' => 'mailhandler.admin.inc',
);
$items['admin/content/mailhandler/clone/%mailhandler_mailbox'] = array(
'title' => 'Add mailbox',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailhandler_add_edit_mailbox',
4,
TRUE,
),
'access arguments' => array(
'administer mailhandler',
),
'type' => MENU_CALLBACK,
'file' => 'mailhandler.admin.inc',
);
$items['admin/content/mailhandler/retrieve/%mailhandler_mailbox'] = array(
'title' => 'Retrieve',
'page callback' => 'mailhandler_node_process_mailbox',
'page arguments' => array(
4,
'ui',
),
'access arguments' => array(
'administer mailhandler',
),
'type' => MENU_CALLBACK,
'file' => 'mailhandler.retrieve.inc',
);
$items['admin/content/mailhandler/edit/%mailhandler_mailbox'] = array(
'title' => 'Edit mailbox',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailhandler_add_edit_mailbox',
4,
),
'access arguments' => array(
'administer mailhandler',
),
'type' => MENU_CALLBACK,
'file' => 'mailhandler.admin.inc',
);
$items['admin/content/mailhandler/delete/%mailhandler_mailbox'] = array(
'title' => 'Delete mailbox',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailhandler_admin_delete_confirm',
4,
),
'access arguments' => array(
'administer mailhandler',
),
'type' => MENU_CALLBACK,
'file' => 'mailhandler.admin.inc',
);
$items['admin/settings/mailhandler'] = array(
'title' => 'Mailhandler Settings',
'description' => t('Set the default content type for incoming messages and set the cron limit.'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailhandler_admin_settings',
),
'access arguments' => array(
'administer mailhandler',
),
'file' => 'mailhandler.admin.inc',
);
return $items;
}
/**
* Implementation of hook_help().
*/
function mailhandler_help($path = 'admin/help#mailhandler', $arg) {
$output = '';
// Gather examples of useful commands, and build a definition list with them:
$commands[] = array(
'command' => 'taxonomy: [term1, term2]',
'description' => t('Use this to add the terms <em>term1</em> and <em>term2</em> to the node.<br />
Both of the terms should already exist. In case they do not exist already, they will be quietly ommitted'),
);
$commands[] = array(
'command' => 'taxonomy[v]: [term1, term2]',
'description' => t('Similar to the above: adds the terms <em>term1</em> and <em>term2</em> to the node, but uses the vocabulary with the vocabulary id <em>v</em>. For example <em>taxonomy[3]</em> will chose only terms from the vocabulary which id is 3.<br />
In case some of the terms do not exist already, the behavior will depend on whether the vocabulary is a free tagging vocabulary or not. If it is a free tagging vocabulary, the term will be added, otherwise, it will be quietly ommitted'),
);
$commands_list = '<dl>';
foreach ($commands as $command) {
$commands_list .= '<dt>' . $command['command'] . '</dt>';
$commands_list .= '<dl>' . $command['description'] . '</dl>';
}
$commands_list .= '</dl>';
switch ($path) {
case 'admin/help#mailhandler':
$output = '<p>' . t('The mailhandler module allows registered users to create or edit nodes and comments via e-mail. Users may post taxonomy terms, teasers, and other post attributes using the mail commands capability. This module is useful because e-mail is the preferred method of communication by community members.') . '</p>';
$output .= '<p>' . t('The mailhandler module requires the use of a custom mailbox. Administrators can add mailboxes that should be customized to meet the needs of a mailing list. This mailbox will then be checked on every cron job. Administrators may also initiate a manual retrieval of messages.') . '</p>';
$output .= '<p>' . t('This is particularly useful when you want multiple sets of default commands. For example , if you want to authenticate based on a non-standard mail header like Sender: which is useful for accepting submissions from a listserv. Authentication is usually based on the From: e-mail address. Administrators can edit the individual mailboxes when they administer mailhandler.') . '</p>';
$output .= t('<p>You can</p>
<ul>
<li><a href="@run-cron">run cron</a> to retrieve messages from all cron enabled mailboxes.</li>
<li>list mailboxes at <a href="@admin-mailhandler">Administer >> Content management >> Mailhandler</a>.</li>
<li>add a mailbox at <a href="@admin-mailhandler-add">Administer >> Content management >> Mailhandler >> Add mailbox.</a></li>
<li>set default commands, (password, type, taxonomy, promote, status), for how to work with incoming mail at <a href="%admin-mailhandler">Administer >> Content management >> Mailhandler</a> and select <strong>edit</strong> for the email address being handled. Set commands in the default command field.</li>
<li>post email, such as from a mailing list, to a forum by adding the term id (number found in the URL) to the default commands using <strong>tid: #</strong>.</li>
<li>alter mailhandler settings (default content type and cron threshold) at <a href="@admin-mailhandler-settings">Administer >> Site configuration >> Mailhandler</a>.</li>
</ul>', array(
'@run-cron' => url('admin/logs/status/run-cron'),
'@admin-mailhandler-add' => url('admin/content/mailhandler/add'),
'@admin-mailhandler' => url('admin/content/mailhandler'),
'@admin-mailhandler-settings' => url('admin/settings/mailhandler'),
));
$output .= '<h3 id="commands">' . t('Useful Commands') . '</h3>';
$output .= $commands_list;
$output .= '<p>' . t('For more information please read the configuration and customization handbook <a href="@mailhandler">Mailhandler page</a>.', array(
'@mailhandler' => url('http://www.drupal.org/handbook/modules/mailhandler', array(
'absolute' => TRUE,
)),
)) . '</p>';
return $output;
case 'admin/content/mailhandler':
return t('The mailhandler module allows registered users to create or edit nodes and comments via email. Authentication is usually based on the From: email address. There is also an email filter that can be used to prettify incoming email. Users may post taxonomy terms, teasers, and other node parameters using the Command capability.');
case 'admin/content/mailhandler/add':
return t('Add a mailbox whose mail you wish to import into Drupal. Can be IMAP, POP3, or local folder.');
case 'admin/content/mailhandler/edit/%':
return t('Edit the mailbox whose mail you wish to import into Drupal. Can be IMAP, POP3, or local folder.');
case 'admin/settings/mailhandler':
return t('The mailhandler module allows registered users to create or edit nodes and comments via e-mail.');
}
}
/**
* @} End of "defgroup mailhandler_drupal_hooks".
*/
/**
* @defgroup mailhandler_mailbox_crud Mailhandler Mailbox database operations
* @{
* The CRUD implemented here mimics the way CRUD operations are being done in
* most of Drupal API implementations, to make it easy to maintain.
*/
/**
* Load a mailbox array from database.
*
* Return a mailbox information based on the ID passed as parameter.
*
* @param $mid
* Int mailbox ID to load
* @param $conditions
* An associative array of conditions on the {mailhandler} table, where the
* keys are the database fields and the values are the values those fields
* must have.
* @param $reset
* Whether to reset the internal mailhandler_mailbox_load cache. Unimplemented
* to make module versions easy to maintain.
* @return
* Array of mailbox configuration
*/
function mailhandler_mailbox_load($mid, $conditions = array(), $reset = FALSE) {
// Convert single mid to array for load multiple calls.
$mids = isset($mid) ? array(
$mid,
) : array();
// Load the mailbox information.
$mailbox = mailhandler_mailbox_load_multiple($mids, $conditions, $reset);
// Record debug information.
mailhandler_watchdog_record('Mailbox loaded: @mailbox', array(
'@mailbox' => var_export($mailbox, TRUE),
), WATCHDOG_DEBUG);
// return the mailbox or FALSE.
return $mailbox ? (array) reset($mailbox) : FALSE;
}
/**
* Load mailboxes from the database.
*
* This function should be used whenever you need to load more than one mailbox
* from the database. Mailboxes are loaded into memory and will not require
* database access if loaded again during the same page request.
*
* @param $mids
* An array of mailboxes IDs. If specified, the conditions will be applied to
* this group of mailboxes.
* @param $conditions
* An associative array of conditions on the {mailhandler} table, where the
* keys are the database fields and the values are the values those fields
* must have. This filter will return only mailboxes matching all the values.
* @param $reset
* Whether to reset the internal mailhandler_mailbox_load cache.
* @return
* An array of mailboxes indexed by mid
*/
function mailhandler_mailbox_load_multiple($mids = array(), $conditions = array(), $reset = FALSE) {
$mailboxes = array();
// Use these variables to compose the query based on $conditions array.
$schema = drupal_get_schema('mailhandler');
$fields = drupal_schema_fields_sql('mailhandler');
$conds = $params = array();
// Select from this group of mailboxes if defined.
if (count($mids)) {
$conds[] = 'mid IN (' . db_placeholders($mids, 'int') . ')';
foreach ($mids as $mid) {
$params[] = intval($mid);
}
}
// Apply the conditions filter.
foreach ($conditions as $key => $value) {
if (in_array($key, $fields)) {
$conds[] = $key . " = " . db_type_placeholder($schema['fields'][$key]['type']);
$params[] = $value;
}
}
// Record debug information.
if (count($conditions)) {
mailhandler_watchdog_record('Mailboxes loading conditions: @conditions', array(
'@conditions' => var_export(array_keys($conditions), TRUE),
), WATCHDOG_DEBUG);
}
// Build and execute the query.
$cond = count($conds) ? ' WHERE ' . implode(' AND ', $conds) : '';
$result = db_query('SELECT ' . implode(', ', $fields) . ' FROM {mailhandler}' . $cond, $params);
// Populate the return array.
$search = array();
while ($mailbox = db_fetch_object($result)) {
$mailboxes[$mailbox->mid] = $mailbox;
}
// Record debug information.
mailhandler_watchdog_record('Mailboxes loaded: @mailboxes', array(
'@mailboxes' => var_export(array_keys($mailboxes), TRUE),
), WATCHDOG_DEBUG);
return $mailboxes;
}
/**
* Validate a Mailhandler Mailbox.
*
* Validate the mailbox and set form errors. Even if this function is not used
* in a form (e.g. validating mailboxes created programatically), the function
* will still set form errors. These errors can be later recalled using the
* function form_get_errors().
*
* <code>
* mailhandler_mailbox_validate($mailbox);
* if ($errors = form_get_errors()) {
* do_my_error_handling($errors);
* }
* else {
* mailhandler_mailbox_save($mailbox);
* }
* </code>
*
* @param $mailbox
* A mailbox settings array.
* @param $form
* The $form where mailbox is being edited.
* @param $form_state
* The $form_state values of the form being validated.
*/
function mailhandler_mailbox_validate($mailbox, $form = array(), &$form_state = array()) {
// Check for valid email address.
if ($error = user_validate_mail($mailbox['mail'])) {
form_set_error('mail', $error);
}
// Set form error in case the email address does not comply email format.
if ($form_state['values']['mailto'] && ($error = user_validate_mail($mailbox['mailto']))) {
form_set_error('mailto', $error);
}
// Test POP/IMAP settings, and store result.
$mailbox_appears_ok = TRUE;
// Assume external mailbox.
if ($mailbox['domain'] && $mailbox['port'] && !is_numeric($mailbox['port'])) {
form_set_error('port', t('Mailbox port must be an integer.'));
$mailbox_appears_ok = FALSE;
}
// Assume local folder.
if (!$mailbox['domain'] && !$mailbox['port'] && $mailbox['folder']) {
// check read and write permission
if (!is_readable($mailbox['folder']) || !is_writable($mailbox['folder'])) {
form_set_error('port', t('The local folder has to be readable and writable by owner of the webserver process, e.g. nobody.'));
$mailbox_appears_ok = FALSE;
}
}
// If POP3 mailbox is chosen, messages must be deleted after processing or
// they will be imported on each retrieval process. Warm about this case when
// trying to save the mailbox.
if ($mailbox['imap'] == 0 && $mailbox['delete_after_read'] == 0) {
form_set_error('delete_after_read', t('You must check off "Delete messages after they are processed" when using a POP3 mailbox.'));
}
}
/**
* Save a Mailhandler Mailbox in the database.
*
* When $mailbox has 'mid' attribute defined, the database entry with this ID
* will be updated, otherwise a new mailbox will be created.
*
* @param $mailbox
* A mailbox settings array.
*/
function mailhandler_mailbox_save(&$mailbox) {
// Determine this is an update or a new mailbox.
$update = isset($mailbox['mid']) && $mailbox['mid'] ? array(
'mid',
) : array();
// Set default values for missing mailbox attributes.
$mailbox += mailhandler_mailbox_defaults();
// Save entry into database.
drupal_write_record('mailhandler', $mailbox, $update);
// Record information message
mailhandler_watchdog_record('Mailbox %mailbox saved.', array(
'%mailbox' => $mailbox['mail'],
), WATCHDOG_INFO);
}
/**
* Delete a Mailhandler Mailbox from the database.
*
* When $mailbox has 'mid' attribute defined, the database entry with this ID
* will be deleted.
*
* @param $mid
* mailbox ID to be deleted.
*/
function mailhandler_mailbox_delete($mailbox) {
$mid = isset($mailbox['mid']) ? $mailbox['mid'] : $mailbox;
db_query("DELETE FROM {mailhandler} WHERE mid = %d", $mid);
// Record information message
mailhandler_watchdog_record('Mailbox %mailbox deleted.', array(
'%mailbox' => isset($mailbox['mail']) ? $mailbox['mail'] : $mid,
), WATCHDOG_INFO);
}
/**
* @} End of "defgroup mailhandler_mailbox_crud".
*/
/**
* @defgroup mailhandler_mailbox_processing Mailbox processing functions.
* @{
* Functions used to process Mailhandler mailboxes. These functions performs the
* mailbox connection, queue processing and data retrieval, but do not generate
* site content.
*/
/**
* Test the connection to a mailbox.
*
* Attempt a mailbox connection and set form errors. Even if this function is
* not used in a form (e.g. testing mailboxes created programatically), the
* function will still set form errors. These errors can be later recalled using
* the function form_get_errors().
*
* <code>
* mailhandler_mailbox_test($mailbox);
* if ($errors = form_get_errors()) {
* do_my_error_handling($errors);
* }
* else {
* mailhandler_mailbox_save($mailbox);
* }
* </code>
*
* This function can be called safely from within a form.
*
* @param $mailbox
* A mailbox settings array.
* @param $form
* The $form where mailbox is being edited.
* @param $form_state
* The $form_state values of the form being validated.
*/
function mailhandler_mailbox_test($mailbox, $form = array(), &$form_state = array()) {
$result = FALSE;
// Verify the mailbox by connecting and getting mailbox status.
if ($stream = mailhandler_mailbox_stream_open($mailbox)) {
// Close stream to mailbox.
mailhandler_mailbox_stream_close($stream);
$result = TRUE;
}
else {
if ($mailbox['domain']) {
form_set_error('mailhandler', t('%c connection to %m failed.', array(
'%c' => $mailbox['imap'] ? 'IMAP' : 'POP3',
'%m' => $mailbox['mail'],
)));
}
else {
form_set_error('mailhandler', t('Mailhandler could not access local folder: %m', array(
'%m' => $mailbox['mail'],
)));
}
}
return $result;
}
/**
* @} End of "defgroup mailhandler_mailbox_processing".
*/
/**
* @defgroup mailhandler_mailbox_stream Mailbox stream functions.
* @{
* Functions used to handle mailbox streams. These functions are responsible of
* connecting or opening mailboxes, reading status and messages and remove the
* processed entries.
*
* Note: all functions making use of PHP imap extension should go in this group.
*/
/**
* Establish stream connection to specified mailbox.
*
* @param $mailbox
* Array of mailbox configuration.
* @return
* stream to work with other stream processing functions or FALSE.
*/
function mailhandler_mailbox_stream_open($mailbox) {
// Build the mailbox string from mailbox settings.
$proto = array(
'pop',
'imap',
);
// Build imap_open arguments.
$box = array(
'path' => $mailbox['domain'] ? '{' . $mailbox['domain'] . ':' . $mailbox['port'] . '/' . $proto[$mailbox['imap']] . $mailbox['extraimap'] . '}' . $mailbox['folder'] : $mailbox['folder'],
'user' => $mailbox['domain'] ? $mailbox['name'] : '',
'pass' => $mailbox['domain'] ? $mailbox['pass'] : '',
);
// Open stream (imap, pop or local folder).
$result = imap_open($box['path'], $box['user'], $box['pass']);
// Record a debug message to inform about no errors opening the stream.
mailhandler_watchdog_record('Opening stream to %box: %result.', array(
'%box' => $box['path'],
'%result' => !imap_last_error(),
), WATCHDOG_DEBUG);
// Provide a warning message when imap_open returns error.
if (!$result) {
// Record error from imap extension.
mailhandler_watchdog_record('Error opening %box: %error.', array(
'%box' => $box['path'],
'%error' => imap_last_error(),
), WATCHDOG_WARNING);
}
return $result;
}
/**
* Close stream connection.
*
* @param $stream
* stream openned using mailhandler_mailbox_stream_open().
* @return
* boolean result of closing operation
*/
function mailhandler_mailbox_stream_close($stream) {
$result = imap_close($stream);
// Record debug information about stream closing operation.
mailhandler_watchdog_record('Closing mailbox stream: %result.', array(
'%result' => !imap_last_error(),
), WATCHDOG_DEBUG);
return $result;
}
/**
* Get number of messages in the stream connection.
*
* @param $stream
* stream openned using mailhandler_mailbox_stream_open().
* @return
* boolean result of closing operation
*/
function mailhandler_mailbox_stream_count($stream) {
$result = imap_num_msg($stream);
// Record debug information about stream closing operation.
mailhandler_watchdog_record('Messages in stream = %total : %result.', array(
'%result' => !imap_last_error(),
'%total' => $result,
), WATCHDOG_DEBUG);
return $result;
}
/**
* Return a message matching the requested conditions.
*
* @param $stream stream openned using mailhandler_mailbox_stream_open().
* @param $msgno message number to retrieve.
* @param $conditions associative array of conditions to retrieve a message.
* When using IMAP connections, the retrieving process can be improved by
* checking the message header first. Conditions are based on IMAP header
* information, E.g. to retrieve only unread emails you can specify the
* 'Unseen' => 'U' condition.
* @return
* boolean result of closing operation
*/
function mailhandler_mailbox_stream_retrieve($stream, $msgno = 0, $conditions = array()) {
// Add default conditions, get unread messages.
$conditions += array(
'Unseen' => 'U',
);
// Get Message header information. In case of POP driver, the function will
// return the whole message, so we should make no additional calls and return
// the result.
$result = imap_headerinfo($stream, $msgno);
die('@todo: Incomplete function');
// Record debug information about stream closing operation.
mailhandler_watchdog_record('Retrieving message %Msgno : %result.', array(
'%result' => !imap_last_error(),
'%Msgno' => $conditions['Msgno'],
), WATCHDOG_DEBUG);
return $result;
}
/**
* Delete a message in the stream connection.
*
* @param $stream stream openned using mailhandler_mailbox_stream_open().
* @param $msgno number of message to delete.
* @return
* boolean result of deleting operation
*/
function mailhandler_mailbox_stream_delete($stream, $msgno = 0) {
$result = imap_delete($stream, $msgno);
// Record debug information about stream closing operation.
mailhandler_watchdog_record('Delete message %msgno : %result.', array(
'%result' => !imap_last_error(),
'%msgno' => $msgno,
), WATCHDOG_DEBUG);
return $result;
}
/**
* @} End of "defgroup mailhandler_mailbox_stream".
*/
/**
* Return a default content type if the user has not chosen a specific type on the settings page
* In order of priority, return blog, story, page
* This assumes that one of these basic types is in use on a site (page and story are active by default)
* A user can choose other content types via the settings page as this exposes all available types
*/
function mailhandler_default_type() {
// Get the current default setting, if defined.
$default_type = variable_get('mailhandler_default_type', NULL);
// Find out what types are available.
$available_types = node_get_types('names');
// Check the default type is still available (it could have been deleted).
if ($default_type && array_key_exists($default_type, $available_types)) {
return $default_type;
}
// If we get here then either no default is set, or the default type is no longer available
// Search for the array key (the machine readable name) for blog, story and page basic types
if (array_key_exists('blog', $available_types)) {
$default_type = 'blog';
}
else {
if (array_key_exists('story', $available_types)) {
$default_type = 'story';
}
else {
if (array_key_exists('page', $available_types)) {
$default_type = 'page';
}
else {
// If basic types not found then return the first item from the array as an alternative default
$default_type = key($available_types);
}
}
}
return $default_type;
}
/**
* Run message retrieval and node processing on a mailbox - is a wrapper around mailhandler_retrieve
*
* Batch API smashes the stack, so this function is called twice when fetching
* messages via batch in order to return the results from the batch.
*
* @param $mailbox
* Array of mailbox configuration
* @param $mode
* String ui or auto (ie cron) processing
* @param $limit
* Int maximum number of messages to retrieve
* @param $messages
* Array of retrieved messages
*/
function mailhandler_node_process_mailbox($mailbox = FALSE, $mode = FALSE, $limit = FALSE, $messages = array()) {
// Set default maximun message limit according to general settings.
$limit = isset($limit) ? $limit : variable_get('mailhandler_max_retrieval', 0);
if (empty($messages)) {
if ($mode == 'ui') {
mailhandler_retrieve($mailbox, $mode, $limit);
}
else {
if ($messages = mailhandler_retrieve($mailbox, $mode, $limit)) {
foreach ($messages as $message) {
mailhandler_node_process_message($message['header'], $message['origbody'], $message['mailbox'], $message['mimeparts']);
}
}
}
}
else {
// See mailhandler_mailhandler_batch_results. This hook is invoked
// and mailhandler_process_mailbox is called a second time in order
// to obtain the messages that were retrieved and continue processing.
// This is necessary because we cannot obtain the results back from
// batch processing directly.
foreach ($messages as $message) {
mailhandler_node_process_message($message['header'], $message['origbody'], $message['mailbox'], $message['mimeparts']);
}
}
}
/**
* Implementation of hook_mailhandler_batch_results()
*
* See mailhandler_process_mailbox()
*
*/
function mailhandler_mailhandler_batch_results($results) {
mailhandler_node_process_mailbox(FALSE, FALSE, FALSE, $results);
// Give the results back for any other modules to use
return $results;
}
// TODO: add arguments
function mailhandler_node_process_message($header, $origbody, $mailbox, $mimeparts) {
mailhandler_user_switch();
// we must process before authenticating because the password may be in Commands
$node = mailhandler_node_prepare_message($header, $origbody, $mailbox);
// Authenticate the message
if (!($node = mailhandler_mailhandler_authenticate('execute', $mailbox['authentication'], array(
$node,
$header,
$origbody,
$mailbox,
)))) {
mailhandler_watchdog_record('Message failed authentication.', array(), WATCHDOG_NOTICE);
return FALSE;
}
// Put $mimeparts on the node
$node->mimeparts = $mimeparts;
// we need to change the current user
// this has to be done here to allow modules
// to create users
mailhandler_user_switch($node->uid);
// modules may override node elements before submitting. they do so by returning the node.
foreach (module_list() as $name) {
if (module_hook($name, 'mailhandler')) {
$function = $name . '_mailhandler';
// @todo: hook_mailhandler implementation is broken. When this function
// was moved out of the retrieve loop, some of the variables where not
// updated.
$result = $i = NULL;
if (!($node = $function($node, $result, $i, $header, $mailbox))) {
// Exit if a module has handled the submitted data.
break;
}
}
}
if ($node) {
if ($node->type == 'comment') {
$saved = mailhandler_comment_submit($node, $header, $mailbox, $origbody);
$type = 'comment';
}
else {
$saved = mailhandler_node_submit($node, $header, $mailbox, $origbody);
$type = 'node';
}
}
// Invoke a second hook for modules to operate on the newly created/edited node/comment.
foreach (module_list() as $name) {
if (module_hook($name, 'mailhandler_post_save')) {
$function = $name . '_mailhandler_post_save';
// Pass in what's returned from saving the comment (cid) or node (object), the
// object type, and the original node object (which is the same as $saved in
// the case of saving a node).
$function($saved, $type, $node);
}
}
// switch back to original user
mailhandler_user_switch();
// Put something in the results array for the counter in the batch finished callback
$context['results'][] = $mailbox['mail'];
mailhandler_user_switch();
}
/**
* Append default commands. Separate commands from body. Strip signature.
* Return a node object.
*/
function mailhandler_node_prepare_message($header, $body, $mailbox) {
// Initialise a node object
$node = new stdClass();
$node->pass = NULL;
// Initialize parameters
$sep = $mailbox['sigseparator'];
// Copy any name/value pairs from In-Reply-To or References e-mail headers to $node. Useful for maintaining threading info.
if (!empty($header->references)) {
// we want the final element in references header, watching out for white space
$threading = substr(strrchr($header->references, '<'), 0);
}
else {
if (!empty($header->in_reply_to)) {
$threading = str_replace(strstr($header->in_reply_to, '>'), '>', $header->in_reply_to);
// Some MUAs send more info in that header.
}
}
if (isset($threading) && ($threading = rtrim(ltrim($threading, '<'), '>'))) {
//strip angle brackets
if ($threading) {
$node->threading = $threading;
}
parse_str($threading, $tmp);
if (isset($tmp['host']) && $tmp['host']) {
$tmp['host'] = ltrim($tmp['host'], '@');
// strip unnecessary @ from 'host' element
}
foreach ($tmp as $key => $value) {
$node->{$key} = $value;
}
}
// Prepend the default commands for this mailbox
if ($mailbox['commands']) {
$body = trim($mailbox['commands']) . "\n" . $body;
}
if ($commands = mailhandler_commands_parse($body, $sep)) {
// Record debug information.
mailhandler_watchdog_record('Message unprocessed commands: @commands', array(
'@commands' => var_export($commands, TRUE),
), WATCHDOG_DEBUG);
// The node type must be set first in order to properly initialize the node
foreach ($commands['commands'] as $command) {
if ($command[0] == 'type') {
$node->type = $command[1];
}
}
}
// Set a default type if none provided
if (!isset($node->type)) {
$node->type = mailhandler_default_type();
}
// Apply defaults to the $node object, and allow modules to add default values
require_once drupal_get_path('module', 'node') . '/node.pages.inc';
if ($node->type != 'comment') {
node_object_prepare($node);
}
// If cron is called by anon then node_object_prepare sets uid to 0, but otherwise global $user.
// Manually set this to 0 since that's what the rest of the code expects.
$node->uid = 0;
// In order to fall back to the permission system for comment status, the status property must
// be unset if type is comment. It will get set by explicit commands, and if not, by
// comment_save itself.
if ($node->type == 'comment') {
unset($node->status);
}
// Execute the commands
if (!empty($commands['commands'])) {
mailhandler_node_process_message_commands($node, $commands['commands']);
// Record debug information.
mailhandler_watchdog_record('Node processed commands: @node', array(
'@node' => var_export($node, TRUE),
), WATCHDOG_DEBUG);
}
// Isolate the body from the commands and the sig
$tmp = array_slice($commands['lines'], $commands['endcommands'], $commands['i'] - $commands['endcommands']);
// flatten and assign the body to node object. note that filter() is called within node_save() [tested with blog post]
if ($node->type != 'comment') {
$type = node_get_types('type', $node->type);
}
if (isset($type) && $type && $type->has_body || $node->type == 'comment') {
$node->body = implode("\n", $tmp);
}
if (empty($node->teaser)) {
$node->teaser = node_teaser($node->body);
}
// decode encoded subject line
$subjectarr = imap_mime_header_decode($header->subject);
if (empty($subjectarr)) {
$node->title = truncate_utf8(trim(decode_entities(strip_tags(check_markup($node->body)))), 29, TRUE);
}
else {
for ($i = 0; $i < count($subjectarr); $i++) {
if ($subjectarr[$i]->charset != 'default') {
$node->title .= drupal_convert_to_utf8($subjectarr[$i]->text, $subjectarr[$i]->charset);
}
else {
$node->title .= $subjectarr[$i]->text;
}
}
}
$node->date = $node->changed = format_date($header->udate, 'custom', 'Y-m-d H:i:s O');
$node->format = $mailbox['format'];
// If an nid command was supplied, and type is not 'comment', append the revision number
if (isset($node->nid) && !empty($node->nid) && $node->type != 'comment') {
$vid = db_result(db_query('SELECT n.vid FROM {node} n WHERE n.nid = %d', $node->nid));
if ($vid) {
$node->revision = $node->vid = $vid;
}
}
// Debug message with node before creation.
mailhandler_watchdog_record('Node or comment: @node', array(
'@node' => var_export($node, TRUE),
), WATCHDOG_DEBUG);
return $node;
}
/**
* Create the comment.
*/
function mailhandler_comment_submit($node, $header, $mailbox, $origbody) {
global $user;
if (!$node->subject) {
$node->subject = $node->title;
}
// When submitting comments, 'comment' means actualy the comment's body, and not the comments status for a node.
// We need to reset the comment's body, so it doesn't colide with a default 'comment' command.
$node->comment = $node->body;
// comment_save will not fall back to permission system if we set the status explicitly
// See comment_save. += will not overwrite an existing array property.
if (property_exists($node, 'status')) {
// In comment module, status of 1 means unpublished, status of 0 means published.
$node->status == 1 ? $node->status = 0 : ($node->status = 1);
}
// We want the comment to have the email time, not the current time
$node->timestamp = $node->created = $header->udate;
// comment_save gets an array
$edit = (array) $node;
// post the comment. if unable, send a failure email when so configured
$cid = comment_save($edit);
if (!$cid && $mailbox['replies']) {
// $fromaddress really refers to the mail header which is authoritative for authentication
list($fromaddress, $fromname) = mailhandler_get_fromaddress($header, $mailbox);
$error_text = t('Sorry, your comment experienced an error and was not posted. Possible reasons are that you have insufficient permission to post comments or the node is no longer open for comments.');
$params = array(
'body' => $origbody,
'error_messages' => array(),
'error_text' => $error_text,
'from' => $fromaddress,
'header' => $header,
'node' => $node,
);
drupal_mail('mailhandler', 'mailhandler_error_comment', $fromaddress, user_preferred_language($user), $params);
mailhandler_watchdog_record('Comment submission failure: %subject.', array(
'%subject' => $edit['subject'],
), WATCHDOG_NOTICE);
// Record debug information.
mailhandler_watchdog_record('Comment submission failure: @comment', array(
'@comment' => var_export($edit, TRUE),
), WATCHDOG_DEBUG);
}
return $cid;
}
/**
* Create the node.
*/
function mailhandler_node_submit($node, $header, $mailbox, $origbody) {
global $user;
list($fromaddress, $fromname) = mailhandler_get_fromaddress($header, $mailbox);
// Reset the static cache
form_set_error(NULL, '', TRUE);
node_validate($node);
if (!($error_messages = form_set_error())) {
// Prepare the node for save and allow modules make changes
$node = node_submit($node);
// Save the node
if (!empty($node->nid)) {
if (node_access('update', $node)) {
node_save($node);
mailhandler_watchdog_record('Updated %title by %from.', array(
'%title' => $node->title,
'%from' => $fromaddress,
));
}
else {
$error_text = t('The e-mail address !from may not update !type items.', array(
'!from' => $fromaddress,
'!type' => $node->type,
));
mailhandler_watchdog_record('Node submission failure: %from may not update %type items.', array(
'%from' => $fromaddress,
'%type' => $node->type,
), WATCHDOG_NOTICE);
}
}
else {
$account = user_load($node->uid);
if (node_access('create', $node, $account)) {
node_save($node);
mailhandler_watchdog_record('Added %title by %from.', array(
'%title' => $node->title,
'%from' => $fromaddress,
));
}
else {
$error_text = t('The e-mail address !from may not create !type items.', array(
'!from' => $fromaddress,
'!type' => $node->type,
));
mailhandler_watchdog_record('Node submission failure: %from may not create %type items.', array(
'%from' => $fromaddress,
'%type' => $node->type,
), WATCHDOG_NOTICE);
}
}
// Return the node is successfully saved
if (!isset($error_text)) {
return $node;
}
}
else {
$error_text = t('Your submission is invalid:');
mailhandler_watchdog_record('Node submission failure: validation error.', array(), WATCHDOG_NOTICE);
}
if (isset($error_text)) {
if ($mailbox['replies']) {
$params = array(
'body' => $origbody,
'error_messages' => $error_messages,
'error_text' => $error_text,
'from' => $fromaddress,
'header' => $header,
'node' => $node,
);
drupal_mail('mailhandler', 'mailhandler_error_node', $fromaddress, user_preferred_language($user), $params);
}
}
// return FALSE if the node was not successfully saved
return FALSE;
}
/**
* Accept a taxonomy term name and replace with a tid. this belongs in taxonomy.module.
*/
function mailhandler_term_map(&$term, $index = array(), $vid = FALSE) {
// provide case insensitive and trimmed map so as to maximize likelihood of successful mapping
if ($vid) {
$and = 'AND vid =' . db_escape_string($vid);
}
$term = db_result(db_query("SELECT tid FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name) {$and}", trim($term)));
}
function mailhandler_node_process_message_commands(&$node, $commands) {
foreach ($commands as $data) {
// TODO: allow for nested arrays in commands ... Possibly trim() values after explode().
// If needed, turn this command value into an array
if (substr($data[1], 0, 1) == '[' && substr($data[1], -1, 1) == ']') {
$data[1] = rtrim(ltrim($data[1], '['), ']');
//strip brackets
$data[1] = explode(",", $data[1]);
// allow for key value pairs
foreach ($data[1] as $key => $value) {
$data_tmp = explode(":", $value, 2);
if (isset($data_tmp[1])) {
// is it a key value pair?
// remove old, add as key value pair
unset($data[1][$key]);
$data_tmp[0] = trim($data_tmp[0]);
$data[1][$data_tmp[0]] = $data_tmp[1];
}
}
}
$data[0] = strtolower(str_replace(' ', '_', $data[0]));
// Taxonomy specific command handling.
if (($data[0] == 'taxonomy' || $data[0] == 'taxonomy') && module_exists('taxonomy')) {
$vocabs = taxonomy_get_vocabularies($node->type);
$node->taxonomy = array();
// if needed, map term names into IDs. this should move to taxonomy_mailhandler()
if ($data[0] == 'taxonomy' && !is_numeric($data[1][0])) {
array_walk($data[1], 'mailhandler_term_map');
// Only add term if node type can use that term's vocab
$term = taxonomy_get_term($data[1][0]);
if (array_key_exists($term->vid, $vocabs)) {
$node->taxonomy = array_merge($node->taxonomy, $data[1]);
}
unset($data[0]);
}
else {
if (substr($data[0], 0, 9) == 'taxonomy[' && substr($data[0], -1, 1) == ']') {
// make sure a valid vid is passed in:
$vid = substr($data[0], 9, -1);
$vocabulary = taxonomy_vocabulary_load($vid);
// if the vocabulary is not activated for that node type, unset $data[0], so the command will be ommited from $node
// TODO: add an error message
if (!in_array($node->type, $vocabulary->nodes)) {
unset($data[0]);
}
else {
if (!$vocabulary->tags) {
array_walk($data[1], 'mailhandler_term_map', $vid);
$node->taxonomy = array_merge($node->taxonomy, $data[1]);
unset($data[0]);
}
else {
if ($vocabulary->tags) {
// for freetagging vocabularies, we just pass the list of terms
$node->taxonomy['tags'][$vid] = implode(',', $data[1]);
unset($data[0]);
// unset, so it won't be included when populating the node object
}
}
}
}
}
}
if (!empty($data[0])) {
$node->{$data}[0] = $data[1];
}
}
}
/**
* Implementation of hook_mail().
*/
function mailhandler_mail($key, &$message, $params) {
$variables = array(
'!body' => $params['body'],
'!from' => $params['from'],
'!site_name' => variable_get('site_name', 'Drupal'),
'!subject' => $params['header']->subject,
'!type' => $params['node']->type,
);
$message['subject'] = t('Email submission to !site_name failed - !subject', $variables);
$message['body'][] = $params['error_text'];
foreach ($params['error_messages'] as $key => $error) {
$message['body'][$key] = decode_entities(strip_tags($error));
}
$message['body'][] = t("You sent:\n\nFrom: !from\nSubject: !subject\nBody:\n!body", $variables);
}
/**
* Implementation of hook_mailhandler_authenticate_info()
*/
function mailhandler_mailhandler_authenticate_info() {
$info = array(
'mailhandler_default' => array(
'title' => 'Mailhandler Default',
'description' => 'Checks whether the sender matches a valid user in the database',
'callback' => 'mailhandler_authenticate_default',
'module' => 'mailhandler',
'extension' => NULL,
// as in $type in module_load_include
'basename' => NULL,
),
);
if (module_exists('tokenauth')) {
$info += array(
'mailhandler_tokenauth' => array(
'title' => 'Mailhandler Tokenauth',
'description' => 'Authenticate messages based on users token from Tokenauth module',
'callback' => 'mailhandler_authenticate_tokenauth',
'module' => 'mailhandler',
'extension' => NULL,
'basename' => NULL,
),
);
}
return $info;
}
/**
* Authenticate message based on sender's email address
* If the sender's email address matches an email address of a valid user, then assign
* that user's uid and name to the node object.
*
* @param $node
* Object a node object
* @param $header
* Object of message header information
* @param $origbody
* String message body text
* @param $mailbox
* Array of mailbox configuration
*
* @return object, the node object
*/
function mailhandler_authenticate_default($node, $header, $origbody, $mailbox) {
list($fromaddress, $fromname) = mailhandler_get_fromaddress($header, $mailbox);
if ($from_user = mailhandler_user_load($fromaddress, $node->pass, $mailbox)) {
$node->uid = $from_user->uid;
$node->name = $from_user->name;
}
else {
if (function_exists('mailalias_user') && ($from_user = mailhandler_user_load_alias($fromaddress, $node, $mailbox))) {
$node->uid = $from_user->uid;
$node->name = $from_user->name;
}
else {
// Authentication failed. Try as anonymous.
$node->uid = 0;
$node->name = $fromname;
}
}
return $node;
}
/**
* Authenticate message based on token from tokenauth module
* If the user's token is found somewhere in the "to" field, assign that user's uid and name
* to the node object. A rough search for the token somewhere in the "toaddress" is performed
* instead of an exact, ordered match in order to allow some freedom in the format of allowed
* "toaddress". For example, if using a catchall email address, the toaddress could be:
*
* f93ksj35dx@example.com - where f93ksj35dx is the user's token
* or alternatively:
* f93ksj35dx-foo@example.com - where f93ksj35dx is the user's token and foo is the name of an
* Organic Group to which the message should be assigned.
*
* A rough search allows for different approaches to use this single authentication method.
*
* @param $node
* Object a node object
* @param $header
* Object of message header information
* @param $origbody
* String message body text
* @param $mailbox
* Array of mailbox configuration
*
* @return object, the node object
*/
function mailhandler_authenticate_tokenauth($node, $header, $origbody, $mailbox) {
if (module_exists('tokenauth')) {
list($fromaddress, $fromname) = mailhandler_get_fromaddress($header, $mailbox);
// If user with given email address exists and their token is in the toaddress, allow.
if (($from_user = mailhandler_user_load($fromaddress, $node->pass, $mailbox)) && strpos($header->to[0]->mailbox, tokenauth_get_token($from_user->uid)) !== FALSE) {
$node->uid = $from_user->uid;
$node->name = $from_user->name;
}
else {
if (function_exists('mailalias_user') && ($from_user = mailhandler_user_load_alias($fromaddress, $node, $mailbox)) && strpos($header->to[0]->mailbox, tokenauth_get_token($from_user->uid)) !== FALSE) {
$node->uid = $from_user->uid;
$node->name = $from_user->name;
}
else {
// If token authentication fails, try as anonymous.
$node->uid = 0;
$node->name = $fromname;
}
}
}
return $node;
}
/**
* Determine from address either using the mailbox setting or via the header information
*
* @param $header
* Object message header information
* @param $mailbox
* Array mailbox settings
* @return array
*/
function mailhandler_get_fromaddress($header, $mailbox) {
if (($fromheader = strtolower($mailbox['fromheader'])) && isset($header->{$fromheader})) {
$from = $header->{$fromheader};
}
else {
$from = $header->from;
}
return array(
$from[0]->mailbox . '@' . $from[0]->host,
isset($from[0]->personal) ? $from[0]->personal : '',
);
}
/**
* Retrieve user information from his email address.
*/
function mailhandler_user_load($mail, $pass, $mailbox) {
if ($mailbox['security'] == 1) {
if (!($account = user_load(array(
'mail' => $mail,
'pass' => $pass,
)))) {
mailhandler_watchdog_record('Wrong password used in message commands for %address', array(
'%address' => $mail,
), WATCHDOG_NOTICE);
}
return $account;
}
else {
return user_load(array(
'mail' => $mail,
));
}
}
/**
* Look up a user based on their mailalias addresses
*
* Helper function for mailhandler_authenticate_tokenauth()
*
* @param $fromaddress
* String from address
* @param $node
* Object node object
* @param $mailbox
* Array of mailhandler mailbox configuration
*
* @return Object user object or FALSE
*/
function mailhandler_user_load_alias($fromaddress, $node, $mailbox) {
$result = db_query("SELECT mail FROM {users} WHERE data LIKE '%%%s%%'", $fromaddress);
while ($alias = db_result($result)) {
if ($from_user = mailhandler_user_load($alias, $node->pass, $mailbox)) {
return $from_user;
break;
}
}
return FALSE;
}
/**
* @defgroup mailhandler_util Mailhandler general purpose functions
* @{
* The functions included here are helpers for the module operation.
*/
/**
* Switch from original user to desired uid for content authoring.
*
* Note: You first need to run mailhandler_switch_user without argument to store
* the current user. Call mailhandler_switch_user agin without argument to set
* the user back to the original user.
*
* @param $uid The user ID to switch to
*
*/
function mailhandler_user_switch($uid = NULL) {
global $user;
static $orig_user = array();
if (isset($uid)) {
session_save_session(FALSE);
$user = user_load(array(
'uid' => $uid,
));
}
else {
if (count($orig_user)) {
$user = array_shift($orig_user);
session_save_session(TRUE);
array_unshift($orig_user, $user);
}
else {
$orig_user[] = $user;
}
}
}
/**
* Log a Mailhandler message.
*
* This is a wrapper call to watchdog, to avoid selective events recording from
* the Mailhandler configuration. For debug messages, the caller function and
* line is shown in the 'Operations' column.
*
* @param $message
* The message to store in the log. See t() for documentation
* on how $message and $variables interact. Keep $message
* translatable by not concatenating dynamic values into it!
* @param $variables
* Array of variables to replace in the message on display or
* NULL if message is already translated or not possible to
* translate.
* @param $severity
* The severity of the message, as per RFC 3164. Possible values are
* WATCHDOG_ERROR, WATCHDOG_WARNING, etc.
* @param $link
* A link to associate with the message.
*
* @see watchdog_severity_levels()
* @see watchdog()
*/
function mailhandler_watchdog_record($message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) {
if ($severity <= variable_get('mailhandler_watchdog_level', WATCHDOG_INFO)) {
// Use 'Operations' column to show function and line of the message call.
// @todo: build a link to an updated contrib API site.
if (!$link) {
$caller = _mailhandler_get_last_caller(debug_backtrace());
$link = $caller['line'] . ' : ' . $caller['function'];
}
watchdog('mailhandler', $message, $variables, $severity, $link);
}
}
/**
* Return mailhandler mailbox default attributes.
*
* @return
* Associative array with mailhandler mailbox default attributes.
*/
function mailhandler_mailbox_defaults() {
return array(
'mail' => '',
'mailto' => '',
'folder' => 'INBOX',
'imap' => 0,
'domain' => '',
'port' => '',
'name' => '',
'pass' => '',
'extraimap' => '',
'mime' => 'TEXT/HTML,TEXT/PLAIN',
'security' => 0,
'replies' => 1,
'fromheader' => '',
'commands' => '',
'sigseparator' => '',
'delete_after_read' => 1,
'enabled' => 1,
'format' => variable_get('filter_default_format', 1),
'authentication' => 'mailhandler_default',
);
}
/**
* Return last caller of a backtrace. Used to trac calls to deprecated functions
* of this module.
*
* @param $backtrace
* @return
* string caller
*/
function _mailhandler_get_last_caller($backtrace) {
// Errors that occur inside PHP internal functions do not generate
// information about file and line. Ignore black listed functions.
$blacklist = array(
'debug',
);
while ($backtrace && !isset($backtrace[1]['line']) || isset($backtrace[2]['function']) && in_array($backtrace[2]['function'], $blacklist)) {
array_shift($backtrace);
}
// The first trace is the call itself.
// It gives us the line and the file of the last call.
$call = $backtrace[1];
// The second call give us the function where the call originated.
if (isset($backtrace[2])) {
if (isset($backtrace[2]['class'])) {
$call['function'] = $backtrace[2]['class'] . $backtrace[2]['type'] . $backtrace[1]['function'] . '()';
}
else {
$call['function'] = $backtrace[2]['function'] . '()';
}
}
else {
$call['function'] = 'main()';
}
return $call;
}
/**
* Record deprecated function usages using watchdog.
*
* Usefull to remove backward compatibility in a future.
*/
function mailhandler_watchdog_deprecated() {
// Record warning information about a deprecated function call, so we can
// track wich modules are still using it.
$caller = _mailhandler_get_last_caller(debug_backtrace());
$call = basename($caller['file']) . ':' . $caller['line'] . ' ' . $caller['function'];
mailhandler_watchdog_record('Deprecated call from: @call', array(
'@call' => $call,
), WATCHDOG_WARNING);
}
/**
* @} End of "defgroup mailhandler_util".
*/
/**
* @defgroup mailhandler_deprecated Mailhandler deprecated functions.
* @{
* Functions that can be removed, but are kept for backward compatibility.
* Modules using these functions can be tracked using warning watchdog entries.
*/
/**
* (DEPRECATED) Fetch data for a specific mailbox from the database.
*
* To be removed once it is not in use by other module. Currently this is just a
* wrapper around mailhandler_mailbox_load(). The only know usage for now is in
* mail_comment module.
*/
function mailhandler_get_mailbox($mid) {
mailhandler_watchdog_deprecated();
return mailhandler_mailbox_load($mid);
}
/**
* @} End of "defgroup mailhandler_deprecated".
*/
Functions
Name | Description |
---|---|
mailhandler_authenticate_default | Authenticate message based on sender's email address If the sender's email address matches an email address of a valid user, then assign that user's uid and name to the node object. |
mailhandler_authenticate_tokenauth | Authenticate message based on token from tokenauth module If the user's token is found somewhere in the "to" field, assign that user's uid and name to the node object. A rough search for the token somewhere in the… |
mailhandler_comment_submit | Create the comment. |
mailhandler_cron | Implementation of hook_cron(). |
mailhandler_default_type | Return a default content type if the user has not chosen a specific type on the settings page In order of priority, return blog, story, page This assumes that one of these basic types is in use on a site (page and story are active by default) A user… |
mailhandler_get_fromaddress | Determine from address either using the mailbox setting or via the header information |
mailhandler_get_mailbox | (DEPRECATED) Fetch data for a specific mailbox from the database. |
mailhandler_help | Implementation of hook_help(). |
mailhandler_mail | Implementation of hook_mail(). |
mailhandler_mailbox_defaults | Return mailhandler mailbox default attributes. |
mailhandler_mailbox_delete | Delete a Mailhandler Mailbox from the database. |
mailhandler_mailbox_load | Load a mailbox array from database. |
mailhandler_mailbox_load_multiple | Load mailboxes from the database. |
mailhandler_mailbox_save | Save a Mailhandler Mailbox in the database. |
mailhandler_mailbox_stream_close | Close stream connection. |
mailhandler_mailbox_stream_count | Get number of messages in the stream connection. |
mailhandler_mailbox_stream_delete | Delete a message in the stream connection. |
mailhandler_mailbox_stream_open | Establish stream connection to specified mailbox. |
mailhandler_mailbox_stream_retrieve | Return a message matching the requested conditions. |
mailhandler_mailbox_test | Test the connection to a mailbox. |
mailhandler_mailbox_validate | Validate a Mailhandler Mailbox. |
mailhandler_mailhandler_authenticate_info | Implementation of hook_mailhandler_authenticate_info() |
mailhandler_mailhandler_batch_results | Implementation of hook_mailhandler_batch_results() |
mailhandler_menu | Implementation of hook_menu(). |
mailhandler_node_prepare_message | Append default commands. Separate commands from body. Strip signature. Return a node object. |
mailhandler_node_process_mailbox | Run message retrieval and node processing on a mailbox - is a wrapper around mailhandler_retrieve |
mailhandler_node_process_message | |
mailhandler_node_process_message_commands | |
mailhandler_node_submit | Create the node. |
mailhandler_perm | Implementation of hook_perm(). |
mailhandler_term_map | Accept a taxonomy term name and replace with a tid. this belongs in taxonomy.module. |
mailhandler_user_load | Retrieve user information from his email address. |
mailhandler_user_load_alias | Look up a user based on their mailalias addresses |
mailhandler_user_switch | Switch from original user to desired uid for content authoring. |
mailhandler_watchdog_deprecated | Record deprecated function usages using watchdog. |
mailhandler_watchdog_record | Log a Mailhandler message. |
_mailhandler_get_last_caller | Return last caller of a backtrace. Used to trac calls to deprecated functions of this module. |