@@ -168,6 +168,8 @@ class Hm_IMAP extends Hm_IMAP_Cache {
168168 public $ folder_state = false ;
169169 private $ scramAuthenticator ;
170170 private $ namespace_count = 0 ;
171+
172+ private $ last_processed_message_number = 0 ;
171173 /**
172174 * constructor
173175 */
@@ -315,11 +317,135 @@ public function authenticate($username, $password) {
315317 $ this ->debug [] = 'Logged in successfully as ' . $ username ;
316318 $ this ->get_capability ();
317319 $ this ->enable ();
320+
321+ // Check if the server supports IMAP IDLE
322+ if ($ this ->supports_idle ()) {
323+ $ this ->start_idle (); // Start IMAP IDLE command after successful authentication
324+ } else {
325+ $ this ->debug [] = 'IMAP IDLE not supported by the server. ' ;
326+ //TO DO: Implement polling mechanism
327+ }
318328 } else {
319329 $ this ->debug [] = 'Log in for ' . $ username . ' FAILED ' ;
320330 }
321331 return $ authed ;
322332 }
333+
334+ /**
335+ * Check if the server supports the IMAP IDLE extension.
336+ *
337+ * @return bool True if IDLE is supported, false otherwise.
338+ */
339+ private function supports_idle () {
340+ // Check if the CAPABILITY response includes "IDLE"
341+ return stripos ($ this ->capability , 'IDLE ' ) !== false ;
342+ }
343+
344+ /**
345+ * Start the IMAP IDLE process to listen for real-time updates from the server.
346+ */
347+ private function start_idle () {
348+ // Send the IDLE command to the server
349+ $ this ->send_command ("IDLE \r\n" );
350+
351+ // Keep listening for server responses while in IDLE mode
352+ while (true ) {
353+ $ lines = $ this ->get_response (); // Get server response
354+
355+ // Iterate through each line to check for new message indications
356+ foreach ($ lines as $ line ) {
357+ // Check for a new message indication from the server
358+ if (strpos ($ line , 'EXISTS ' ) !== false ) {
359+ // A new message has arrived, fetch and handle it
360+ $ this ->fetch_and_handle_new_messages ();
361+ }
362+
363+ // Exit IDLE mode if necessary
364+ if ($ this ->should_exit_idle ()) {
365+ // Send the DONE command to exit the IDLE state
366+ $ this ->send_command ("DONE \r\n" );
367+ break ;
368+ }
369+ }
370+ }
371+ }
372+
373+ // Fetch and handle new messages
374+ private function fetch_and_handle_new_messages () {
375+ // Get the current number of messages in the mailbox
376+ $ current_message_count = $ this ->get_message_count ();
377+
378+ // Determine the range of message numbers to check
379+ $ start_message_number = $ this ->last_processed_message_number + 1 ;
380+
381+ // Fetch and process each new message
382+ for ($ message_number = $ start_message_number ; $ message_number <= $ current_message_count ; $ message_number ++) {
383+ $ uid = $ this ->get_message_uid ($ message_number ); // Fetch UID for the message number
384+ $ this ->fetch_and_handle_message ($ uid );
385+ $ this ->last_processed_message_number = $ message_number ; // Update the last processed message number
386+ }
387+ }
388+
389+ /**
390+ * Fetch and handle the new message by its number.
391+ */
392+ private function fetch_and_handle_message ($ uid ) {
393+ // Fetch the full message content
394+ $ message_content = $ this ->get_message_content ($ uid , '1 ' ); // Fetch the entire message body
395+ // Process the message (e.g., parse content, send notifications)
396+ $ this ->handle_new_message ($ message_content );
397+ }
398+
399+ // Get the UID of a message by its number
400+ private function get_message_uid ($ message_number ) {
401+ // Use the FETCH command to get the UID of the message
402+ $ fetchCommand = "FETCH $ message_number (UID) \r\n" ;
403+ $ this ->send_command ($ fetchCommand );
404+ $ response = $ this ->get_response ();
405+
406+ foreach ($ response as $ line ) {
407+ if (preg_match ('/UID (\d+)/ ' , $ line , $ matches )) {
408+ return $ matches [1 ];
409+ }
410+ }
411+
412+ return '' ; // Return an empty string if UID is not found
413+ }
414+
415+ // Get the current number of messages in the mailbox
416+ private function get_message_count () {
417+ // Use the STATUS command to get the number of messages in the selected mailbox
418+ $ this ->send_command ("STATUS INBOX (MESSAGES) \r\n" );
419+ $ response = $ this ->get_response ();
420+
421+ foreach ($ response as $ line ) {
422+ if (preg_match ('/MESSAGES (\d+)/ ' , $ line , $ matches )) {
423+ return (int )$ matches [1 ];
424+ }
425+ }
426+
427+ return 0 ; // Fallback to 0 if unable to determine message count
428+ }
429+
430+ /**
431+ * Determine if the client should exit the IDLE state.
432+ *
433+ * @return bool True if the client should exit IDLE, false otherwise.
434+ */
435+ private function should_exit_idle () {
436+ // Placeholder function to determine when to exit the IDLE state
437+ // Implement logic to decide when to break out of the IDLE command
438+ return false ;
439+ }
440+
441+ /**
442+ * Handle the event when a new message arrives while in IDLE mode.
443+ */
444+ private function handle_new_message ($ messageData ) {
445+ // Process the new message data
446+ // Example: Extract headers, body, etc.
447+ // Notify via Telegram, SMS, etc.
448+ }
323449
324450
325451 /**
0 commit comments