/**
 * Read messages from server and save returned emails into DB
 *
 * @param resource $mbox created by dre_connect() (by reference)
 * @param integer the number of messages to process
 * @param boolean TRUE if script is executed by cron
 * @return boolean true on success
 */
function dre_process_messages(&$mbox, $limit, $cron = false)
{
    global $Settings, $debug;
    global $dre_messages, $dre_emails, $email_cntr, $del_cntr, $is_cron_mode;
    // This may take a very long time if there are many messages; No execution time limit:
    set_max_execution_time(0);
    if ($Settings->get('repath_ignore_read')) {
        // Read status info of all messages in order to know which have already been read:
        $msg_statuses = imap_fetch_overview($mbox, '1:' . $limit);
    }
    $email_cntr = 0;
    $del_cntr = 0;
    for ($index = 1; $index <= $limit; $index++) {
        // Repeat for as many messages as allowed...
        dre_msg('<hr /><h3>' . sprintf(T_('Processing message %s:'), '#' . $index) . '</h3>', $cron);
        if ($Settings->get('repath_ignore_read')) {
            // Check if we can read this message or we should skip this:
            if (isset($msg_statuses[$index - 1]) && $msg_statuses[$index - 1]->seen == 1) {
                // Skip this message because it has already been read:
                dre_msg(T_('Ignoring this message because it has aleady been read.'), $cron);
                continue;
            } else {
                // Mark this message as "Seen" in order to don't read it twice:
                imap_setflag_full($mbox, $index, '\\Seen');
            }
        }
        $html_body = '';
        $strbody = '';
        $hasAttachment = false;
        $hasRelated = false;
        // Save email to a temporary file on hard drive, otherwise BIG attachments may take a lot of RAM:
        if (!($tmpMIME = tempnam(sys_get_temp_dir(), 'b2evoMail'))) {
            dre_msg(T_('Could not create temporary file.'), $cron);
            continue;
        }
        // Save the whole body of a specific message from the mailbox:
        imap_savebody($mbox, $tmpMIME, $index);
        // fp> TODO: soemwhere here we should skip messages that already have the "seen" flag. This should be optional but should be the default.
        // This will allow to keep the emails in the INBOX without reprocessing them but to easily try them again my marking them unread.
        // Create random temp directory for message parts:
        $tmpDirMIME = dre_tempdir(sys_get_temp_dir(), 'b2evo_');
        // Instanciate mime_parser.php library:
        $mimeParser = new mime_parser_class();
        $mimeParser->mbox = 0;
        // Set to 0 for parsing a *single* RFC 2822 message
        $mimeParser->decode_headers = 1;
        // Set to 1 if it is	necessary to decode message headers that may have non-ASCII	characters and use other character set encodings
        $mimeParser->ignore_syntax_errors = 1;
        // ignore syntax errors in	malformed messages.
        $mimeParser->extract_addresses = 0;
        // Associative array to specify parameters for the messagedata parsing and decoding operation.
        $MIMEparameters = array('File' => $tmpMIME, 'SaveBody' => $tmpDirMIME, 'SkipBody' => 1);
        // STEP 1: Parse and decode message data and retrieve its structure:
        if (!$mimeParser->Decode($MIMEparameters, $decodedMIME)) {
            // error:
            dre_msg(sprintf(T_('MIME message decoding error: %s at position %d.'), $mimeParser->error, $mimeParser->error_position), $cron);
            rmdir_r($tmpDirMIME);
            unlink($tmpMIME);
            continue;
        } else {
            // the specified message data was parsed successfully:
            dre_msg(T_('MIME message decoding successful'), $cron);
            // STEP 2: Analyze (the first) parsed message to describe its contents:
            if (!$mimeParser->Analyze($decodedMIME[0], $parsedMIME)) {
                // error:
                dre_msg(sprintf(T_('MIME message analyze error: %s'), $mimeParser->error), $cron);
                rmdir_r($tmpDirMIME);
                unlink($tmpMIME);
                continue;
            }
            // Get message $subject and $post_date from headers (by reference)
            if (!dre_process_header($parsedMIME, $subject, $post_date, $cron)) {
                // Couldn't process message headers:
                rmdir_r($tmpDirMIME);
                unlink($tmpMIME);
                continue;
            }
            // TODO: handle type == "message" recursively
            // fp> where is type == "message" ???
            // yura> I don't find the type == 'message' in dump of $decodedMIME and $parsedMIME
            // sam2kb> For some reason imap_qprint() demages HTML text... needs more testing
            // yura> I replaced imap_qprint() with quoted_printable_decode() to avoid notices about invalid quoted-printable sequence
            // yura> imap_qprint() and quoted_printable_decode() do empty the message text, thus they were deleted.
            dre_msg(T_('Email Type') . ': ' . $parsedMIME['Type'], $cron);
            if ($parsedMIME['Type'] == 'html') {
                // Mail is HTML:
                if ($debug) {
                    // Display this info only in debug mode:
                    dre_msg(sprintf(T_('HTML message part saved as %s'), $parsedMIME['DataFile']), $cron);
                }
                $html_body = file_get_contents($parsedMIME['DataFile']);
                if (empty($html_body)) {
                    // Try to get a body text from alternative parts if main html body is empty:
                    foreach ($parsedMIME['Alternative'] as $alternative) {
                        // First try to get HTML alternative (when possible)
                        if ($alternative['Type'] == 'html') {
                            // HTML text
                            if ($debug) {
                                // Display this info only in debug mode:
                                dre_msg(sprintf(T_('HTML alternative message part saved as %s'), $alternative['DataFile']), $cron);
                            }
                            $strbody = file_get_contents($alternative['DataFile']);
                            break;
                            // stop after first alternative
                        } elseif ($alternative['Type'] == 'text') {
                            // Plain text
                            if ($debug) {
                                // Display this info only in debug mode:
                                dre_msg(sprintf(T_('Text alternative message part saved as %s'), $alternative['DataFile']), $cron);
                            }
                            $strbody = file_get_contents($alternative['DataFile']);
                            break;
                            // stop after first alternative
                        }
                    }
                }
            } elseif ($parsedMIME['Type'] == 'text') {
                // Mail is plain text:
                if ($debug) {
                    // Display this info only in debug mode:
                    dre_msg(sprintf(T_('Plain-text message part saved as %s'), $parsedMIME['DataFile']), $cron);
                }
                $strbody = file_get_contents($parsedMIME['DataFile']);
            } elseif ($parsedMIME['Type'] == 'delivery-status') {
                // Mail is delivery-status:
                $strbody = $parsedMIME['Response'];
            }
            if (count($mimeParser->warnings) > 0) {
                // Record potential warnings:
                dre_msg('<h4>' . sprintf(T_('%d warnings during decode:'), count($mimeParser->warnings)) . '</h4>', $cron);
                foreach ($mimeParser->warnings as $k => $v) {
                    dre_msg(sprintf(T_('Warning: %s at position %s'), $v, $k), $cron);
                }
            }
        }
        unlink($tmpMIME);
        if (empty($html_body)) {
            // Plain-text message
            dre_msg(sprintf(T_('Message type: %s'), 'TEXT'), $cron);
            // Process body. First fix different line-endings (dos, mac, unix), remove double newlines
            $content = str_replace(array("\r", "\n\n"), "\n", trim($strbody));
            dre_msg(sprintf(T_('Message body: %s'), '<pre style="font-size:10px">' . htmlspecialchars($strbody) . '</pre>'), $cron);
        } else {
            // HTML message
            dre_msg(sprintf(T_('Message type: %s'), 'HTML'), $cron);
            dre_msg(sprintf(T_('Message body (original): %s'), '<pre style="font-size:10px">' . htmlspecialchars($html_body) . '</pre>', $cron));
            // Prepare html message body text:
            $content = dre_prepare_html_message($html_body);
            dre_msg(sprintf(T_('Message body (processed): %s'), '<pre style="font-size:10px">' . htmlspecialchars($content) . '</pre>', $cron));
        }
        dre_msg('<b class="green">' . T_('MIME Decoding Successful') . '</b>', $cron);
        $message_text = $content;
        // Remove content after terminators
        $content = dre_limit_by_terminators($content);
        global $Messages;
        if ($Messages->has_errors()) {
            // Make it easier for user to find and correct the errors
            dre_msg("\n" . sprintf(T_('Processing message: %s'), $post_title), $cron);
            dre_msg($Messages->get_string(T_('Cannot post, please correct these errors:'), 'error'), $cron);
            $Messages->clear();
            rmdir_r($tmpDirMIME);
            continue;
        }
        global $dre_emails, $DB, $localtimenow;
        dre_msg('<h4>' . T_('Saving the returned email in the database') . '</h4>', $cron);
        // Get Headers from Decoded MIME Data:
        $email_headers = dre_get_headers($decodedMIME);
        // Get data of the returned email:
        $email_data = dre_get_email_data($content, $message_text, $email_headers);
        dre_msg(T_('Email Address') . ': ' . $email_data['address'], $cron);
        dre_msg(T_('Error Type') . ': ' . dre_decode_error_type($email_data['errtype']), $cron);
        dre_msg(T_('Error Message') . ': ' . $email_data['errormsg'], $cron);
        // Insert a returned email's data into DB
        if (dre_insert_returned_email($email_data)) {
            ++$email_cntr;
        }
        // Delete temporary directory:
        rmdir_r($tmpDirMIME);
        // Mark message to be deleted:
        if ($Settings->get('repath_delete_emails')) {
            dre_msg(sprintf(T_('Marking message for deletion from inbox: %s'), $index), $cron);
            imap_delete($mbox, $index);
            ++$del_cntr;
        }
    }
    // Expunge messages marked for deletion
    imap_expunge($mbox);
    return true;
}
/**
 * Read messages from server and save returned emails into DB
 *
 * @param resource $mbox created by dre_connect() (by reference)
 * @param integer the number of messages to process
 * @return boolean true on success
 */
function dre_process_messages(&$mbox, $limit)
{
    //return; // Exit, in development...
    global $Settings;
    global $dre_messages, $dre_emails, $email_cntr, $del_cntr, $is_cron_mode;
    // No execution time limit
    set_max_execution_time(0);
    $email_cntr = 0;
    $del_cntr = 0;
    for ($index = 1; $index <= $limit; $index++) {
        dre_msg('<hr /><h3>Processing message #' . $index . ':</h3>');
        $strbody = '';
        $hasAttachment = false;
        $hasRelated = false;
        // Save email to hard drive, otherwise attachments may take a lot of RAM
        if (!($tmpMIME = tempnam(sys_get_temp_dir(), 'b2evoMail'))) {
            dre_msg(T_('Could not create temporary file.'), true);
            continue;
        }
        imap_savebody($mbox, $tmpMIME, $index);
        // Create random temp directory for message parts
        $tmpDirMIME = dre_tempdir(sys_get_temp_dir(), 'b2evo_');
        $mimeParser = new mime_parser_class();
        $mimeParser->mbox = 0;
        // Set to 0 for parsing a single message file
        $mimeParser->decode_headers = 1;
        $mimeParser->ignore_syntax_errors = 1;
        $mimeParser->extract_addresses = 0;
        $MIMEparameters = array('File' => $tmpMIME, 'SaveBody' => $tmpDirMIME, 'SkipBody' => 1);
        if (!$mimeParser->Decode($MIMEparameters, $decodedMIME)) {
            dre_msg(sprintf('MIME message decoding error: %s at position %d.', $mimeParser->error, $mimeParser->error_position), true);
            rmdir_r($tmpDirMIME);
            unlink($tmpMIME);
            continue;
        } else {
            dre_msg('MIME message decoding successful');
            if (!$mimeParser->Analyze($decodedMIME[0], $parsedMIME)) {
                dre_msg(sprintf('MIME message analyse error: %s', $mimeParser->error), true);
                rmdir_r($tmpDirMIME);
                unlink($tmpMIME);
                continue;
            }
            // Get message $subject and $post_date from headers (by reference)
            if (!dre_process_header($parsedMIME, $subject, $post_date)) {
                // Couldn't process message headers
                rmdir_r($tmpDirMIME);
                unlink($tmpMIME);
                continue;
            }
            // TODO: handle type == "message" recursively
            // sam2kb> For some reason imap_qprint() demages HTML text... needs more testing
            if ($parsedMIME['Type'] == 'html') {
                // Mail is HTML
                dre_msg('HTML message part saved as ' . $parsedMIME['DataFile']);
                $html_body = file_get_contents($parsedMIME['DataFile']);
                foreach ($parsedMIME['Alternative'] as $alternative) {
                    // First try to get HTML alternative (when possible)
                    if ($alternative['Type'] == 'html') {
                        // HTML text
                        dre_msg('HTML alternative message part saved as ' . $alternative['DataFile']);
                        // sam2kb> TODO: we may need to use $html_body here instead
                        $strbody = file_get_contents($alternative['DataFile']);
                        break;
                        // stop after first alternative
                    } elseif ($alternative['Type'] == 'text') {
                        // Plain text
                        dre_msg('Text alternative message part saved as ' . $alternative['DataFile']);
                        $strbody = imap_qprint(file_get_contents($alternative['DataFile']));
                        break;
                        // stop after first alternative
                    }
                }
            } elseif ($parsedMIME['Type'] == 'text') {
                // Mail is plain text
                dre_msg('Plain-text message part saved as ' . $parsedMIME['DataFile']);
                $strbody = imap_qprint(file_get_contents($parsedMIME['DataFile']));
            } elseif ($parsedMIME['Type'] == 'delivery-status') {
                // Mail is delivery-status
                $strbody = '';
                foreach ($decodedMIME[0]['Parts'] as $part) {
                    $strbody .= imap_qprint(file_get_contents($part['BodyFile']));
                }
            }
            if (count($mimeParser->warnings) > 0) {
                dre_msg(sprintf('<h4>%d warnings during decode:</h4>', count($mimeParser->warnings)));
                foreach ($mimeParser->warnings as $k => $v) {
                    dre_msg('Warning: ' . $v . ' at position ' . $k);
                }
            }
        }
        unlink($tmpMIME);
        if (empty($html_body)) {
            // Plain text message
            dre_msg('Message type: TEXT');
            dre_msg('Message body: <pre style="font-size:10px">' . htmlspecialchars($strbody) . '</pre>');
            // Process body. First fix different line-endings (dos, mac, unix), remove double newlines
            $content = str_replace(array("\r", "\n\n"), "\n", trim($strbody));
        } else {
            // HTML message
            dre_msg('Message type: HTML');
            if (($parsed_message = dre_prepare_html_message($html_body)) === false) {
                // No 'auth' tag provided, skip to the next message
                rmdir_r($tmpDirMIME);
                continue;
            }
            list($auth, $content) = $parsed_message;
        }
        dre_msg('<b class="green">Success</b>');
        $message_text = $content;
        // Remove content after terminators
        $content = dre_limit_by_terminators($content);
        global $Messages;
        if ($Messages->has_errors()) {
            // Make it easier for user to find and correct the errors
            dre_msg("\n" . sprintf(T_('Processing message: %s'), $post_title), true);
            dre_msg($Messages->get_string(T_('Cannot post, please correct these errors:'), 'error'), true);
            $Messages->clear();
            rmdir_r($tmpDirMIME);
            continue;
        }
        global $dre_emails, $DB, $localtimenow;
        dre_msg(sprintf('<h4>Saving the returned email in the database</h4>'));
        // Insert a returned email's data into DB
        if ($returned_email = dre_insert_returned_email($content, $message_text, dre_get_headers($decodedMIME))) {
            dre_msg('Error Type: ' . dre_decode_error_type($returned_email['errtype']));
            dre_msg('Error Message: ' . $returned_email['errormsg']);
            ++$email_cntr;
        }
        // Delete temporary directory
        rmdir_r($tmpDirMIME);
        if ($Settings->get('repath_delete_emails')) {
            dre_msg('Marking message for deletion from inbox: ' . $index);
            imap_delete($mbox, $index);
            ++$del_cntr;
        }
    }
    // Expunge messages market for deletion
    imap_expunge($mbox);
    return true;
}