3

I'm working on a PHP script that periodically checks the user's inbox for new messages via IMAP. The script leaves an open connection to the IMAP server, and grabs the UID of the most recent message every 5 seconds. If the UID is greater than the initially recorded comparison UID, the script sends a push notification to the user's iPhone notifying him/her that there is a new message available, records the new UID as the comparison UID, and continues to check for new messages in this fashion. Here is the script:

<?php
$server = '{imap.gmail.com:993/ssl}';
$login = 'email_address@gmail.com';
$password = 'my_email_password';
$connection = imap_open($server, $login, $password) OR die ("can't connect: " . imap_last_error());

$imap_obj = imap_check($connection);
$number = $imap_obj->Nmsgs;
$uid = imap_uid($connection, $number);


//infinite loop, need to add some sort of escape condition...
for(;;){

$imap_obj = imap_check($connection);
$number = $imap_obj->Nmsgs;

    //if there is a new message send push notification
    if(imap_uid($connection, $number) > $uid){

    $uid = imap_uid($connection, $number);
    

$result = imap_fetch_overview($connection,$number,0);

$message = $result[0]->subject;
                

                $deviceToken = 'xxxxxxxxxxxxxxxxxx';
                $passphrase = 'my_secret_password';

                $ctx = stream_context_create();
                stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
                stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
                
                $fp = stream_socket_client(
                    'ssl://gateway.sandbox.push.apple.com:2195', $err,
                    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
                
                if (!$fp)
                    exit("Failed to connect: $err $errstr" . PHP_EOL);
                
                echo 'Connected to APNS' . PHP_EOL;
                
                // Create the payload body
                $body['aps'] = array(
                    'alert' => $message,
                    'sound' => 'default'
                    );
                
                // Encode the payload as JSON
                $payload = json_encode($body);
                
                // Build the binary notification
                $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
                
                // Send it to the server
                $result = fwrite($fp, $msg, strlen($msg));
                
                if (!$result)
                    //echo 'Message not delivered' . PHP_EOL;
                else
                    //echo 'Message successfully delivered' . PHP_EOL;
                
                // Close the connection to the server
                fclose($fp);
                
    }

sleep(5);
}

imap_close($connection);
?>

This works. But it seems terribly inefficient to me. Each additional user maintains an indefinite connection with the IMAP server, and checks for new messages every couple seconds, which seems silly.

Is there a better way to do this?

James
  • 2,272
  • 1
  • 21
  • 31

1 Answers1

0

Couldnt you use something like CRON to schedule a script to run every 30 seconds, which keeps a db record of the last UID for every user, and then searches each users mailbox locally (via local shell not imapd connection), if a particular user has a new message, push the notification and update the latest UID for that user in the DB...

This is assuming the PHP script is living on the mail server and you have root access.

Rick Kukiela
  • 1,135
  • 1
  • 15
  • 34
  • PHP script is on a separate server. Mail server, in this case, is GMail. – James Aug 01 '12 at 19:34
  • isnt there already a gmail app for iphone with push notifications built in? though I'm sure you have your reasons for needing this... though I cant think of any other way to do this than you are already doing it. – Rick Kukiela Aug 01 '12 at 19:36
  • There is indeed a Gmail app with push notifications. I'm not trying to connect exclusively with Gmail, however. That was just the example I used in the script. Thanks for your help. – James Aug 01 '12 at 19:39