/[drupal]/contributions/modules/mailhandler/mailhandler.module
ViewVC logotype

Diff of /contributions/modules/mailhandler/mailhandler.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.87, Thu Feb 1 05:34:50 2007 UTC revision 1.87.2.10, Sun Jul 6 20:07:09 2008 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: mailhandler.module,v 1.86 2006/08/08 23:01:24 weitzman Exp $  // $Id: mailhandler.module,v 1.87.2.9 2008/05/02 17:32:18 weitzman Exp $
3    
4  /**  /**
5   * Retrieve all msgs from a given mailbox and process them.   * Retrieve all msgs from a given mailbox and process them.
# Line 33  function mailhandler_retrieve($mailbox) Line 33  function mailhandler_retrieve($mailbox)
33        }        }
34    
35        $mime = explode(',', variable_get('mime', 'TEXT/HTML,TEXT/PLAIN'));        $mime = explode(',', variable_get('mime', 'TEXT/HTML,TEXT/PLAIN'));
36    
37          // Get the first text part - this will be the node body
38        $origbody = mailhandler_get_part($result, $i, $mime[0]);        $origbody = mailhandler_get_part($result, $i, $mime[0]);
39    
40          // If we didn't get a body from our first attempt, try the alternate format (HTML or PLAIN)
41        if (!$origbody) {        if (!$origbody) {
42          $origbody = mailhandler_get_part($result, $i, $mime[1]);          $origbody = mailhandler_get_part($result, $i, $mime[1]);
43          if (!$origbody) {        }
44            // @TODO: Log that we got an empty email?  
45            continue;        // Parse MIME parts, so all mailhandler modules have access to
46          }        // the full array of mime parts without having to process the email.
47          $mimeparts = mailhandler_get_parts($result, $i);
48    
49          // Is this an empty message with no body and no mimeparts?
50          if (!$origbody && !$mimeparts) {
51            // @TODO: Log that we got an empty email?
52            continue;
53        }        }
54    
55        $num_processed++;        $num_processed++;
# Line 50  function mailhandler_retrieve($mailbox) Line 60  function mailhandler_retrieve($mailbox)
60        // check if mail originates from an authenticated user        // check if mail originates from an authenticated user
61        $node = mailhandler_authenticate($node, $header, $origbody, $mailbox);        $node = mailhandler_authenticate($node, $header, $origbody, $mailbox);
62    
63          // Put $mimeparts on the node
64          $node->mimeparts = $mimeparts;
65    
66        // we need to change the current user        // we need to change the current user
67        // this has to be done here to allow modules        // this has to be done here to allow modules
68        // to create users        // to create users
# Line 87  function mailhandler_retrieve($mailbox) Line 100  function mailhandler_retrieve($mailbox)
100    }    }
101    else {    else {
102      if ($err) {      if ($err) {
103        watchdog('error', t('Mailhandler %c connection failed: %m', array('%c' => ($mailbox['imap'] ? 'imap' : 'POP3'), '%m' => $mailbox['mail'])));        watchdog('mailhandler', t('Mailhandler %c connection failed: %m', array('%c' => ($mailbox['imap'] ? 'imap' : 'POP3'), '%m' => $mailbox['mail'])), WATCHDOG_ERROR);
104        return t('Mailhandler %c connection failed: %m', array('%c' => ($mailbox['imap'] ? 'imap' : 'POP3'), '%m' => $mailbox['mail']));        return t('Mailhandler %c connection failed: %m', array('%c' => ($mailbox['imap'] ? 'imap' : 'POP3'), '%m' => $mailbox['mail']));
105      }      }
106      else {      else {
107        watchdog('error', t('Mailhandler: Could not access local folder: %m', array('%m' => $mailbox['mail'])));        watchdog('mailhandler', t('Mailhandler: Could not access local folder: %m', array('%m' => $mailbox['mail'])), WATCHDOG_ERROR);
108        return t('Mailhandler could not access local folder: %m', array('%m' => $mailbox['mail']));        return t('Mailhandler could not access local folder: %m', array('%m' => $mailbox['mail']));
109      }      }
110    }    }
# Line 118  function mailhandler_comment_submit($nod Line 131  function mailhandler_comment_submit($nod
131      $headers = "From: $sitemail\nReply-to: $sitemail\nX-Mailer: Drupal\nReturn-path: $sitemail\nErrors-to: $sitemail";      $headers = "From: $sitemail\nReply-to: $sitemail\nX-Mailer: Drupal\nReturn-path: $sitemail\nErrors-to: $sitemail";
132      drupal_mail($fromaddress, t('Email submission to %sn failed - %subj', array('%sn' => variable_get('site_name', 'Drupal'), '%subj' => $header->subject)), $error, $headers);      drupal_mail($fromaddress, t('Email submission to %sn failed - %subj', array('%sn' => variable_get('site_name', 'Drupal'), '%subj' => $header->subject)), $error, $headers);
133      $watchdog = t('Mailhandler: comment submission failure: %subject.', array('%subject' => $edit['subject']));      $watchdog = t('Mailhandler: comment submission failure: %subject.', array('%subject' => $edit['subject']));
134      watchdog('error', $watchdog);      watchdog('mailhandler', $watchdog, WATCHDOG_ERROR);
135    }    }
136  }  }
137    
# Line 138  function mailhandler_node_submit($node, Line 151  function mailhandler_node_submit($node,
151    list($fromaddress, $fromname) = mailhandler_get_fromaddress($header, $mailbox);    list($fromaddress, $fromname) = mailhandler_get_fromaddress($header, $mailbox);
152    
153    //dprint_r($node); //DEBUG    //dprint_r($node); //DEBUG
154    
155      // Drupal 5.x & 6.x don't support multiple validations: each node_validate()
156      // call will ADD error messages to previous ones, so if some validation error
157      // occours in one message it will be reported in all messages after it.
158      // Since there is no way to reset form errors, the only method to avoid this
159      // problem is working with $_SESSION['messages'], used by form_set_error().
160      // See http://drupal.org/node/271975 for more info.
161      // Warning: with this method, if the same error message is reported for 2+ different
162      // fields it will be detected only for the last one.
163    
164      if (!isset($_SESSION['messages'])) {
165        $_SESSION['messages'] = array();
166      }
167      $saved_errors = is_array($_SESSION['messages']['error']) ? $_SESSION['messages']['error'] : array();
168      $_SESSION['messages']['error'] = array();
169    node_validate($node);    node_validate($node);
170    $error = form_get_errors();    $error = array();
171      if (count($_SESSION['messages']['error'])) {
172        $allerrors = form_get_errors();
173        foreach ($_SESSION['messages']['error'] as $message) {
174          $keys = array_keys($allerrors, $message);
175          if (!$keys || !count($keys)) {
176            // Not a validation error (but an error, i'll print it)
177            $saved_errors[] = $message;
178          } else {
179            // This is a validation error, i take the last field with it (previous fields
180            // should be about previous validations)
181            $error[$keys[count($keys) - 1]] = $message;
182          }
183        }
184      }
185      $_SESSION['messages']['error'] = $saved_errors;
186    
187    if (!$error) {    if (!$error) {
188      // Prepare the node for save and allow modules make changes      // Prepare the node for save and allow modules make changes
189      $node = node_submit($node);      $node = node_submit($node);
# Line 148  function mailhandler_node_submit($node, Line 191  function mailhandler_node_submit($node,
191      if ($node->nid) {      if ($node->nid) {
192        if (node_access('update', $node)) {        if (node_access('update', $node)) {
193          node_save($node);          node_save($node);
194          watchdog('special', t("Mailhandler: Updated '%t' by %f", array('%t' => $node->title, '%f' => $fromaddress)));          watchdog('mailhandler', t("Mailhandler: Updated '%t' by %f", array('%t' => $node->title, '%f' => $fromaddress)), WATCHDOG_NOTICE);
195        }        }
196        else {        else {
197          $errortxt = t("The e-mail address '%f' may not update %t items.", array('%f' => $fromaddress, '%t' => $node->type));          $errortxt = t("The e-mail address '%f' may not update %t items.", array('%f' => $fromaddress, '%t' => $node->type));
# Line 157  function mailhandler_node_submit($node, Line 200  function mailhandler_node_submit($node,
200      else {      else {
201        if (node_access('create', $node)) {        if (node_access('create', $node)) {
202          node_save($node);          node_save($node);
203          watchdog('special', t("Mailhandler: Added '%t' by %f", array('%t' => $node->title, '%f' => $fromaddress)));          watchdog('mailhandler', t("Mailhandler: Added '%t' by %f", array('%t' => $node->title, '%f' => $fromaddress)), WATCHDOG_NOTICE);
204        }        }
205        else {        else {
206          $errortxt = t("The e-mail address '%f' may not create %t items.", array('%f' => $fromaddress, '%t' => $node->type));          $errortxt = t("The e-mail address '%f' may not create %t items.", array('%f' => $fromaddress, '%t' => $node->type));
# Line 172  function mailhandler_node_submit($node, Line 215  function mailhandler_node_submit($node,
215    }    }
216    
217    if ($errortxt) {    if ($errortxt) {
218      watchdog('error', "Mailhandler: $errortxt");      watchdog('mailhandler', "Mailhandler: $errortxt", WATCHDOG_ERROR);
219      if ($mailbox['replies']) {      if ($mailbox['replies']) {
220        $errortxt .= t("\n\nYou sent:\n\nFrom: %f\nSubject: %t\nBody:\n%b", array('%f' => $fromaddress, '%t' => $header->subject, '%b' => $origbody));        $errortxt .= t("\n\nYou sent:\n\nFrom: %f\nSubject: %t\nBody:\n%b", array('%f' => $fromaddress, '%t' => $header->subject, '%b' => $origbody));
221        $sitemail = variable_get('site_mail', ini_get('sendmail_from'));        $sitemail = variable_get('site_mail', ini_get('sendmail_from'));
# Line 237  function mailhandler_process_message($he Line 280  function mailhandler_process_message($he
280        if ($data[0] == 'taxonomy' && !is_numeric($data[1][0])) {        if ($data[0] == 'taxonomy' && !is_numeric($data[1][0])) {
281          array_walk($data[1], 'mailhandler_term_map');          array_walk($data[1], 'mailhandler_term_map');
282        }        }
283        $node->$data[0] = $data[1];        if (!empty($data[0])) {
284            $node->$data[0] = $data[1];
285          }
286      }      }
287      else {      else {
288        if (is_null($endcommands)) $endcommands = $i;        if (is_null($endcommands)) $endcommands = $i;
# Line 325  function mailhandler_switch_user($uid = Line 370  function mailhandler_switch_user($uid =
370    static $orig_user = array();    static $orig_user = array();
371    
372    if (isset($uid)) {    if (isset($uid)) {
373        session_save_session(FALSE);
374      $user = user_load(array('uid' => $uid));      $user = user_load(array('uid' => $uid));
375    }    }
376    // retrieve the initial user, can be called multiple times    // retrieve the initial user, can be called multiple times
377    else if (count($orig_user)) {    else if (count($orig_user)) {
378      $user = array_shift($orig_user);      $user = array_shift($orig_user);
379        session_save_session(TRUE);
380      array_unshift($orig_user, $user);      array_unshift($orig_user, $user);
381    }    }
382    // store the initial user    // store the initial user
# Line 387  function mailhandler_get_part($stream, $ Line 434  function mailhandler_get_part($stream, $
434          $part_number = '1';          $part_number = '1';
435        }        }
436        $text = imap_fetchbody($stream, $msg_number, $part_number);        $text = imap_fetchbody($stream, $msg_number, $part_number);
437        if ($structure->encoding == 3) {        if ($structure->encoding == ENCBASE64) {
438          return drupal_convert_to_utf8(imap_base64($text), $encoding);          return drupal_convert_to_utf8(imap_base64($text), $encoding);
439        }        }
440        else if ($structure->encoding == 4) {        else if ($structure->encoding == ENCQUOTEDPRINTABLE) {
441          return drupal_convert_to_utf8(quoted_printable_decode($text), $encoding);          return drupal_convert_to_utf8(quoted_printable_decode($text), $encoding);
442        }        }
443        else {        else {
444          return drupal_convert_to_utf8($text, $encoding);          return drupal_convert_to_utf8($text, $encoding);
445        }        }
446      }      }
447      if ($structure->type == 1) { /* multipart */      if ($structure->type == TYPEMULTIPART) { /* multipart */
448        while (list($index, $sub_structure) = each ($structure->parts)) {        while (list($index, $sub_structure) = each ($structure->parts)) {
449          if ($part_number) {          if ($part_number) {
450            $prefix = $part_number .'.';            $prefix = $part_number .'.';
# Line 413  function mailhandler_get_part($stream, $ Line 460  function mailhandler_get_part($stream, $
460    return false;    return false;
461  }  }
462    
463    
464    /**
465     * Returns an array of parts as file objects
466     *
467     * @param
468     * @param $structure
469     *   A message structure, usually used to recurse into specific parts
470     * @param $max_depth
471     *   Maximum Depth to recurse into parts.
472     * @param $depth
473     *   The current recursion depth.
474     * @param $part_number
475     *   A message part number to track position in a message during recursion.
476     * @return
477     *   An array of file objects.
478     */
479    function mailhandler_get_parts($stream, $msg_number, $max_depth = 10, $depth = 0, $structure = FALSE, $part_number = FALSE) {
480      $parts = array();
481    
482      // Load Structure.
483      if (!$structure && !$structure = imap_fetchstructure($stream, $msg_number)) {
484        watchdog('mailhandler', t('Could not fetch structure for message number %msg_number', array('%msg_number' => $msg_number)), WATCHDOG_NOTICE);
485        return $parts;
486      }
487    
488      // Recurse into multipart messages.
489      if ($structure->type == TYPEMULTIPART) {
490        // Restrict recursion depth.
491        if ($depth >= $max_depth) {
492          watchdog('mailhandler', t('Maximum recursion depths met in mailhander_get_structure_part for
493                      message number %msg_number.',  array('%msg_number' => $msg_number)), WATCHDOG_NOTICE);
494          return $parts;
495        }
496        foreach($structure->parts as $index => $sub_structure) {
497          // If a part number was passed in and we are a multitype message, prefix the
498          // the part number for the recursive call to match the imap4 dot seperated part indexing.
499          if ($part_number) {
500            $prefix = $part_number .'.';
501          }
502          $sub_parts =  mailhandler_get_parts($stream, $msg_number, $max_depth, $depth + 1,
503            $sub_structure, $prefix . ($index + 1));
504          $parts = array_merge($parts, $sub_parts);
505        }
506        return $parts;
507      }
508    
509      // Per Part Parsing.
510    
511      // Initalize file object like part structure.
512      $part = new StdClass();
513      $part->attributes = array();
514      $part->filename = 'unnamed_attachment';
515      if (!$part->filemime = mailhandler_get_mime_type($structure)) {
516        watchdog('mailhandler', t('Could not fetch mime type for message part. Defaulting to application/octet-stream.'),
517          WATCHDOG_NOTICE);
518        $part->filemime = 'application/octet-stream';
519      }
520    
521      if ($structure->ifparameters) {
522        foreach ($structure->parameters as $parameter) {
523          switch (strtoupper($parameter->attribute)) {
524            case 'NAME':
525            case 'FILENAME':
526              $part->filename = $parameter->value;
527              break;
528            default:
529              // put every thing else in the attributes array;
530              $part->attributes[$parameter->attribute] = $parameter->value;
531          }
532        }
533      }
534    
535      // Handle Content-Disposition parameters for non-text types.
536      if ($structure->type != TYPETEXT && $structure->ifdparameters) {
537        foreach ($structure->dparameters as $parameter) {
538          switch (strtoupper($parameter->attribute)) {
539            case 'NAME':
540            case 'FILENAME':
541              $part->filename = $parameter->value;
542              break;
543            // put every thing else in the attributes array;
544            default:
545              $part->attributes[$parameter->attribute] = $parameter->value;
546          }
547        }
548      }
549    
550      // Retrieve part  convert MIME encoding to UTF-8
551      if(!$part->data = imap_fetchbody($stream, $msg_number, $part_number)) {
552        drupal_set_message("imap_fetchbody($stream, $msg_number, $part_number)");
553        watchdog('mailhandler', 'No Data!!', WATCHDOG_ERROR);
554        return $parts;
555      }
556    
557      // convert text attachment to UTF-8.
558      if ($structure->type == TYPETEXT) {
559        $part->data = imap_utf8($part->data);
560      }
561      else {
562        // If not text then decode as necessary
563        if ($structure->encoding == ENCBASE64) {
564          $part->data = imap_base64($part->data);
565        }
566        else if ($structure->encoding == ENCQUOTEDPRINTABLE) {
567          $part->data = quoted_printable_decode($part->data);
568        }
569      }
570    
571      //always return an array to satisfy array_merge in recursion catch, and array return value.
572      $parts[] = $part;
573      return $parts;
574    }
575    
576  /**  /**
577   * Retrieve MIME type of the message structure.   * Retrieve MIME type of the message structure.
578   */   */
# Line 427  function mailhandler_get_mime_type(&$str Line 587  function mailhandler_get_mime_type(&$str
587    
588  /**  /**
589   * Implementation of hook_user().   * Implementation of hook_user().
590   */   *
591     * Commented out because mailhandler cannot assume that this mailbox will
592     * accept blog entries from users.
593    */
594    /*
595  function mailhandler_user($type, &$edit, &$account, $category = NULL) {  function mailhandler_user($type, &$edit, &$account, $category = NULL) {
596    if ($type == 'view') {    if ($type == 'view') {
597      // @TODO: We may add a new option in mailboxes to choose which roles can post.      // @TODO: We may add a new option in mailboxes to choose which roles can post.
# Line 452  function mailhandler_user($type, &$edit, Line 616  function mailhandler_user($type, &$edit,
616      }      }
617    }    }
618  }  }
619    */
620    
621  /**  /**
622   * Implementation of hook_cron(). Process msgs from all enabled mailboxes.   * Implementation of hook_cron(). Process msgs from all enabled mailboxes.
# Line 484  function mailhandler_menu($may_cache) { Line 649  function mailhandler_menu($may_cache) {
649    if ($may_cache) {    if ($may_cache) {
650      $items[] = array('path' => 'admin/content/mailhandler', 'title' => t('Mailhandler'),      $items[] = array('path' => 'admin/content/mailhandler', 'title' => t('Mailhandler'),
651        'callback' => 'mailhandler_admin',        'callback' => 'mailhandler_admin',
652          'description' => t('Manage mailboxes and retrieve messages.'),
653        'access' => $admin_access);        'access' => $admin_access);
654      $items[] = array('path' => 'admin/content/mailhandler/retrieve', 'title' => t('Retrieve'),      $items[] = array('path' => 'admin/content/mailhandler/retrieve', 'title' => t('Retrieve'),
655        'callback' => 'mailhandler_admin_retrieve',        'callback' => 'mailhandler_admin_retrieve',
# Line 590  function mailhandler_form($edit = array( Line 756  function mailhandler_form($edit = array(
756    $form['mailto'] = array('#type' => 'textfield', '#title' => t('Second E-mail address'), '#default_value' => $edit['mailto'], '#description' => t('Optional. The e-mail address to which modules should send generated content.'));    $form['mailto'] = array('#type' => 'textfield', '#title' => t('Second E-mail address'), '#default_value' => $edit['mailto'], '#description' => t('Optional. The e-mail address to which modules should send generated content.'));
757    $form['folder'] = array('#type' => 'textfield', '#title' => t('Folder'), '#default_value' => $edit['folder'], '#description' => t('Optional. The folder where the mail is stored. If you want this mailbox to read from a local folder, give the full path. Leave domain, port, name, and pass empty below. Remember to set the folder to readable and writable by the webserver.'));    $form['folder'] = array('#type' => 'textfield', '#title' => t('Folder'), '#default_value' => $edit['folder'], '#description' => t('Optional. The folder where the mail is stored. If you want this mailbox to read from a local folder, give the full path. Leave domain, port, name, and pass empty below. Remember to set the folder to readable and writable by the webserver.'));
758    $form['imap'] = array('#type' => 'select', '#title' => t('POP3 or IMAP Mailbox'), '#options' => array('POP3', 'IMAP'), '#default_value' => $edit['imap'], '#description' => t('If you wish to retrieve mail from a POP3 or IMAP mailbox instead of a Folder, select POP3 or IMAP. Also, complete the Mailbox items below.'));    $form['imap'] = array('#type' => 'select', '#title' => t('POP3 or IMAP Mailbox'), '#options' => array('POP3', 'IMAP'), '#default_value' => $edit['imap'], '#description' => t('If you wish to retrieve mail from a POP3 or IMAP mailbox instead of a Folder, select POP3 or IMAP. Also, complete the Mailbox items below.'));
759    $form['domain'] = array('#type' => 'textfield', '#title' => t('Mailbox domain'), '#default_value' => $edit['domain'], '#description' => t('The domain of the server used to collect mail.'), '#required' => TRUE);    $form['domain'] = array('#type' => 'textfield', '#title' => t('Mailbox domain'), '#default_value' => $edit['domain'], '#description' => t('The domain of the server used to collect mail.'));
760    $form['port'] = array('#type' => 'textfield', '#title' => t('Mailbox port'), '#size' => 5, '#maxlength' => 5, '#default_value' => $edit['port'], '#description' => t('The port of the mailbox used to collect mail (usually 110 for POP3, 143 for IMAP).'));    $form['port'] = array('#type' => 'textfield', '#title' => t('Mailbox port'), '#size' => 5, '#maxlength' => 5, '#default_value' => $edit['port'], '#description' => t('The port of the mailbox used to collect mail (usually 110 for POP3, 143 for IMAP).'));
761    $form['name'] = array('#type' => 'textfield', '#title' => t('Mailbox username'), '#default_value' => $edit['name'], '#description' => t('This username is used while logging into this mailbox during mail retrieval.'));    $form['name'] = array('#type' => 'textfield', '#title' => t('Mailbox username'), '#default_value' => $edit['name'], '#description' => t('This username is used while logging into this mailbox during mail retrieval.'));
762    $form['pass'] = array('#type' => 'textfield', '#title' => t('Mailbox password'), '#default_value' => $edit['pass'], '#description' => t('The password corresponding to the username above. Consider using a non-vital password, since this field is stored without encryption in the database.'));    $form['pass'] = array('#type' => 'textfield', '#title' => t('Mailbox password'), '#default_value' => $edit['pass'], '#description' => t('The password corresponding to the username above. Consider using a non-vital password, since this field is stored without encryption in the database.'));
# Line 681  function mailhandler_admin_delete_confir Line 847  function mailhandler_admin_delete_confir
847  function mailhandler_admin_delete_confirm_submit($form_id, $form_values) {  function mailhandler_admin_delete_confirm_submit($form_id, $form_values) {
848    $info = db_fetch_object(db_query("SELECT mid, mail FROM {mailhandler} WHERE mid = %d", $form_values['mid']));    $info = db_fetch_object(db_query("SELECT mid, mail FROM {mailhandler} WHERE mid = %d", $form_values['mid']));
849    db_query("DELETE FROM {mailhandler} WHERE mid = %d", $form_values['mid']);    db_query("DELETE FROM {mailhandler} WHERE mid = %d", $form_values['mid']);
850    watchdog('special', t('Mailhandler: Mailbox %mailbox deleted', array('%mailbox' => $info->mail)));    watchdog('mailhandler', t('Mailhandler: Mailbox %mailbox deleted', array('%mailbox' => $info->mail)), WATCHDOG_NOTICE);
851    drupal_set_message(t('Mailbox %mailbox deleted', array('%mailbox' => $info->mail)));    drupal_set_message(t('Mailbox %mailbox deleted', array('%mailbox' => $info->mail)));
852    drupal_goto('admin/content/mailhandler');    drupal_goto('admin/content/mailhandler');
853  }  }

Legend:
Removed from v.1.87  
changed lines
  Added in v.1.87.2.10

  ViewVC Help
Powered by ViewVC 1.1.2