Commit 1f880a39 authored by Matthias Larisch's avatar Matthias Larisch Committed by Matthias Larisch

Add bounce processing library and support code

parent fda5ef9f
......@@ -14,7 +14,6 @@
"sebastian/diff": "^3.0.1"
},
"require": {
"sentry/sentry": "^1.10.0",
"mobiledetect/mobiledetectlib": "^2.8.33",
"maximebf/debugbar": "^1.15.0",
"guiguiboy/php-cli-progress-bar": "^0.0.4",
......@@ -22,28 +21,13 @@
"setasign/fpdi-fpdf": "^2.1.0",
"erusev/parsedown": "^1.7.1",
"fzaninotto/faker": "^1.8.0",
"symfony/dependency-injection": "^4.1.8",
"symfony/config": "^4.1.8",
"symfony/http-foundation": "^4.1.8",
"twig/twig": "^2.5.0",
"ddeboer/imap": "^1.5.5",
"symfony/form": "^4.1.9",
"symfony/twig-bridge": "^4.1.8",
"symfony/validator": "^4.1.8",
"symfony/translation": "^4.1.8",
"symfony/expression-language": "^4.1.8",
"doctrine/annotations": "^1.6.0",
"doctrine/cache": "^1.8.0",
"intervention/image": "^2.4.2",
"twig/extensions": "^1.5.3",
"symfony/yaml": "^4.1.8",
"symfony/framework-bundle": "^4.1.8",
"symfony/http-kernel": "^4.1.8",
"friendsofsymfony/rest-bundle": "^2.4.0",
"symfony/debug": "^4.1.8",
"jms/serializer-bundle": "^2.4.2",
"mrclay/jsmin-php": "^2.3.2",
"sensio/framework-extra-bundle": "^5.2.2",
"exercise/htmlpurifier-bundle": "^1.0.0",
"ext-json": "*",
"ext-pdo": "*",
......@@ -56,7 +40,25 @@
"ext-openssl": "*",
"ext-intl": "*",
"influxdb/influxdb-php": "^1.14.7",
"symfony/console": "^4.2"
"localheinz/composer-normalize": "^1.1.1",
"mrclay/jsmin-php": "^2.4.0",
"sensio/framework-extra-bundle": "^5.2.4",
"sentry/sentry": "^1.10.0",
"symfony/config": "4.1.9",
"symfony/console": "^4.2.2",
"symfony/dependency-injection": "4.1.9",
"symfony/expression-language": "4.1.9",
"symfony/form": "4.1.9",
"symfony/framework-bundle": "4.1.9",
"symfony/http-foundation": "4.1.9",
"symfony/http-kernel": "4.1.9",
"symfony/translation": "4.1.9",
"symfony/twig-bridge": "4.1.9",
"symfony/validator": "4.1.9",
"symfony/yaml": "^4.2.2",
"twig/extensions": "^1.5.4",
"twig/twig": "^2.6.0",
"voku/bounce-mail-handler": "^6.0"
},
"autoload": {
"psr-4": {"Foodsharing\\": "src/",
......
This diff is collapsed.
......@@ -47,6 +47,11 @@ define('IMAP', [
['host' => 'imap', 'user' => 'user', 'password' => 'pass']
]);
define('BOUNCE_IMAP_HOST', null);
define('BOUNCE_IMAP_USER', null);
define('BOUNCE_IMAP_PASS', null);
define('BOUNCE_IMAP_PORT', null);
if (!defined('ROOT_DIR')) {
define('ROOT_DIR', './');
}
......@@ -43,6 +43,11 @@ define('SOCK_URL', 'http://chat:1338/');
define('REDIS_HOST', 'redis');
define('REDIS_PORT', 6379);
define('BOUNCE_IMAP_HOST', null);
define('BOUNCE_IMAP_USER', null);
define('BOUNCE_IMAP_PASS', null);
define('BOUNCE_IMAP_PORT', null);
if (!defined('ROOT_DIR')) {
define('ROOT_DIR', './');
}
......@@ -144,3 +144,15 @@ services:
factory: ['InfluxDB\Client', 'fromdsn']
arguments:
- !php/const INFLUX_DSN
BounceMailHandler\BounceMailHandler:
properties:
disableDelete: true
mailhost: !php/const BOUNCE_IMAP_HOST
mailboxUserName: !php/const BOUNCE_IMAP_USER
mailboxPassword: !php/const BOUNCE_IMAP_PASS
port: !php/const BOUNCE_IMAP_PORT
service: 'imap'
serviceOption: 'tls'
boxname: 'INBOX'
maxMessages: 20
CREATE TABLE IF NOT EXISTS `fs_email_bounces` (
`email` VARCHAR(255) NOT NULL,
`bounced_at` DATETIME NOT NULL,
`bounce_type` VARCHAR(255) NOT NULL
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
ALTER TABLE `fs_email_bounces` ADD index `email` (email);
<?php
namespace Foodsharing\Command;
use Foodsharing\Lib\Mail\BounceProcessing;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ProcessBounceMailsCommand extends Command
{
protected static $defaultName = 'foodsharing:process-bounce-emails';
private $bounceProcessing;
public function __construct(BounceProcessing $bounceProcessing)
{
$this->bounceProcessing = $bounceProcessing;
parent::__construct();
}
protected function configure(): void
{
$this->setDescription('fetches email bounces and stores them in the database');
}
protected function execute(InputInterface $input, OutputInterface $output): void
{
$this->bounceProcessing->process();
$output->writeln('processed ' . $this->bounceProcessing->getNumberOfProcessedBounces() . ' bounces');
}
}
<?php
namespace Foodsharing\Lib\Mail;
use BounceMailHandler\BounceMailHandler;
use Foodsharing\Modules\Email\EmailGateway;
class BounceProcessing
{
private $bounceMailHandler;
private $emailGateway;
private $numBounces;
public function __construct(BounceMailHandler $bounceMailHandler, EmailGateway $emailGateway)
{
$this->bounceMailHandler = $bounceMailHandler;
$this->emailGateway = $emailGateway;
$this->numBounces = 0;
}
public function process()
{
$this->bounceMailHandler->actionFunction = [$this, 'handleBounce'];
$this->bounceMailHandler->openMailbox();
$this->bounceMailHandler->processMailbox();
/* catch errors/notices that would otherwise fall through */
imap_errors();
}
public function getNumberOfProcessedBounces()
{
return $this->numBounces;
}
public function handleBounce($msgnum, $bounceType, $email, $subject, $xheader, $remove, $ruleNo = false, $ruleCat = false, $totalFetched = 0, $body = '', $headerFull = '', $bodyFull = '')
{
if ($bounceType !== false) {
$this->emailGateway->addBounceForMail($email, $ruleCat, new \DateTime());
++$this->numBounces;
}
}
}
......@@ -157,4 +157,13 @@ class EmailGateway extends BaseGateway
return $row;
}
public function addBounceForMail($email, $category, \DateTime $time)
{
$this->db->insert('fs_email_bounces', [
'email' => $email,
'bounce_category' => $category,
'bounced_at' => $time->format('Y-m-d H:i:s')
]);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment