diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php
index fb17d8a26ac719854a683ba778c287321ddefea9..39e19f21ccbe3b3e0271f12614454e563dedcc96 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -17,112 +17,161 @@
 require_once(INCLUDE_DIR.'class.mailparse.php');
 require_once(INCLUDE_DIR.'class.ticket.php');
 require_once(INCLUDE_DIR.'class.dept.php');
+require_once(INCLUDE_DIR.'class.email.php');
 require_once(INCLUDE_DIR.'class.filter.php');
 
 class MailFetcher {
-    var $hostname;
-    var $username;
-    var $password;
 
-    var $port;
-    var $protocol;
-    var $encryption;
+    var $ht;
 
     var $mbox;
+    var $srvstr;
 
-    var $charset= 'UTF-8';
+    var $charset = 'UTF-8';
+    var $encodings =array('UTF-8','WINDOWS-1251', 'ISO-8859-5', 'ISO-8859-1','KOI8-R');
     
-    function MailFetcher($username,$password,$hostname,$port,$protocol,$encryption='') {
+    function MailFetcher($email, $charset='UTF-8') {
 
-        if(!strcasecmp($protocol,'pop')) //force pop3
-            $protocol='pop3';
-
-        $this->hostname=$hostname;
-        $this->username=$username;
-        $this->password=$password;
-        $this->protocol=strtolower($protocol);
-        $this->port = $port;
-        $this->encryption = $encryption;
+        
+        if($email && is_numeric($email)) //email_id
+            $email=Email::lookup($email);
+
+        if(is_object($email))
+            $this->ht = $email->getMailAccountInfo();
+        elseif(is_array($email) && $email['host']) //hashtable of mail account info
+            $this->ht = $email; 
+        else
+            $this->ht = null;
+           
+        $this->charset = $charset;
+
+        if($this->ht) {
+            if(!strcasecmp($this->ht['protocol'],'pop')) //force pop3
+                $this->ht['protocol'] = 'pop3';
+            else
+                $this->ht['protocol'] = strtolower($this->ht['protocol']);
+
+            //Max fetch per poll
+            if(!$this->ht['max_fetch'] || !is_numeric($this->ht['max_fetch']))
+                $this->ht['max_fetch'] = 20;
+
+            //Mail server string
+            $this->srvstr=sprintf('{%s:%d/%s', $this->getHost(), $this->getPort(), $this->getProtocol());
+            if(!strcasecmp($this->getEncryption(), 'SSL'))
+                $this->srvstr.='/ssl';
+        
+            $this->srvstr.='/novalidate-cert}';
 
-        $this->serverstr=sprintf('{%s:%d/%s',$this->hostname,$this->port,strtolower($this->protocol));
-        if(!strcasecmp($this->encryption,'SSL')){
-            $this->serverstr.='/ssl';
         }
-        $this->serverstr.='/novalidate-cert}INBOX'; //add other flags here as needed.
 
-        //echo $this->serverstr;
-        //Charset to convert the mail to.
-        $this->charset='UTF-8';
         //Set timeouts 
-        if(function_exists('imap_timeout'))
-            imap_timeout(1,20); //Open timeout.
+        if(function_exists('imap_timeout')) imap_timeout(1,20);
+
+    }
+
+    function getEmailId() {
+        return $this->ht['email_id'];
+    }
+
+    function getHost() {
+        return $this->ht['host'];
+    }
+
+    function getPort() {
+        return $this->ht['port'];
+    }
+
+    function getProtocol() {
+        return $this->ht['protocol'];
+    }
+
+    function getEncryption() {
+        return $this->ht['encryption'];
+    }
+
+    function getUsername() {
+        return $this->ht['username'];
     }
     
+    function getPassword() {
+        return $this->ht['password'];
+    }
+
+    /* osTicket Settings */
+
+    function canDeleteEmails() {
+        return ($this->ht['delete_mail']);
+    }
+
+    function getMaxFetch() {
+        return $this->ht['max_fetch'];
+    }
+
+    function getArchiveFolder() {
+        return $this->ht['archive_folder'];
+    }
+
+    /* Core */
+    
     function connect() {
-        return $this->open()?true:false;
+        return ($this->mbox && $this->ping())?$this->mbox:$this->open();
     }
 
-    function open() {
-       
-        //echo $this->serverstr;
-        if($this->mbox && imap_ping($this->mbox))
-            return $this->mbox;
-            
-        $this->mbox =@imap_open($this->serverstr,$this->username,$this->password);
-        
+    function ping() {
+        return ($this->mbox && imap_ping($this->mbox));
+    }
+
+    /* Default folder is inbox - TODO: provide user an option to fetch from diff folder/label */
+    function open($box='INBOX') {
+      
+        if($this->mbox)
+           $this->close();
+
+        $this->mbox = imap_open($this->srvstr.$box, $this->getUsername(), $this->getPassword());
+
         return $this->mbox;
     }
 
-    function close() {
-        imap_close($this->mbox,CL_EXPUNGE);
+    function close($flag=CL_EXPUNGE) {
+        imap_close($this->mbox, $flag);
     }
 
-    function mailcount(){
+    function mailcount() {
         return count(imap_headers($this->mbox));
     }
 
     //Get mail boxes.
-    function getMailboxes(){
+    function getMailboxes() {
 
+        if(!($folders=imap_list($this->mbox, $this->srvstr, "*")) || !is_array($folders))
+            return null;
 
-        $mstr=sprintf('{%s:%d/%s',$this->hostname,$this->port,strtolower($this->protocol));
-        if(!strcasecmp($this->encryption,'SSL'))
-            $mstr.='/ssl';
-        $mstr.='/novalidate-cert}';
-        $list=array();
-        if(($folders=imap_listmailbox($this->mbox,$mstr,'*')) && is_array($folders)){
-            foreach($folders as $k=>$folder){
-                $list[]= str_replace($mstr, "", imap_utf7_decode(trim($folder)));
-            }
-        }
+        $list = array();
+        foreach($folders as $k => $folder)
+            $list[]= str_replace($this->srvstr, '', imap_utf7_decode(trim($folder)));
 
         return $list;
     }
 
     //Create a folder.
-    function createMailbox($folder){
+    function createMailbox($folder) {
 
         if(!$folder) return false;
-
-        $mstr=sprintf('{%s:%d/%s',$this->hostname,$this->port,strtolower($this->protocol));
-        if(!strcasecmp($this->encryption,'SSL'))
-            $mstr.='/ssl';
-        $mstr.='/novalidate-cert}'.$folder;
             
-        return imap_createmailbox($this->mbox,imap_utf7_encode($mstr));
+        return imap_createmailbox($this->mbox, imap_utf7_encode($this->srvstr.trim($folder)));
     }
 
-    /* check if a folder exits - create on if requested */
-    function checkMailbox($folder,$create=false){
+    /* check if a folder exists - create one if requested */
+    function checkMailbox($folder, $create=false) {
 
-        if(($mailboxes=$this->getMailboxes()) && in_array($folder,$mailboxes))
+        if(($mailboxes=$this->getMailboxes()) && in_array(trim($folder), $mailboxes))
             return true;
 
         return ($create && $this->createMailbox($folder));
     }
 
 
-    function decode($encoding,$text) {
+    function decode($encoding, $text) {
 
         switch($encoding) {
             case 1:
@@ -145,14 +194,13 @@ class MailFetcher {
     }
 
     //Convert text to desired encoding..defaults to utf8
-    function mime_encode($text,$charset=null,$enc='utf-8') { //Thank in part to afterburner  
-                
-        $encodings=array('UTF-8','WINDOWS-1251', 'ISO-8859-5', 'ISO-8859-1','KOI8-R');
-        if(function_exists("iconv") and $text) {
+    function mime_encode($text, $charset=null, $enc='utf-8') { //Thank in part to afterburner  
+        
+        if(function_exists('iconv') and $text) {
             if($charset)
-                return iconv($charset,$enc.'//IGNORE',$text);
-            elseif(function_exists("mb_detect_encoding"))
-                return iconv(mb_detect_encoding($text,$encodings),$enc,$text);
+                return iconv($charset, $enc.'//IGNORE', $text);
+            elseif(function_exists('mb_detect_encoding'))
+                return iconv(mb_detect_encoding($text, $this->encodings), $enc, $text);
         }
 
         return utf8_encode($text);
@@ -161,15 +209,15 @@ class MailFetcher {
     //Generic decoder - mirrors imap_utf8
     function mime_decode($text) {
         
-        $a = imap_mime_header_decode($text);
         $str = '';
-        foreach ($a as $k => $part)
+        $parts = imap_mime_header_decode($text);
+        foreach ($parts as $k => $part)
             $str.= $part->text;
         
         return $str?$str:imap_utf8($text);
     }
 
-    function getLastError(){
+    function getLastError() {
         return imap_last_error();
     }
 
@@ -183,67 +231,128 @@ class MailFetcher {
 
     function getHeaderInfo($mid) {
         
-        $headerinfo=imap_headerinfo($this->mbox,$mid);
-        $sender=$headerinfo->from[0];
+        if(!($headerinfo=imap_headerinfo($this->mbox, $mid)) || !$headerinfo->from)
+            return null;
 
-        //Parse what we need...
-        $header=array(
-                      'from'   =>array('name'  =>@$sender->personal,'email' =>strtolower($sender->mailbox).'@'.$sender->host),
+        $sender=$headerinfo->from[0];
+        //Just what we need...
+        $header=array('name'  =>@$sender->personal,
+                      'email' =>(strtolower($sender->mailbox).'@'.$sender->host),
                       'subject'=>@$headerinfo->subject,
-                      'mid'    =>$headerinfo->message_id);
+                      'mid'    =>$headerinfo->message_id
+                      );
+
         return $header;
     }
 
+    function getAttachment($part) {
+
+        if(!$part) return null;
+
+        if($part->ifdisposition && in_array(strtolower($part->disposition), array('attachment', 'inline')))
+            return $part->dparameters[0]->value;
+
+        if($part->ifparameters && $part->type == 5)
+            return $part->parameters[0]->value;
+
+
+        return null;
+    }
+
     //search for specific mime type parts....encoding is the desired encoding.
-    function getPart($mid,$mimeType,$encoding=false,$struct=null,$partNumber=false){
+    function getPart($mid, $mimeType, $encoding=false, $struct=null, $partNumber=false) {
           
         if(!$struct && $mid)
             $struct=@imap_fetchstructure($this->mbox, $mid);
+
         //Match the mime type.
-        if($struct && !$struct->ifdparameters && strcasecmp($mimeType,$this->getMimeType($struct))==0){
+        if($struct && !$struct->ifdparameters && strcasecmp($mimeType, $this->getMimeType($struct))==0) {
             $partNumber=$partNumber?$partNumber:1;
-            if(($text=imap_fetchbody($this->mbox, $mid, $partNumber))){
+            if(($text=imap_fetchbody($this->mbox, $mid, $partNumber))) {
                 if($struct->encoding==3 or $struct->encoding==4) //base64 and qp decode.
-                    $text=$this->decode($struct->encoding,$text);
+                    $text=$this->decode($struct->encoding, $text);
 
                 $charset=null;
                 if($encoding) { //Convert text to desired mime encoding...
-                    if($struct->ifparameters){
+                    if($struct->ifparameters) {
                         if(!strcasecmp($struct->parameters[0]->attribute,'CHARSET') && strcasecmp($struct->parameters[0]->value,'US-ASCII'))
                             $charset=trim($struct->parameters[0]->value);
                     }
-                    $text=$this->mime_encode($text,$charset,$encoding);
+                    $text=$this->mime_encode($text, $charset, $encoding);
                 }
                 return $text;
             }
         }
+
         //Do recursive search
         $text='';
-        if($struct && $struct->parts){
+        if($struct && $struct->parts) {
             while(list($i, $substruct) = each($struct->parts)) {
                 if($partNumber) 
                     $prefix = $partNumber . '.';
-                if(($result=$this->getPart($mid,$mimeType,$encoding,$substruct,$prefix.($i+1))))
+                if(($result=$this->getPart($mid, $mimeType, $encoding, $substruct, $prefix.($i+1))))
                     $text.=$result;
             }
         }
+
         return $text;
     }
 
-    function getHeader($mid){
+    /*
+     getAttachments
+
+     search and return a hashtable of attachments....
+     NOTE: We're not actually fetching the body of the attachment  - we'll do it on demand to save some memory.
+
+     */
+    function getAttachments($part, $index=0) {
+
+        if($part && !$part->parts) {
+            //Check if the part is an attachment.
+            $filename = '';
+            if($part->ifdisposition && in_array(strtolower($part->disposition), array('attachment', 'inline')))
+                $filename = $part->dparameters[0]->value;
+            elseif($part->ifparameters && $part->type == 5) //inline image without disposition.
+                $filename = $part->parameters[0]->value;
+
+            if($filename) {
+                return array(
+                        array(
+                            'name'  => $filename,
+                            'mime'  => $this->getMimeType($part),
+                            'encoding' => $part->encoding,
+                            'index' => ($index?$index:1)
+                            )
+                        );
+            }
+        }
+
+        //Recursive attachment search!
+        $attachments = array();
+        if($part && $part->parts) {
+            foreach($part->parts as $k=>$struct) {
+                if($index) $prefix = $index.'.';
+                $attachments = array_merge($attachments, $this->getAttachments($struct, $prefix.($k+1)));
+            }
+        }
+
+        return $attachments;
+    }
+
+    function getHeader($mid) {
         return imap_fetchheader($this->mbox, $mid,FT_PREFETCHTEXT);
     }
 
     
-    function getPriority($mid){
+    function getPriority($mid) {
         return Mail_Parse::parsePriority($this->getHeader($mid));
     }
 
     function getBody($mid) {
         
         $body ='';
-        if(!($body = $this->getPart($mid,'TEXT/PLAIN',$this->charset))) {
-            if(($body = $this->getPart($mid,'TEXT/HTML',$this->charset))) {
+        if(!($body = $this->getPart($mid,'TEXT/PLAIN', $this->charset))) {
+            if(($body = $this->getPart($mid,'TEXT/HTML', $this->charset))) {
                 //Convert tags of interest before we striptags
                 $body=str_replace("</DIV><DIV>", "\n", $body);
                 $body=str_replace(array("<br>", "<br />", "<BR>", "<BR />"), "\n", $body);
@@ -251,171 +360,190 @@ class MailFetcher {
                 $body=Format::striptags($body); //Strip tags??
             }
         }
+
         return $body;
     }
 
-    function createTicket($mid,$emailid=0){
-        global $cfg, $ost;
+    //email to ticket 
+    function createTicket($mid) { 
+        global $ost;
 
-        $mailinfo=$this->getHeaderInfo($mid);
+        if(!($mailinfo = $this->getHeaderInfo($mid)))
+            return false;
 
-        //Make sure the email is NOT one of the undeleted emails.
-        if($mailinfo['mid'] && ($id=Ticket::getIdByMessageId(trim($mailinfo['mid']),$mailinfo['from']['email']))){
-            //TODO: Move emails to a fetched folder when delete is false?? 
-            return true;
-        }
+        //Make sure the email is NOT already fetched... (undeleted emails)
+        if($mailinfo['mid'] && ($id=Ticket::getIdByMessageId(trim($mailinfo['mid']), $mailinfo['email'])))
+            return true; //Reporting success so the email can be moved or deleted.
 
 	    //Is the email address banned?
-        if($mailinfo['from']['email'] && EmailFilter::isBanned($mailinfo['from']['email'])) {
+        if($mailinfo['email'] && EmailFilter::isBanned($mailinfo['email'])) {
 	        //We need to let admin know...
-            $ost->logWarning('Ticket denied', 'Banned email - '.$mailinfo['from']['email']);
-	        return true;
+            $ost->logWarning('Ticket denied', 'Banned email - '.$mailinfo['email']);
+	        return true; //Report success (moved or delete)
         }
-	
 
-        $var['name']=$this->mime_decode($mailinfo['from']['name']);
-        $var['email']=$mailinfo['from']['email'];
+        $emailId = $this->getEmailId();
+
+        $var['name']=$this->mime_decode($mailinfo['name']);
+        $var['email']=$mailinfo['email'];
         $var['subject']=$mailinfo['subject']?$this->mime_decode($mailinfo['subject']):'[No Subject]';
         $var['message']=Format::stripEmptyLines($this->getBody($mid));
         $var['header']=$this->getHeader($mid);
-        $var['emailId']=$emailid?$emailid:$cfg->getDefaultEmailId(); //ok to default?
+        $var['emailId']=$emailid?$emailid:$ost->getConfig()->getDefaultEmailId(); //ok to default?
         $var['name']=$var['name']?$var['name']:$var['email']; //No name? use email
         $var['mid']=$mailinfo['mid'];
 
-        if($cfg->useEmailPriority())
+        if(!$var['message']) //An email with just attachments can have empty body.
+            $var['message'] = '(EMPTY)';
+
+        if($ost->getConfig()->useEmailPriority())
             $var['priorityId']=$this->getPriority($mid);
        
         $ticket=null;
         $newticket=true;
         //Check the subject line for possible ID.
-        if(preg_match ("[[#][0-9]{1,10}]",$var['subject'],$regs)) {
+        if($var['subject'] && preg_match ("[[#][0-9]{1,10}]", $var['subject'], $regs)) {
             $extid=trim(preg_replace("/[^0-9]/", "", $regs[0]));
-            $ticket= new Ticket(Ticket::getIdByExtId($extid));
             //Allow mismatched emails?? For now NO.
-            if(!$ticket || strcasecmp($ticket->getEmail(),$var['email']))
+            if(!($ticket=Ticket::lookupByExtId($extId)) || strcasecmp($ticket->getEmail(), $var['email']))
                 $ticket=null;
         }
         
         $errors=array();
-        if(!$ticket) {
-            # Apply email filters for the new ticket
-            $ef = new EmailFilter($var); $ef->apply($var);
-            if(!($ticket=Ticket::create($var,$errors,'Email')) || $errors)
-                return null;
-            $msgid=$ticket->getLastMsgId();
-        }else{
-            $message=$var['message'];
-            //Strip quoted reply...TODO: figure out how mail clients do it without special tag..
-            if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()) && strpos($var['message'],$tag))
-                list($message)=split($tag,$var['message']);
-            $msgid=$ticket->postMessage($message,'Email',$var['mid'],$var['header']);
+        if($ticket) {
+            if(!($msgid=$ticket->postMessage($var['message'], 'Email', $var['mid'], $var['header'])))
+                return false;
+
+        } elseif (($ticket=Ticket::create($var, $errors, 'Email'))) {
+            $msgid = $ticket->getLastMsgId();
+        } else {
+            //TODO: Log error..
+            return null;
         }
-        //Save attachments if any.
-        if($msgid && $cfg->allowEmailAttachments()){
-            if(($struct = imap_fetchstructure($this->mbox,$mid)) && $struct->parts) {
-                if($ticket->getLastMsgId()!=$msgid)
-                    $ticket->setLastMsgId($msgid);
-                $this->saveAttachments($ticket,$mid,$struct);
 
+        //Save attachments if any.
+        if($msgid 
+                && $ost->getConfig()->allowEmailAttachments()
+                && ($struct = imap_fetchstructure($this->mbox, $mid)) 
+                && $struct->parts 
+                && ($attachments=$this->getAttachments($struct))) {
+                
+            //We're just checking the type of file - not size or number of attachments...
+            // Restrictions are mainly due to PHP file uploads limitations
+            foreach($attachments as $a ) {
+                if($ost->isFileTypeAllowed($a['name'], $a['mime'])) {
+                    $file = array(
+                            'name'  => $a['name'],
+                            'type'  => $a['mime'],
+                            'data'  => $this->decode($a['encoding'], imap_fetchbody($this->mbox, $mid, $a['index']))
+                            );
+                    $ticket->saveAttachment($file, $msgid, 'M');
+                } else {
+                    //This should be really a comment on message - NoT an internal note.
+                    //TODO: support comments on Messages and Responses.
+                    $error = sprintf('Attachment %s [%s] rejected because of file type', $a['name'], $a['mime']);
+                    $ticket->postNote('Email Attachment Rejected', $error, false);
+                    $ost->logDebug('Email Attachment Rejected (Ticket #'.$ticket->getExtId().')', $error);
+                }
             }
-        } 
+        }
+
         return $ticket;
     }
 
-    function saveAttachments($ticket,$mid,$part,$index=0) {
-        global $ost;
 
-        if($part && $part->ifdparameters && ($filename=$part->dparameters[0]->value)){ //attachment
-            $index=$index?$index:1;
-            if($ticket 
-                    && $ost->isFileTypeAllowed($filename) 
-                    && $ost->getConfig()->getMaxFileSize()>=$part->bytes) {
-                //extract the attachments...and do the magic.
-                $data=$this->decode($part->encoding, imap_fetchbody($this->mbox,$mid,$index));
-                $ticket->saveAttachment(array('name'=>$filename, 'data'=>$data),$ticket->getLastMsgId(),'M');
-                return;
-            }
-            //TODO: Log failure??
-        }
+    function fetchEmails() {
 
-        //Recursive attachment search!
-        if($part && $part->parts) {
-            foreach($part->parts as $k=>$struct) {
-                if($index) $prefix = $index.'.';
-                $this->saveAttachments($ticket,$mid,$struct,$prefix.($k+1));
-            }
-        }
 
-    }
+        if(!$this->connect())
+            return false;
 
-    function fetchTickets($emailid,$max=20,$deletemsgs=false,$archivefolder){
+        $archiveFolder = $this->getArchiveFolder();
+        $delete = $this->canDeleteEmails();
+        $max = $this->getMaxFetch();
 
         $nummsgs=imap_num_msg($this->mbox);
         //echo "New Emails:  $nummsgs\n";
         $msgs=$errors=0;
-        for($i=$nummsgs; $i>0; $i--){ //process messages in reverse. Latest first. FILO.
-            if($this->createTicket($i,$emailid)){
-                imap_setflag_full($this->mbox, imap_uid($this->mbox,$i), "\\Seen", ST_UID); //IMAP only??
-                if((!$archivefolder || !imap_mail_move($this->mbox,$i,$archivefolder)) && $deletemsgs)
-                    imap_delete($this->mbox,$i);
+        for($i=$nummsgs; $i>0; $i--) { //process messages in reverse.
+            if($this->createTicket($i)) {
+
+                imap_setflag_full($this->mbox, imap_uid($this->mbox, $i), "\\Seen", ST_UID); //IMAP only??
+                if((!$archiveFolder || !imap_mail_move($this->mbox, $i, $archiveFolder)) && $delete)
+                    imap_delete($this->mbox, $i);
+
                 $msgs++;
                 $errors=0; //We are only interested in consecutive errors.
-            }else{
+            } else {
                 $errors++;
             }
-            if(($max && $msgs>=$max) || $errors>20)
+
+            if(($max && $msgs>=$max) || $errors>100)
                 break;
         }
+
         @imap_expunge($this->mbox);
 
         return $msgs;
     }
 
-    function fetchMail(){
-        global $ost, $cfg;
+
+    /*
+       MailFetcher::run()
+
+       Static function called to initiate email polling 
+     */
+    function run() {
+        global $ost;
       
-        if(!$cfg->canFetchMail())
+        if(!$ost->getConfig()->canFetchMail())
             return;
 
         //We require imap ext to fetch emails via IMAP/POP3
+        //We check here just in case the extension gets disabled post email config...
         if(!function_exists('imap_open')) {
-            $msg='osTicket requires PHP IMAP extension enabled for IMAP/POP3 fetch to work!';
+            $msg='osTicket requires PHP IMAP extension enabled for IMAP/POP3 email fetch to work!';
             $ost->logWarning('Mail Fetch Error', $msg);
             return;
         }
 
-        $MAX_ERRORS=5; //Max errors before we start delayed fetch attempts - hardcoded for now.
+        //Hardcoded error control... 
+        $MAXERRORS = 5; //Max errors before we start delayed fetch attempts
+        $TIMEOUT = 10; //Timeout in minutes after max errors is reached.
 
-        $sql=' SELECT email_id,mail_host,mail_port,mail_protocol,mail_encryption,mail_delete,mail_archivefolder,mail_errors,userid,userpass FROM '.EMAIL_TABLE.
-             ' WHERE mail_active=1 AND (mail_errors<='.$MAX_ERRORS.' OR (TIME_TO_SEC(TIMEDIFF(NOW(),mail_lasterror))>5*60) )'.
-             ' AND (mail_lastfetch IS NULL OR TIME_TO_SEC(TIMEDIFF(NOW(),mail_lastfetch))>mail_fetchfreq*60) ';
-        //echo $sql;
-        if(!($accounts=db_query($sql)) || !db_num_rows($accounts))
-            return;
+        $sql=' SELECT email_id, mail_errors FROM '.EMAIL_TABLE
+            .' WHERE mail_active=1 '
+            .'  AND (mail_errors<='.$MAXERRORS.' OR (TIME_TO_SEC(TIMEDIFF(NOW(), mail_lasterror))>'.($TIMEOUT*60).') )'
+            .'  AND (mail_lastfetch IS NULL OR TIME_TO_SEC(TIMEDIFF(NOW(), mail_lastfetch))>mail_fetchfreq*60)'
+            .' ORDER BY mail_lastfetch DESC'
+            .' LIMIT 10'; //Processing up to 10 emails at a time.
+
+       // echo $sql;
+        if(!($res=db_query($sql)) || !db_num_rows($res))
+            return;  /* Failed query (get's logged) or nothing to do... */
 
         //TODO: Lock the table here??
-        while($row=db_fetch_array($accounts)) {
-            $fetcher = new MailFetcher($row['userid'], Mcrypt::decrypt($row['userpass'],SECRET_SALT),
-                                       $row['mail_host'],$row['mail_port'],$row['mail_protocol'],$row['mail_encryption']);
-            if($fetcher->connect()){   
-                $fetcher->fetchTickets($row['email_id'],$row['mail_fetchmax'],$row['mail_delete']?true:false,$row['mail_archivefolder']);
+
+        while(list($emailId, $errors)=db_fetch_row($res)) {
+            $fetcher = new MailFetcher($emailId);
+            if($fetcher->connect()) {
+                $fetcher->fetchEmails();
                 $fetcher->close();
-                db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=0, mail_lastfetch=NOW() WHERE email_id='.db_input($row['email_id']));
-            }else{
-                $errors=$row['mail_errors']+1;
-                db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=mail_errors+1, mail_lasterror=NOW() WHERE email_id='.db_input($row['email_id']));
-                if($errors>=$MAX_ERRORS){
+                db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=0, mail_lastfetch=NOW() WHERE email_id='.db_input($emailId));
+            } else {
+                db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=mail_errors+1, mail_lasterror=NOW() WHERE email_id='.db_input($emailId));
+                if(++$errors>=$MAXERRORS) {
                     //We've reached the MAX consecutive errors...will attempt logins at delayed intervals
-                    $msg="\nThe system is having trouble fetching emails from the following mail account: \n".
-                        "\nUser: ".$row['userid'].
-                        "\nHost: ".$row['mail_host'].
+                    $msg="\nosTicket is having trouble fetching emails from the following mail account: \n".
+                        "\nUser: ".$fetcher->getUsername().
+                        "\nHost: ".$fetcher->getHost().
                         "\nError: ".$fetcher->getLastError().
-                        "\n\n ".$errors.' consecutive errors. Maximum of '.$MAX_ERRORS. ' allowed'.
-                        "\n\n This could be connection issues related to the host. Next delayed login attempt in aprox. 10 minutes";
+                        "\n\n ".$errors.' consecutive errors. Maximum of '.$MAXERRORS. ' allowed'.
+                        "\n\n This could be connection issues related to the mail server. Next delayed login attempt in aprox. $TIMEOUT minutes";
                     $ost->alertAdmin('Mail Fetch Failure Alert', $msg, true);
                 }
             }
-        }
+        } //end while.
     }
 }
 ?>