svn.filsa.org wordpress_dev

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
/*



*/


/** Make sure that the WordPress bootstrap has run before continuing. */
require(dirname(__FILE__) . '/../../../wp-load.php');

/** Get the POP3 class with which to access the mailbox. */
require_once( ABSPATH . WPINC . '/class-pop3.php' );
/** Include mimeparser lib from Manuel Lemos. */
require_once('lib/rfc822_addresses.php');
require_once('lib/mime_parser.php');


class mail2wp {

       
        var $run_id; // unique path
        var $image_id = 1;
        var $upload_dir;
        var $blog_gmt_offset;
       
        /**
        * Process one mail message, and execute the post-by-mail.
        * - handle attachments correctly.
        - parse with mime_parser.
        - get headers.
        - process body (including attachments)
          - move attachments to upload folder
          - concatenate body text and insert <img? tags to attachment files
        - create new post
        - delete message
        @param $msg_text - full text of the rfc822 message
        @param $result - array that will be returned as the result
        @return True if successful, False if not.
        */

        function process_message($msg_text, $result) {
                //$this->log("process_message: start.");

                $parser = new mime_parser_class;
                $parseparams = array ('Data'=>$msg_text);
                //$parseparams['SaveBody'] = 'temp/';
                //$parseparams['SkipBody'] = '1';
                //var_dump($parseparams);
                $result['status'] = 'INCOMPLETE';
               
                if(!$parser->Decode($parseparams, $decoded)) {
                        $result['error'] =  'MIME message decoding error: '.$mime->error.' at position '.$mime->error_position. 'Aborting this message.' . "\n";
                        $this->log($result['error'], 'ERR');
                return False;
                }
                $msgparse = $decoded[0];

                if(!$parser->Analyze($msgparse, $analyzed)) {
                        $result['error'] =  'MIME message analyzing error: '.$mime->error.' at position '.$mime->error_position. 'Aborting this message.' . "\n";
                        $this->log($result['error'], 'ERR');
                        return False;
                }
                $this->log(' - Parsing data from message titled: ' . $analyzed['Subject']);
                //var_dump($analyzed);
                //get headers
                // 'post_content','post_title','post_date','post_date_gmt','post_author','post_category', 'post_status'
                $post_author   = $this->_get_post_author($msgparse);
                $post_category = array(get_option('default_email_category'));
                $post_date     = $this->_parse_rfc822date($analyzed['Date']);
                $post_date_gmt = $this->_parse_rfc822date($analyzed['Date'], True);
                //$post_title    = $this->_decode_text($msgparse['Headers']['subject:']); // using decoded
                $post_title = $this->_decode_text($analyzed['Subject']);
                $post_status   = 'pending';
               
                if (empty($post_author)) {
                        $post_author=1; // dumb but easy assumption that user 1, admin, will always exist.                     
                } else {
                        $user = new WP_User($post_author);
                        $post_status = ( $user->has_cap('publish_posts') ) ? 'publish' : 'pending';
                }
                // process body
                $post_content = $this->process_analyzed_body($analyzed); // process via analyzed
                $post_content = apply_filters('phone_content', $post_content);// WP filter hook
               

               
                if (function_exists('mb_convert_encoding') &&
                        $analyzed['Encoding'] == 'iso-2022-jp') {
                        $this->log(' ! Detected iso-2022-jp encoding. Making adjustments.');
                        $post_title = mb_convert_encoding($post_title, "UTF-8", "ISO-2022-JP");
                        $post_content = mb_convert_encoding($post_content, "UTF-8", "ISO-2022-JP");
                }
               
               
                // prep post
                $post_data = compact('post_content','post_title','post_date','post_date_gmt','post_author','post_category', 'post_status');
                $post_data = add_magic_quotes($post_data);
                // send post to WP
                $post_ID = wp_insert_post($post_data);
                if ( is_wp_error( $post_ID ) ) {
                        $this->log(' WP Post failed. '. $post_ID->get_error_message(), 'ERR');
                        return False;
                        }
                // We couldn't post, for whatever reason. Better move forward to the next email.
                if ( empty( $post_ID ) )
                        return False;

                do_action('publish_phone', $post_ID); // WP hook
                $this->log(" * Posted title: $post_title, Author id: $post_author, status: $post_status.");
                //var_dump($post_data);
                //echo 'POST_CONTENT:<br/>' . $post_content . '<br />';
                return True;
               
        }
       
        /**
        Returns a string containing the body of a mail message.
        The body is modified based on the attachments or related fileparts that are included with the message.
        @param $mail is an array returned from the $mime_parser_class->Analyze() function.
        */

        function process_analyzed_body($mail) {
                $result = '';
                if ($mail['Type'] == 'text') $result = $this->_decode_text($mail['Data']);

                //handle Type=html and Related
                if ($mail['Type'] == 'html') {
                        $this->log (' - HTML message type.');
                        $result = $this->_decode_text($mail['Data']);
                        if (!empty($mail['Related'])) {
                        $this->log(' - Processing related items.');                                    
                                foreach ($mail['Related'] as $attachment) {
                                        if (! 'image' == $attachment['Type']) continue; //skip non-images for now
                                        $fname = $this->_get_safe_filename($attachment['FileName'], $attachment['SubType']);
                                        if ($this->_save_file($fname, $attachment['Data'])) {
                                                $urlpath = $this->upload_dir['url'] . '/' . $fname;
                                                $cid = 'cid:' . $attachment['ContentID'];
                                                $result = str_replace($cid, $urlpath, $result);
                                        }
                                }
                        }
                }
               
                // handle attachments
                if (!empty($mail['Attachments'])) {
                        $this->log(' - Processing attachments.');
                        $result .= "\n<div class='attachments'>\n";
                        foreach ($mail['Attachments'] as $attachment) {
                                if (! 'image' == $attachment['Type']) continue; //skip non-images for now
                                $fname = $this->_get_safe_filename($attachment['FileName'], $attachment['SubType']);
                                if ($this->_save_file($fname, $attachment['Data'])) {
                                        $urlpath = $this->upload_dir['url'] . '/' . $fname;
                                        $result .= '<img src="' . $urlpath .'" class="photomail attachments"/>'. "\n";
                                }
                        }
                        $result .= "\n</div>\n";

                }
                return $result;
        }
       
        /**
        Returns a string, that represents a safe filename.
        - safe filename is not encoded in a weird way
        - safe filename is unique and is not a
        */

        function _get_safe_filename($f, $subtype){
                $fext = array('jpeg'=>'.jpg', 'gif'=>'.gif', 'png'=>'.png');
                // fix encoded filenames - just generate a safe name.
                if ($f != $this->_decode_text($f)) {   
                        $f = $this->run_id . '-' . $this->image_id++ . $fext[$subtype];
                        $f = $this->_decode_text($f);
                }
                $f = str_replace(' ', '_', $f); // change spaces to underscores.
                $filechar = 65;
                $fpath = $this->upload_dir['path'] . '/' . $f;
                // makes sure file doesnt already exist.
                while (file_exists($fpath)) {
                        $fparts = explode('.', $f);
                        $f = $fparts[0];
                        if (substr($f, -2, 1) == '-') {
                                $f = substr($f, 0, strlen($f)-2);
                        }
                        $f = $f . '-' . chr($filechar++) . '.' . $fparts[1];
                        $fpath = $this->upload_dir['path'] . '/' . $f; 
                }
               
                return $f;
        }
        /*
       
        */

        function _save_file($fname, $data) {
                $result = true;
                $fpath = $this->upload_dir['path'] . '/' . $fname;
               
                if ($fh = fopen($fpath, 'w')) {
                        fwrite($fh, $data);
                        $this->log(' - File saved: ' . $fpath);
                } else {
                        $this->log("Attachment not written: $fname.", 'ERR' );
                        $result = false;
                }
                fclose($fh);
               
                return $result;
        }
       
        /**
        Easy logging
        */

        function log($s, $level='INFO') {
                $t = date('Y-m-d H:i:s');
                echo "$t [$level] $s" . "<br/>\n";
        }
        /**
        * Loop through messages on pop3 server.
        * @param $msg_count - # of message on the server.
        * @param $pop3 - variable that holds reference to an active POP3 instance.
        */

        function process_messages($msg_count, $pop3) {
                $this->startup();
                // loop through messages
                // if message process is True, then delete from pop3.
                for ( $i = 1; $i <= $msg_count; $i++ ) {
                        // get message
                        $this->log("Processing message #$i.");

                        $message = $pop3->get($i);
                        $msg_text = implode ('',  $message); // convert message array to string
                        // process message
                        $msg_status = $this->process_message($msg_text, $msg_result);
                        // delete message if message process was successful.
                        if ($msg_status) {
                                $this->log ("Message #$i OK. Attempting POP3 server delete...");

                                if(!$pop3->delete($i)) {
                                        $this->log( 'Message delete failure: ' . wp_specialchars($pop3->ERROR), 'ERR');
                                        $pop3->reset();
                                        exit;
                                } else {
                                        $this->log ("Message <strong>$i</strong> deleted.");
                                }      
                        } else {
                                $this->log ("process message $i failed: " . $result['error'], "ERR");
                        }
               
                }
                //$pop3->quit();
                $this->shutdown();

        }
        function startup() {           
                $this->run_id = dechex(time());
                $this->upload_dir = wp_upload_dir(date('Y/m'));
                $this->blog_gmt_offset = absint(get_option('gmt_offset')) * 3600;
        }
       
        function shutdown() {
        }
       

        /*-- PRIVATE FUNCTIONS --*/
        /**
        Converts a rfc822date to a php and db friendly format.
        From - Thu, 1 Jan 2009 23:33:40 +0900
        To - 2009-01-01 22:33:40
       
        @param dataheader - string that reflects rfc822date
        @param gmt - returns a GMT date. default is false.
        */

        function _parse_rfc822date($dateheader, $gmt=False) {
                $dmonths = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
               
                $ddate = trim($dateheader);
                if (strpos($ddate, ',')) {
                        $ddate = trim(substr($ddate, strpos($ddate, ',') + 1, strlen($ddate)));
                }
                $date_arr = explode(' ', $ddate);
                $date_time = explode(':', $date_arr[3]);

                $ddate_H = $date_time[0];
                $ddate_i = $date_time[1];
                $ddate_s = $date_time[2];

                $ddate_m = $date_arr[1];
                $ddate_d = $date_arr[0];
                $ddate_Y = $date_arr[2];
                for ( $j = 0; $j < 12; $j++ ) {
                        if ( $ddate_m == $dmonths[$j] ) {
                                $ddate_m = $j+1;
                        }
                }

                $time_zn = intval($date_arr[4]) * 36;
                $ddate_U = gmmktime($ddate_H, $ddate_i, $ddate_s, $ddate_m, $ddate_d, $ddate_Y);
                if ($gmt) {$ddate_U = $ddate_U - $time_zn;}
                return gmdate('Y-m-d H:i:s', $ddate_U); //post_date_gmt
        }
        function _rfc822date($dateheader, $gmt=False) {
                $epoch_secs = strtotime(trim($dateheader));
               
        }
        /**
        Converts subject text to match blog settings using iconv
        */
     
        function _decode_text($text) {
                // Captures any text in the subject before $phone_delim as the subject
                if ( function_exists('iconv_mime_decode') ) {
                        $result = iconv_mime_decode($text, 2, get_option('blog_charset'));
                } else {
                        $result = wp_iso_descrambler($text);
                }
                return $result;
        }
        /**
        * Collects email addresses from mail headers, then attempts to identify a WP author with that email address.
        */

        function _get_post_author($msgparse) {
                //Find $post_author based on from: (and reply-to)headers, set $author_found
                $authors = array();
                $result = NULL;
                $addr_fields = array('from:','reply-to:','return-path:');

                foreach ($addr_fields as $field){ // collect emails
                        if (! empty($msgparse['ExtractedAddresses'][$field])) {
                        foreach ($msgparse['ExtractedAddresses'][$field] as $email) {
                                $authors[] = $email['address'];
                                }
                        }
                }
                foreach ($authors as $author) { // find authors based on email
                        if ( is_email($author) ) {
                                $userdata = get_user_by_email($author);
                                if ( ! empty($userdata) ) {
                                        $result = $userdata->ID;
                                        break;
                                }
                        }
                }
                return $result;
        }
}


function do_photomail() {
        // fetch mail via POP3
        $mail_server = new POP3();
        $photomail = new mail2wp();

        if ( ! $mail_server->connect(get_option('mailserver_url'), get_option('mailserver_port') ) ||
                ! $mail_server->user(get_option('mailserver_login')) ||
                ( ! $msg_count = $mail_server->pass(get_option('mailserver_pass')) ) ) {
                        $mail_server->quit();
                        wp_die( ( 0 === $msg_count ) ? __("There doesn't seem to be any new mail.") : wp_specialchars($mail_server->ERROR) );
        }
        // loop through mail.
       
        $photomail->log("Connected to POP3 server: There are $msg_count message(s).");
        $photomail->process_messages($msg_count, $mail_server);
}

do_photomail();



?>