Pagination for Mailgun events API
<?php
use Mailgun\Mailgun;
use Setting;
/**
* Pagination for Mailgun events API
* Retrieves all new (not have retrieved yet) events for each run
* See main code at processNewEvents()
*
* Used, but can be replaced by any implementation:
* "mailgun/mailgun-php": "^2.3",
* "anlutro/l4-settings": "^0.5.0",
*/
class EmailProcessor
{
/**
* Pagination step for api calls, max 300
* @var int
*/
private static $step = 300;
public function sendEmails()
{
$this->processNewEmails(function($response) {
/** @var \Mailgun\Model\Message\ShowResponse $response */
// any code what you want
// $response->getBodyPlain();
});
}
/**
* Make some action with all new inbounded emails
*
* @param \Closure $callback
*/
private function processNewEmails(\Closure $callback)
{
$this->processNewEvents(function($event) use($callback) {
/** @var \Mailgun\Model\Event\Event $event */
$storage = $event->getStorage();
if (empty($storage) ||empty($storage['url'])) {
return;
}
$mailgun = Mailgun::create(env('MAILGUN_SECRET'));
$response = $mailgun->messages()->show($storage['url']);
$callback($response);
}, 'stored');
}
/**
* Make some actions with all new events
*
* @param \Closure $callback
* @param string $type
*/
private function processNewEvents(\Closure $callback, $type)
{
$domain = env('MAILGUN_DOMAIN');
$mailgun = Mailgun::create(env('MAILGUN_SECRET'));
$latestEventOfPreviousRunSetting = 'latest_processed_mailgun_event_' . $type;
$latestEventOfPreviousRun = Setting::get($latestEventOfPreviousRunSetting, '0');
$begin = time();
$processed = [];
$latestEventIsWritten = false;
do {
$eventsResponse = $mailgun->events()
->get(
$domain,
[
'begin' => $begin,
'event' => $type,
'ascending' => 'no',
'limit' => self::$step,
]
);
$needToMakeNextApiStep = false;
foreach ($eventsResponse->getItems() as $event) {
//already processed last run
if ($latestEventOfPreviousRun === $event->getId()) {
break(2);
}
// because after the step of api pagination first part of current batch can contain the same events as previous
// it depends on crossing of events with the same timestamp (peculiarity of the mailgun API)
if (in_array($event->getId(), $processed)) {
continue;
}
$needToMakeNextApiStep = true;
$processed[] = $event->getId();
$begin = $event->getTimestamp();
if (!$latestEventIsWritten) {
Setting::set($latestEventOfPreviousRunSetting, $event->getId());
Setting::save();
$latestEventIsWritten = true;
}
$callback($event);
}
} while($needToMakeNextApiStep);
}
}