First we have to allow third parties to access your gmail.
Even I turn on “Less secure app access”, it still doesn’t work.
Workable solution is to turn on 2-step verification for your google account then set an app password, which you can find the config on the section “Signing in to Google”
Secondly, go to https://mail.google.com and click the setting icon then see all settings. press Forwarding and POP/IMAP on the top horizontal menu, click “Enable IMAP”
Gmail is ready for you to access, let’s code it!
composer require php-mail-client/client composer require ssilence/php-imap-client
Before we start, we download the above libraries using composer then we try to connect.
use SSilence\ImapClient\ImapClient as Imap;
use SSilence\ImapClient\ImapClientException;
try {
$imap = new Imap("imap.gmail.com", "yourname@gmail.com", "app-password", Imap::ENCRYPT_SSL);
} catch (ImapClientException $error) {
throw new InstagramAuthException('Login error. Cannot login to imap server: ' . $error->getMessage());
}
Try to get the count of unread messages in INBOX folder.
$imap->selectFolder("INBOX");
try {
$unreadMessages = $imap->countUnreadMessages();
var_dump('countUnreadMessages: ' . $unreadMessages);
} catch (ImapClientException $e) {
var_dump($e);
}
Try to search Criteria: UNSEEN, on today, from a specified email using imap_search and form an array storing the mails and their IDs.
$date = date("j F Y");
var_dump($date);
$result = imap_search($imap->getImap(), 'UNSEEN FROM "xxx@mail.xxx.com" ON "'.$date.'"');
$countId = count($result);
var_dump('countId: ' . $countId);
foreach($result as $key=>$id) {
//var_dump($id);
$emails[]= ['email'=>$imap->getMessage($id), 'id'=>$id];
}
var_dump($emails);
Why do we get the ID? because we can set the email to be read.
$imap->setSeenMessage($id);
Here I have a completed source code to keep checking the email and stop once I receive a special email with a verification code inside the email.
<?php
require __DIR__ . '/vendor/autoload.php';
use SSilence\ImapClient\ImapClient as Imap;
use SSilence\ImapClient\ImapClientException;
const MAIL_MAX_WAIT_TIME = 600;
const MAIL_WAIT_STEP_TIME = 10;
try {
$imap = new Imap("imap.gmail.com", "user@gmail.com", "app-password", Imap::ENCRYPT_SSL);
echo keepChecking($imap);
} catch (ImapClientException $error) {
throw new InstagramAuthException('Login error. Cannot login to imap server: ' . $error->getMessage());
}
function keepChecking($imap) {
$startTime = time();
while (time() - $startTime < MAIL_MAX_WAIT_TIME) {
sleep(mt_rand(60,MAIL_WAIT_STEP_TIME*60)/60);
try {
$code = getCodeFromEmail($imap);
} catch (ImapClientException $e) {
break;
}
if ($code) return $code;
sleep(MAIL_WAIT_STEP_TIME);
}
throw new InstagramAuthException('Login error. Verification email read timeout.');
}
function searchEmail($imap) {
$date = date("j F Y");
var_dump($date);
$result = imap_search($imap->getImap(), 'UNSEEN FROM "from@mail.com" ON "'.$date.'"');
$countId = count($result);
var_dump('countId: ' . $countId);
foreach($result as $key=>$id) {
//var_dump($id);
$emails[]= ['email'=>$imap->getMessage($id), 'id'=>$id];
}
return array_reverse($emails); //desc
}
function getCodeFromEmail($imap) {
$imap->selectFolder("INBOX");
try {
$unreadMessages = $imap->countUnreadMessages();
var_dump('countUnreadMessages: ' . $unreadMessages);
$code = false;
if ($unreadMessages) {
$emails = searchEmail($imap);
foreach ($emails as $mailWrap) {
$mail = $mailWrap['email'];
echo "{$mailWrap['id']} [{$mail->header->date}] ({$mail->header->from}) {$mail->header->subject}\n";
if ($mail->header->from !== 'Demo <from@mail.com>') {
continue;
}
$message = json_encode($mail->message);
if (preg_match('/>(\d{6})</', $message, $matches)) {
$code = $matches[1];
var_dump($code);
$imap->setSeenMessage($mailWrap['id']);
return $code;
}
}
}
} catch (ImapClientException $e) {
var_dump($e);
}
}