e107inc/e107

View on GitHub
e107_handlers/pop_bounce_handler.php

Summary

Maintainability
A
0 mins
Test Coverage
F
0%
<?php
/*
 * e107 website system
 *
 * Copyright (C) 2008-2009 e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 *
 * Bounce handler for cron or manual triggering
 *
 * $Source: /cvs_backup/e107_0.8/e107_handlers/pop_bounce_handler.php,v $
 * $Revision$
 * $Date$
 * $Author$
*/

/*
This handler is intended for use with a cron job, or with manual triggering, to get bounce notifications from a POP3 or IMAP account.
It extends the receiveMail class (pop3_class.php) to provide some higher level methods.
Can be used for getting mail from any POP3 mail account.

Some parts used from/based on the receiveMail class, by Mitul Koradia (Email: mitulkoradia@gmail.com, Cell : +91 9879697592)

Notes:
1. Requires that the IMAP extension is installed
2. Mailbox names that contain international characters besides those in the printable ASCII space have to be encoded width imap_utf7_encode(). 
*/


/**
 *
 */
class pop3BounceHandler
{
    protected    $e107;

    protected $server='';                // String to connect to server
    protected $username='';
    protected $password='';

    protected $email='';                // Email address receiving bounces
    protected $delBounce = FALSE;        // TRUE to delete emails after reading

    protected $mailResource = '';        // Resource identifier for IMAP
    
    protected $mailManager = FALSE;


    /**
     * @param $override
     */
    public function __construct($override = FALSE)
    {
        global $pref;
        $this->e107 = e107::getInstance();
        if (($override === FALSE) || !is_array($override))
        {    // Set up from prefs
            $override['mail_bounce_user'] = $pref['mail_bounce_user'];
            $override['mail_bounce_pass'] = $pref['mail_bounce_pass'];
            $override['mail_bounce_email'] = $pref['mail_bounce_email'];
            $override['mail_bounce_pop3'] = $pref['mail_bounce_pop3'];
            $override['mail_bounce_type'] = varset($pref['mail_bounce_type'],'pop3');
        }

        if($override['mail_bounce_type']=='imap')
        {
            $port = varset($override['mail_bounce_port'], '143');
            $strConnect='{'.$override['mail_bounce_pop3'].':'.$port. '}INBOX';
        }
        else
        {
            $port = varset($override['mail_bounce_port'], '110');        // POP3 port
            $servertype = '/'.varset($override['mail_bounce_type'], 'pop3');
            $strConnect='{'.$override['mail_bounce_pop3'].':'.$port. $servertype.'}INBOX';
        }
        $this->server            =    $strConnect;
        $this->username            =    $override['mail_bounce_user'];
        $this->password            =    $override['mail_bounce_pass'];
        $this->email            =    $override['mail_bounce_email'];

        $this->delBounce = ($pref['mail_bounce_delete']) ? true : false;
    }


    /**
     * @return void
     */
    function connect() //Connect To the Mail Box
    {
        $this->mailResource=imap_open($this->server,$this->username,$this->password);
    }


    /**
     * @return int
     */
    function getTotalMails() //Get Total Number off Unread Email In Mailbox
    {
        $headers=imap_headers($this->mailResource);
        return count($headers);
    }


    /**
     * @param $mid
     * @return array
     */
    function getHeaders($mid) // Get Header info
    {
        $mail_header=imap_header($this->mailResource,$mid);
        $sender=$mail_header->from[0];
        $sender_replyto=$mail_header->reply_to[0];
        $stat = !(strtolower($sender->mailbox) != 'mailer-daemon' && strtolower($sender->mailbox) != 'postmaster');
        if(strpos($mail_header->subject,"delayed"))
        {
            $stat = FALSE;
        }
            $mail_details=array(
                    'from'=>strtolower($sender->mailbox).'@'.$sender->host,
                    'fromName'=>$sender->personal,
                    'toOth'=>strtolower($sender_replyto->mailbox).'@'.$sender_replyto->host,
                    'toNameOth'=>$sender_replyto->personal,
                    'subject'=>$mail_header->subject,
                    'to'=>strtolower($mail_header->toaddress),
                    'bounce'=>$stat,
                    'date'=>$mail_header->date
                );
        return $mail_details;
    }


    /**
     * @param $structure
     * @return string
     */
    protected function get_mime_type(&$structure) //Get Mime type Internal Private Use
    {
        $primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");

        if($structure->subtype) 
        {
            return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype;
        }
        return "TEXT/PLAIN";
    }


    /**
     * @param $stream
     * @param $msg_number
     * @param $mime_type
     * @param $structure
     * @param $part_number
     * @return false|string
     */
    protected function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) //Get Part Of Message Internal Private Use
    {
        if(!$structure) 
        {
            $structure = imap_fetchstructure($stream, $msg_number);
        }
        if($structure) 
        {
            if($mime_type == $this->get_mime_type($structure))
            {
                if(!$part_number)
                {
                    $part_number = '1';
                }
                $text = imap_fetchbody($stream, $msg_number, $part_number);
                if($structure->encoding == 3)
                {
                    return imap_base64($text);
                }
                else if($structure->encoding == 4)
                {
                    return imap_qprint($text);
                }
                else
                {
                    return $text;
                }
            }
            if($structure->type == 1) /* multipart */
            {
                foreach($structure->parts as $index => $sub_structure)
                {
                    if($part_number)
                    {
                        $prefix = $part_number . '.';
                    }
                    $data = $this->get_part($stream, $msg_number, $mime_type, $sub_structure, $prefix . ($index + 1));
                    if($data)
                    {
                        return $data;
                    }
                }
            }
        }
        return false;
    }


    /**
     * @param $mid
     * @param $mode
     * @return false|string
     */
    function getBody($mid, $mode='') // Get Message Body
    {
        if($mode != 'plain')
        {
            $body = $this->get_part($this->mailResource, $mid, 'TEXT/HTML');
        }
        if (($body == '') || $mode == 'plain')
        {
            $body = $this->get_part($this->mailResource, $mid, 'TEXT/PLAIN');
        }
        if ($body == '') 
        {
            return '';
        }
        return $body;
    }


    /**
     * @param $mid
     * @return void
     */
    function deleteMails($mid) // Delete That Mail
    {
        imap_delete($this->mailResource,$mid);
    }


    /**
     * @return void
     */
    function close_mailbox() //Close Mail Box
    {
        imap_close($this->mailResource,CL_EXPUNGE);
    }



    /**
     * Loop reading all emails from the bounces mailbox. If an email address and/or e107 header are
     * identified, process the bounce.
     * Delete all emails after processing, if $pref flag is set.
     *
     * @return void
     */
    public function processBounces()
    {
        $identifier = deftrue('MAIL_IDENTIFIER', 'X-e107-id');
        
        $this->connect();
        $tot = $this->getTotalMails();        // Get all the emails
        for ($i = 1; $i <= $tot; $i++)
        {
            $head = $this->getHeaders($i);    // Get the headers
            if ($head['bounce'])
            {
                //print_a($head);
                $body = $this->getBody($i);
                $e107Header = '';
                if (preg_match('#.*'.$identifier.':(.*?)[\n\r]#',$body, $result))
                {
                    $e107Header = varset($result[1],'');
                }
                $emailAddress = '';
                if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$body,$result))
                {
                    $emailAddress = varset($result[0],'');
                    if ($emailAddress == $this->email)
                    {
                        $emailAddress = '';            // Email address found is that of the bounce email account
                    }
                }
                // Call the bounce handler here
                if ($this->mailManager === FALSE)
                {
                    require_once(e_HANDLER.'mail_manager_class.php');
                    $this->mailManager = new e107MailManager();
                }
                echo "Email: {$emailAddress}<br />Header: {$e107Header}<br />";
                $this->mailManager->markBounce($e107Header, $emailAddress);
            }
            // Now delete the email, if option set (do it regardless of whether a bounce email)
            if ($this->delBounce)
            {
                $this->deleteMails($i);        // Not actually deleted until we close the mailbox
            }
        }
        $this->close_mailbox();
    }
}