. * * ========================= * * This script fetches DMARC reports from mailboxes and server local directories and saves them to the DB. * The parameters of mailboxes and directories must be specified in the configuration file. * The mailboxes and directories accessibility can be checked on the administration page in the web interface. * The script has one optional parameter: `source` - the type of the source. The valid types are `email`, `directory`. * * Some examples: * $ utils/fetch_reports * will fetch reports from both the mailboxes and the local server directories. * * $ utils/fetch_reports source=email * will only fetch reports from the mailboxes. * * The best place to use it is cron. * Note: the current directory must be the one containing the classes directory. * * @category Utilities * @package DmarcSrg * @author Aleksey Andreev (liuch) * @license https://www.gnu.org/licenses/gpl-3.0.html GNU/GPLv3 */ namespace Liuch\DmarcSrg; use Liuch\DmarcSrg\Mail\MailBoxes; use Liuch\DmarcSrg\Report\ReportFetcher; use Liuch\DmarcSrg\Sources\Source; use Liuch\DmarcSrg\Sources\MailboxSource; use Liuch\DmarcSrg\Sources\DirectorySource; use Liuch\DmarcSrg\Directories\DirectoryList; use Liuch\DmarcSrg\Exception\RuntimeException; require 'init.php'; if (php_sapi_name() !== 'cli') { echo 'Forbidden'; exit(1); } $usage = false; $source = null; if (isset($argv)) { for ($i = 1; $i < count($argv); ++$i) { $av = explode('=', $argv[$i]); if (count($av) !== 2) { echo 'Invalid parameter format' . PHP_EOL; $usage = true; break; } switch ($av[0]) { case 'source': $source = $av[1]; break; default: echo 'Unknown parameter "' . $av[0] . '"' . PHP_EOL; $usage = true; break; } } if ($source && $source !== 'email' && $source !== 'directory') { echo 'Invalid source type "' . $source . '". "email" or "directory" expected.' . PHP_EOL; exit(1); } } if ($usage) { echo PHP_EOL; echo 'Usage: ' . basename(__FILE__) . ' [source=email|directory]' . PHP_EOL; exit(1); } $sou_list = []; $problems = []; $addError = function (\Throwable $e, array &$errors): void { $err_r = ErrorHandler::exceptionResult($e); $errors['messages'][] = $err_r['message']; if (!$errors['debug_info'] && isset($err_r['debug_info'])) { $errors['debug_info'] = $err_r['debug_info']['content']; } }; const MAILBOX_LIST = 1; const DIRECTORY_LIST = 2; const FETCHER = 3; $state = MAILBOX_LIST; if (!$source || $source === 'email') { $errors = [ 'messages' => [], 'debug_info' => null ]; $mb_list = new MailBoxes(); for ($mb_num = 1; $mb_num <= $mb_list->count(); ++$mb_num) { try { $sou_list[] = new MailboxSource($mb_list->mailbox($mb_num)); } catch (RuntimeException $e) { $addError($e, $errors); } } if (count($errors['messages']) > 0) { $problems[] = [ 'state' => $state, 'messages' => $errors['messages'], 'debug_info' => $errors['debug_info'] ]; } } $state = DIRECTORY_LIST; if (!$source || $source === 'directory') { $errors = [ 'messages' => [], 'debug_info' => null ]; foreach ((new DirectoryList())->list() as $dir) { try { $sou_list[] = new DirectorySource($dir); } catch (RuntimeException $e) { $addError($e, $errors); } } if (count($errors['messages']) > 0) { $problems[] = [ 'state' => $state, 'messages' => $errors['messages'], 'debug_info' => $errors['debug_info'] ]; } } $state = FETCHER; try { foreach ($sou_list as $source) { $results = (new ReportFetcher($source))->fetch(); foreach ($results as &$res) { $messages = []; if (isset($res['source_error'])) { $messages[] = $res['source_error']; } if (isset($res['post_processing_message'])) { $messages[] = $res['post_processing_message']; } if (isset($res['error_code']) && $res['error_code'] !== 0 && isset($res['message'])) { $messages[] = $res['message']; } if (count($messages) > 0) { $pr = [ 'state' => $state, 'messages' => $messages ]; foreach ([ 'report_id', 'emailed_from', 'emailed_date' ] as $it) { if (isset($res[$it])) { $pr[$it] = $res[$it]; } } if ($source->type() === Source::SOURCE_MAILBOX) { $cont = $source->container(); $pr['mailbox'] = $cont->mailbox() . ' (' . $cont->name() . ')'; } $problems[] = $pr; } } unset($res); } } catch (RuntimeException $e) { $problems[] = [ 'state' => $state, 'messages' => [ $e->getMessage() ] ]; } if (count($problems) > 0) { $debug_info = null; foreach ($problems as $i => $pr) { if ($i > 0) { echo PHP_EOL; } switch ($pr['state']) { case MAILBOX_LIST: echo 'Failed to get mailbox list:'; break; case DIRECTORY_LIST: echo 'Failed to get directory list:'; break; case FETCHER: echo 'Failed to get incoming report:'; break; } echo PHP_EOL; echo ' Error message:', PHP_EOL; $messages = array_map(function ($msg) { return " - {$msg}"; }, $pr['messages']); echo implode(PHP_EOL, $messages), PHP_EOL; if (isset($pr['report_id'])) { echo " Report ID: {$pr['report_id']}", PHP_EOL; } if (isset($pr['emailed_from']) || isset($pr['emailed_date']) || isset($pr['mailbox'])) { echo ' Email message metadata:', PHP_EOL; echo ' - From: ' . ($pr['emailed_from'] ?? '-'), PHP_EOL; echo ' - Date: ' . ($pr['emailed_date'] ?? '-'), PHP_EOL; echo ' - Mailbox: ' . ($pr['mailbox'] ?? '-'), PHP_EOL; } if (!$debug_info && !empty($pr['debug_info'])) { $debug_info = $pr['debug_info']; } } if ($debug_info) { echo PHP_EOL; echo 'Debug information:', PHP_EOL, $debug_info, PHP_EOL; } exit(1); } exit(0);