Search code examples
phpemailphp-imap

How to read unseen mails in PHP


I wrote the following code to read mails from my mailbox to program. when i give "ALL" in imap_search i get all the mails. but when i give "SEEN" or "UNSEEN" I always get zero results. I used the php-imap library to fetch mails from the inbox of my email. I get the results correctly when i use "ALL" in the function imap_search but i zero results when i replace ALL with SEEN or UNSEEN.

MY code:

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href=
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="style.css">

    <script>
        function getEmails() {
            document.getElementById('dataDivID')
                .style.display = "block";
        }
    </script>
</head>

<body>
    <h2>List Emails from inbox of [email protected] using PHP and IMAP</h2>

    <div id="btnContainer">
        <button class="btn active" onclick="getEmails()">
            <i class="fa fa-bars"></i>Click to get mails
        </button>
    </div>
    <br>
    
    <div id="dataDivID" class="form-container" style="display:none;">
        <?php
            
$host = '{mail.cdit.org:993/ssl}INBOX';

            /* Your gmail credentials */
            $user = '[email protected]';
            $password = 'MYPASSWORD';

            /* Establish a IMAP connection */
            $conn = imap_open($host, $user, $password)
                or die('unable to connect mail.cdit.org: ' . imap_last_error());

            /* Search emails from gmail inbox*/
            $mails = imap_search($conn, 'UNSEEN');

            /* loop through each email id mails are available. */
            if ($mails) {

                /* Mail output variable starts*/
                $mailOutput = '';
                $mailOutput.= '<table><tr><th>Subject </th><th> From </th>
                        <th> Date Time </th> <th> Content </th></tr>';

                /* rsort is used to display the latest emails on top */
                rsort($mails);

                /* For each email */
                foreach ($mails as $email_number) {

                    /* Retrieve specific email information*/
                    $headers = imap_fetch_overview($conn, $email_number, 0);
                    //print_r($headers);echo "<br/>";
                    $header = imap_headerinfo($conn, $email_number);
                    //print_r($header);
                    $from = $header->from;
                    
                    foreach ($from as $id => $object) 
                    {
                    $fromname = $object->personal;
                    $fromaddress = $object->mailbox . "@" . $object->host;
                    }

                    /* Returns a particular section of the body*/
                    //$message = imap_fetchbody($conn, $email_number, '1');

                    /* Check the content type */
                    $contentType = $headers[0]->type;

                    /* Fetch the appropriate section based on content type 
                    $message = ($contentType === 0) ? imap_fetchbody($conn, $email_number, '1') : 
                        imap_fetchbody($conn, $email_number, '1.2');*/

                /* Get the email structure */
                /* Retrieve the email structure */
                $structure = imap_fetchstructure($conn, $email_number);

                /* Check if the email has HTML content */
                $htmlMessage = '';$message='';
                if (isset($structure->parts) && is_array($structure->parts)) {
                    foreach ($structure->parts as $part) {
                        if ($part->subtype === 'HTML') {
                            $htmlMessage = getDecodedContent($conn, $email_number, $part);
                            break;
                        }
                    }
                }

                /* If HTML content is empty or unavailable, fetch the plain text version */
                if (empty($htmlMessage)) {
                    $message = getDecodedContent($conn, $email_number, $structure);
                } else {
                    $message = $htmlMessage;
                }


                    /*$subMessage = substr($message, 0, 150);
                    $finalMessage = trim(quoted_printable_decode($subMessage));*/
                    $finalMessage = getActualContent($message);
                    $mailOutput.= '<div class="row">';

                    /* Gmail MAILS header information */                
                    $mailOutput.= '<td><span class="columnClass">' .
                                $headers[0]->subject . '</span></td> ';
                    $mailOutput.= '<td><span class="columnClass">' .
                                $fromaddress . '</span></td>';
                    $mailOutput.= '<td><span class="columnClass">' .
                                $headers[0]->date . '</span></td>';
                    $mailOutput.= '</div>';

                    /* Mail body is returned */
                    $mailOutput.= '<td><span class="column">' .
                    $finalMessage . '</span></td></tr></div>';
                }// End foreach
                $mailOutput.= '</table>';
                echo $mailOutput;
            }//endif

            /* imap connection is closed */
            imap_close($conn);
            
            /**
 * Get the decoded content from a specific part of the email.
 *
 * @param resource $conn The IMAP connection resource.
 * @param int $email_number The email number.
 * @param object $part The specific part of the email structure.
 * @return string The decoded content.
 */
function getDecodedContent($conn, $email_number, $part) {
    $encoding = $part->encoding;
    $content = '';

    if ($part->type === 0) {
        $content = imap_fetchbody($conn, $email_number, $part->partNumber, FT_PEEK);
    } elseif ($part->type === 1 || $part->type === 2 || $part->type === 3) {
        $content = imap_fetchbody($conn, $email_number, $part->partNumber);
    }

    switch ($encoding) {
        case 1: // BASE64
            $content = base64_decode($content);
            break;
        case 2: // QUOTED-PRINTABLE
            $content = quoted_printable_decode($content);
            break;
        case 3: // 8BIT
        case 4: // 7BIT
        case 5: // BINARY
        default:
            break;
    }

    return $content;
}

function getActualContent($content)
{

$startMarker = 'base64';
$endMarker = '--b1';

$startPos = strpos($content, $startMarker);
if ($startPos !== false) {
    $startPos = strpos($content, PHP_EOL, $startPos) + strlen(PHP_EOL);
    $endPos = strpos($content, $endMarker, $startPos);
    if ($endPos !== false) {
        $substring = substr($content, $startPos, $endPos - $startPos);
        //echo $substring;
    }
}

return base64_decode($substring);

}


?>
    </div>
</body>

</html>

Please give me the correct code to get results of read/unread mails.


Solution

  • I added a check if ($headers[0]->seen == 0) { before fetching mail details In this method i first get all the results using ALL in imap_search. Then i filter out the results using the seen parameter of array returned by imap_fetch_overview

    The corrected code:

    <?php
    // Connect to the mail server
    $mailbox = imap_open('{your_email_server:993/imap/ssl}', 'your_username', 'your_password');
    
    if (!$mailbox) {
        echo 'Failed to connect to the mail server.';
        exit;
    }
    
    // Fetch all emails
    $emailIds = imap_search($mailbox, 'ALL');
    
    if ($emailIds === false) {
        echo 'Failed to fetch the emails.';
        exit;
    }
    
    // Iterate through each email
    foreach ($emailIds as $emailId) {
        // Fetch the email overview
        $overview = imap_fetch_overview($mailbox, $emailId, 0);
    
        // Check if the email is unseen
        if ($overview[0]->seen == 0) {
            // Email is unseen, process it
    
            // Mark the email as read manually
            imap_setflag_full($mailbox, $emailId, '\\Seen');
    
            // Process the email content
            $message = imap_fetchbody($mailbox, $emailId, 1.2); // Assuming the content is in MIME format
    
            // Process the content as needed
            // ...
    
            // Print the content
            echo $message;
        }
    }
    
    // Close the mailbox
    imap_close($mailbox);
    ?>