%PDF- %PDF-
Direktori : /www/varak.net/dmarc.varak.net/utils/ |
Current File : //www/varak.net/dmarc.varak.net/utils/summary_report.php |
<?php /** * dmarc-srg - A php parser, viewer and summary report generator for incoming DMARC reports. * Copyright (C) 2020-2025 Aleksey Andreev (liuch) * * Available at: * https://github.com/liuch/dmarc-srg * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. * * ========================= * * This script creates a summary report and sends it by email. * The email addresses must be specified in the configuration file. * The script have two required parameters: `domain` and `period`, * and five optional: `offset`, `emailto`, `format`, `user`, `subject`. * The `domain` parameter must contain a domain name, a comma-separated list of domains, or `all`. * The `period` parameter must have one of these values: * `lastmonth` - to make a report for the last month; * `lastweek` - to make a report for the last week; * `lastndays:N` - to make a report for the last N days; * The `offset` parameter is optional. It is intended to be used in conjunction with the `period` parameter * and allows you to specify a date range offset to the past. Must be the number days, weeks or months * for `lastNDays`, `lastWeek` and `lastMonth` respectively. The default value is 0. * The `emailto` parameter is optional. Set it if you want to use a different email address to sent the report to. * The `format` parameter is optional. It provides the ability to specify the email message format. * Possible values are: `text`, `html`, `text+html`. The default value is `text`. * The `user` parameter is optional. It can be useful for specifying a list of assigned domains for a single user * when the `domain` options is set to `all`. Only makes sense if the user_management mode is active. * The default value is `admin`. * The `subject` parameter is optional. It allows you to specify the subject line of the summary report message * instead of the default subject line. Remember to escape spaces and special characters! * * Some examples: * * $ php utils/summary_report.php domain=example.com period=lastweek * will send a summary report for the last week for the domain example.com via email * * $ php utils/summary_report.php domain=example.com period=lastweek offset=1 * will send a summary report for the week before last week for the domain example.com via email * * $ php utils/summary_report.php domain=example.com period=lastndays:10 "subject:My cool summary report" * will send a summary report for last 10 days for the domain example.com via email with the specified subject line * * $ php utils/summary_report.php domain=all user=frederick1 period=lastmonth emailto=frederick@example.com * will send a summary report for the last month for all domains assigned to user frederick1 to frederick@example.com. * * The best place to use it is cron. * * @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\Mailer; use Liuch\DmarcSrg\Mail\MailBody; use Liuch\DmarcSrg\Domains\Domain; use Liuch\DmarcSrg\Domains\DomainList; use Liuch\DmarcSrg\Report\SummaryReport; use Liuch\DmarcSrg\Report\OverallReport; use Liuch\DmarcSrg\Exception\SoftException; use Liuch\DmarcSrg\Exception\RuntimeException; require realpath(__DIR__ . '/..') . '/init.php'; if (Core::isWEB()) { echo 'Forbidden'; exit(1); } if (!isset($argv)) { echo 'Cannot get the script arguments. Probably register_argc_argv is disabled.', PHP_EOL; exit(1); } $domain = null; $all_dom = false; $period = null; $offset = '0'; $emailto = null; $format = 'text'; $uname = null; $acount = count($argv); $subject = ''; if ($acount <= 1) { echo "Usage: {$argv[0]} domain=<domains>|all", PHP_EOL; echo ' period=lastmonth|lastweek|lastndays:<days>', PHP_EOL; echo ' [offset=<days>] [format=text|html|text+html]', PHP_EOL; echo ' [emailto=<email address>] [user=<username>]', PHP_EOL; exit(1); } for ($i = 1; $i < $acount; ++$i) { $av = explode('=', $argv[$i]); if (count($av) == 2) { switch ($av[0]) { case 'domain': $domain = $av[1]; break; case 'period': $period = $av[1]; break; case 'offset': $offset = $av[1]; break; case 'emailto': $emailto = $av[1]; break; case 'format': $format = $av[1]; break; case 'user': $uname = $av[1]; break; case 'subject': $subject = $av[1]; break; } } } $core = Core::instance(); try { $core->setCurrentUser($uname ?? 'admin'); if (!$domain) { throw new SoftException('Parameter "domain" is not specified'); } if (!$period) { throw new SoftException('Parameter "period" is not specified'); } if (filter_var($offset, FILTER_VALIDATE_INT, [ 'options' => [ 'min_range' => 0 ] ]) === false) { throw new SoftException('Parameter "offset" must be a positive integer'); } if (!in_array($format, [ 'text', 'html', 'text+html' ], true)) { throw new SoftException('Unknown email message format: ' . $format); } if (!$emailto) { $emailto = $core->config('mailer/default', ''); } if ($domain === 'all') { $domains = (new DomainList($core->getCurrentUser()))->getList()['domains']; $all_dom = true; } else { $domains = array_map(function ($d) { return new Domain($d); }, explode(',', $domain)); } $rep = new SummaryReport($period, intval($offset)); switch ($format) { case 'text': $text = []; $html = null; break; case 'html': $text = null; $html = []; break; default: $text = []; $html = []; break; } $dom_cnt = count($domains); if ($dom_cnt == 0) { throw new SoftException('The user has no assigned domains'); } $overall = null; if ($dom_cnt > 1) { $overall = new OverallReport(); $rep->bindSection($overall); } $add_sep = function () use (&$text, &$html) { if (!is_null($text)) { $text[] = '-----------------------------------'; $text[] = ''; } if (!is_null($html)) { $html[] = '<hr style="margin:2em 0;" />'; } }; $rep_cnt = 0; $err_cnt = 0; for ($i = 0; $i < $dom_cnt; ++$i) { $domain = $domains[$i]; if ($domain->isAssigned($core->getCurrentUser())) { $rep->setDomain($domain); if (!$all_dom || $domain->active() || !$rep->isEmpty()) { if ($rep_cnt || $err_cnt) { $add_sep(); } if (!is_null($text)) { foreach ($rep->text() as &$row) { $text[] = $row; } unset($row); } if (!is_null($html)) { foreach ($rep->html() as &$row) { $html[] = $row; } unset($row); } ++$rep_cnt; } else { $overall->removeRow($domain); } } else { if ($rep_cnt || $err_cnt) { $add_sep(); } $nf_message = "Domain \"{$domain->fqdn()}\" does not exist"; if ($dom_cnt === 1) { throw new SoftException($nf_message); } if (!is_null($text)) { $text[] = "# {$nf_message}"; $text[] = ''; } if (!is_null($html)) { $html[] = '<h2>' . htmlspecialchars($nf_message) . '</h2>'; } ++$err_cnt; } } if (!is_null($text)) { if (!$rep_cnt && !$err_cnt) { $text[] = 'There are no active domains'; } elseif ($overall) { $text = array_merge($overall->text(), [ '-----------------------------------', '' ], $text); } } if (!is_null($html)) { if (!$rep_cnt && !$err_cnt) { $html[] = '<p>There are no active domains</p>'; } elseif ($overall) { $html = array_merge($overall->html(), [ '<hr style="margin:2em 0;" />' ], $html); } } $mbody = new MailBody(); $mbody->text = $text; $mbody->html = $html; $mailer = Mailer::get($core->config('mailer', [])); $mailer->setFrom($core->config('mailer/from', '')); $mailer->addAddress($emailto); if (!empty($subject)) { $mailer->setSubject($subject); } elseif ($dom_cnt === 1) { $mailer->setSubject("{$rep->subject()} for {$domain->fqdn()}"); } elseif ($uname && $all_dom) { $mailer->setSubject("{$rep->subject()} for {$uname}'s domains"); } else { $dom_cnt = $rep_cnt + $err_cnt; $mailer->setSubject("{$rep->subject()} for {$dom_cnt} domains"); } $mailer->setBody($mbody); $mailer->send(); } catch (SoftException $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; exit(1); } catch (RuntimeException $e) { echo ErrorHandler::exceptionText($e); exit(1); } exit(0);