forked from remp2020/remp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMailgunEventsCommand.php
125 lines (102 loc) · 4.63 KB
/
MailgunEventsCommand.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
namespace Remp\MailerModule\Commands;
use Mailgun\Model\Event\EventResponse;
use Nette\Utils\DateTime;
use Remp\MailerModule\Mailer\MailgunMailer;
use Remp\MailerModule\Repository\LogsRepository;
use Remp\MailerModule\Sender\MailerFactory;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MailgunEventsCommand extends Command
{
const WAIT_SECONDS = 15;
const INTENTIONAL_DELAY_SECONDS = 60;
/** @var MailgunMailer */
private $mailgun;
private $logsRepository;
public function __construct(
MailerFactory $mailerFactory,
LogsRepository $logsRepository
) {
parent::__construct();
$this->mailgun = $mailerFactory->getMailer('remp-mailgun');
$this->logsRepository = $logsRepository;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('mailgun:events')
->setDescription('Syncs latest mailgun events with local log')
->addArgument('now', InputArgument::OPTIONAL, 'Offset from "now" of the first event to be processed in seconds', '30');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$nowOffset = $input->getArgument('now');
$output->writeln('');
$output->writeln('<info>***** SYNCING MAILGUN EVENTS *****</info>');
$output->writeln('');
$dateTo = (new \DateTime())
->sub(new \DateInterval(sprintf("PT%dS", self::INTENTIONAL_DELAY_SECONDS)));
$dateFrom = (clone $dateTo)->sub(new \DateInterval(sprintf("PT%dS", $nowOffset)));
$eventResponse = $this->getEvents($dateFrom, $dateTo);
$latestEventTime = $dateFrom;
while (true) {
$events = $eventResponse->getItems();
if (count($events) == 0) {
$output->writeln(sprintf("%s: all events processed, waiting for %d seconds before proceeding", new DateTime(), self::WAIT_SECONDS));
sleep(self::WAIT_SECONDS);
$dateTo = (new \DateTime())
->sub(new \DateInterval(sprintf("PT%dS", self::INTENTIONAL_DELAY_SECONDS)));
$eventResponse = $this->getEvents($latestEventTime, $dateTo);
continue;
}
/** @var \Mailgun\Model\Event\Event $event */
foreach ($events as $event) {
$userVariables = $event->getUserVariables();
$date = $event->getEventDate();
if ($date > $latestEventTime) {
$latestEventTime = $date;
}
$eventTimestamp = explode('.', $event->getTimestamp())[0];
$date = DateTime::from($eventTimestamp);
if (!isset($userVariables['mail_sender_id'])) {
// cannot map to logsRepository instance
$output->writeln(sprintf("%s: ignoring event: %s (unsupported)", $date, $event->getEvent()));
continue;
}
$mappedEvent = $this->logsRepository->mapEvent($event->getEvent(), $event->getReason());
if (!$mappedEvent) {
// unsupported event type
$output->writeln(sprintf("%s: ignoring event: %s (unsupported)", $date, $event->getEvent()));
continue;
}
$updated = $this->logsRepository->getTable()->where([
'mail_sender_id' => $userVariables['mail_sender_id'],
])->update([
$mappedEvent => $date,
'updated_at' => new DateTime(),
]);
if (!$updated) {
$output->writeln(sprintf("%s: event ignored, missing mail_logs record: %s (%s)", $date, $event->getRecipient(), $event->getEvent()));
} else {
$output->writeln(sprintf("%s: event processed: %s (%s)", $date, $event->getRecipient(), $event->getEvent()));
}
}
$eventResponse = $this->mailgun->mailer()->events()->nextPage($eventResponse);
};
}
private function getEvents(\DateTime $begin, \DateTime $end): EventResponse
{
/** @var EventResponse $eventResponse */
return $this->mailgun->mailer()->events()->get($this->mailgun->option('domain'), [
'ascending' => true,
'begin' => $begin->getTimestamp(),
'end' => $end->getTimestamp(),
'event' => implode(' OR ', $this->logsRepository->mappedEvents()),
]);
}
}