Created
April 26, 2018 19:15
-
-
Save mashiox/673bd3b8b5f3ee22e6cb0f71dff524ed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Example usage: | |
* | |
* // Initalize the client | |
* $imap = DIOIMAP::init(); | |
* | |
* // Initalize the email client without a postfix and search for the latest unread email | |
* $emailMessage = DIOIMAP::init()->findEmail(); | |
* | |
* // Reinitalize the stream, and find the latest email with the subject "Test 123" | |
* $secondEmail = $imap->reinit()->findEmail("Test 123"); | |
* | |
* // Occasionally, the stream needs to be reset if the instance has done nothing for a while | |
* $imap = $imap->reinit(); | |
* $imap->reinit()->findEmail(); | |
* | |
*/ | |
class DIOIMAP { | |
const _IMAP_HOST = '{imap.gmail.com:993/imap/ssl/novalidate-cert}INBOX'; | |
private $imapStream; | |
private $user; | |
private $password; | |
private $expectedRecipient; | |
private $subject; | |
private $latestId; | |
private static $lastPostfix = ''; | |
/** | |
* Bootstrap a DIOIMAP object | |
* @param $postfix (string) RFC 2822 email tag ex: $postfix = "testTag" -> $expectedRecipient = "myGmailAcct+testTag@gmail.com" | |
*/ | |
public static function init($postfix = '') | |
{ | |
$key = 'myGmailAcct%s@gmail.com'; | |
$user = sprintf($key, ""); | |
$expectedRecipient = empty($postfix) ? $user : sprintf($key, "+$postfix"); | |
self::$lastPostfix = $postfix; | |
return new self($user, 'password!@', $expectedRecipient); | |
} | |
/** | |
* @param $user (string) IMAP Server username | |
* @param $pass (string) IMAP Server password | |
* @param $expectedRecipient (string) Expected recipient (in the "TO" field) of a set of email in the inbox | |
*/ | |
public function __construct($user, $pass, $expectedRecipient) | |
{ | |
date_default_timezone_set("UTC"); | |
$this->user = $user; | |
$this->password = $pass; | |
$this->expectedRecipient = $expectedRecipient; | |
$this->openConnection(); | |
} | |
private static $TEMP_lastDate; | |
/** | |
* Return the latest email id meeting the specified recipient and subject criteria | |
* @param $iteration (int) OPTIONAL The number used to identify the recursive position | |
* @param $maxDepth (int) OPTIONAL The number used to limit the recursive depth. | |
* @throws Exception No new emails found matching search criteria | |
* @return (int) IMAP server id of the found email | |
*/ | |
private function refresh($iteration = 0, $maxDepth = 5) | |
{ | |
$theNow = new DateTime(); | |
$emailStack = imap_search( | |
$this->imapStream, | |
sprintf("TO %s %s UNSEEN NEW", | |
$this->expectedRecipient, | |
empty($this->subject) ? "" : sprintf('SUBJECT "%s"', $this->subject) | |
), | |
SE_UID | |
); | |
$this->close(); | |
$this->openConnection(); | |
var_dump("Returned Email Stack"); | |
var_dump($emailStack); | |
if (!$emailStack) | |
{ | |
if ($iteration < $maxDepth) | |
{ | |
sleep(10); | |
var_dump($this->imapStream); | |
var_dump("Iteration: $iteration"); | |
var_dump("Time diff:\n"); | |
var_dump(self::$TEMP_lastDate->diff($theNow)->format("%h:%i:%s")); | |
var_dump("\n\n"); | |
self::$TEMP_lastDate = $theNow; | |
$this->refresh($iteration+1, $maxDepth); | |
} | |
throw new Exception( | |
sprintf( | |
"No new emails found matching criteria: user=%s subject=%s attempt=%s depth=%s", | |
$this->expectedRecipient, | |
$this->subject, | |
$iteration, | |
$maxDepth | |
) | |
); | |
} | |
$this->latestId = array_pop($emailStack); // Get latest email only | |
// foreach($emailStack as $mailId) | |
// { | |
// imap_clearflag_full($this->imapStream, $mailId, "//Seen"); | |
// } | |
return $this->latestId; | |
} | |
/** | |
* Find and return the latest email meeting the specified recipient and subject criteria | |
* @return (string) The email body | |
*/ | |
public function findEmail($subject = '') | |
{ | |
$this->subject = $subject; | |
self::$TEMP_lastDate = new DateTime(); | |
$this->refresh(0, 30); | |
$emailBody = $this->fetch($this->latestId); | |
$emailBody = $this->decode($emailBody); | |
return $emailBody; | |
} | |
public function reinit() | |
{ | |
$this->close(); | |
return self::init(self::$lastPostfix); | |
} | |
/** | |
* Close the connection to the IMAP server | |
*/ | |
public function close() | |
{ | |
imap_close($this->imapStream); | |
} | |
/** | |
* Return the expected recipient | |
* @return (string) The expected recipient | |
*/ | |
public function getRecipient() | |
{ | |
return $this->expectedRecipient; | |
} | |
private function decode($emailBody) | |
{ | |
$structure = imap_fetchstructure($this->imapStream, $this->latestId); | |
switch ($structure->encoding) | |
{ | |
case 3: | |
$emailBody = imap_base64($emailBody); | |
break; | |
case 4: | |
case 0: | |
$emailBody = imap_qprint($emailBody); | |
break; | |
default: | |
throw new Exception( | |
sprintf("Unknown encoding of email body encoding=%s", $structure->encoding) | |
); | |
} | |
return $emailBody; | |
} | |
private function openConnection() | |
{ | |
$this->imapStream = imap_open(self::_IMAP_HOST, $this->user, $this->password); | |
if (!$this->imapStream) throw new Exception("Cannot connect to " . self::_IMAP_HOST); | |
} | |
private function fetch($msgNumber) | |
{ | |
return imap_fetchbody($this->imapStream, $msgNumber, "2", FT_UID); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment