@@ -168,6 +168,8 @@ class Hm_IMAP extends Hm_IMAP_Cache {
168
168
public $ folder_state = false ;
169
169
private $ scramAuthenticator ;
170
170
private $ namespace_count = 0 ;
171
+
172
+ private $ last_processed_message_number = 0 ;
171
173
/**
172
174
* constructor
173
175
*/
@@ -315,13 +317,136 @@ public function authenticate($username, $password) {
315
317
$ this ->debug [] = 'Logged in successfully as ' . $ username ;
316
318
$ this ->get_capability ();
317
319
$ 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
+ }
318
328
} else {
319
329
$ this ->debug [] = 'Log in for ' . $ username . ' FAILED ' ;
320
330
}
321
331
return $ authed ;
322
332
}
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
+ }
323
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
+ }
324
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
+ }
449
+
325
450
/**
326
451
* attempt starttls
327
452
* @return void
0 commit comments