mirror of
https://github.com/domainaware/parsedmarc.git
synced 2026-09-06 14:07:59 +00:00
* Make the output and mailbox integrations optional extras (#883) Breaking change for the next major release: pip install parsedmarc now installs the parsing core plus a working core CLI (file, IMAP, Maildir, and mbox input; CSV/JSON, Splunk HEC, webhook, and syslog output). Everything else moves behind an extra: elastic, opensearch, kafka, s3, gelf, loganalytics, msgraph, and gmail, joining the existing postgresql extra, with an umbrella [all] that deliberately excludes postgresql (psycopg's binary wheels do not exist on every platform, so parsedmarc[all] must never fail to install there). cli.py imports the six SDK-dependent output modules behind the #884 TYPE_CHECKING/try-except guard; a configured section whose extra is missing fails fast with a ConfigurationError naming the section and the exact pip install command — including the msgraph and gmail_api mailbox sections (detected via parsedmarc.mail's placeholder classes) and postgresql (checked before the constructor so the startup retry loop does not retry a missing dependency for a minute). The Azure/kiota Graph error types fall back to never-raised sentinel classes. The Docker image installs [all,postgresql], so container users see no change. CI lint installs [build,all,postgresql]; the unit-test job installs [build,all], deliberately without postgresql so test_postgres.py's absent-psycopg arm stays exercised. The never-imported dateparser dependency is dropped in favor of declaring python-dateutil, which utils.py actually imports; pytz moves to the build extra for the one test that uses it. Verified live: a no-extras wheel install imports, parses samples, and reports the install hint for each gated section; a [all] install restores every integration; the Docker image builds with every SDK importable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Patch psycopg presence in the PostgreSQL CLI wiring tests CI's unit-test job deliberately installs [build,all] without the postgresql extra, so parsedmarc.cli.postgres.psycopg is None there and the new missing-extra presence check correctly made _main exit 1 before the wiring under test ran. The tests simulate the SDK being available (PostgreSQLClient is mocked at the SDK boundary), so the module-level psycopg handle is now patched present in setUp. Verified against a simulated psycopg-absent environment as well as the local full install. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Address Copilot review: narrow guards to ModuleNotFoundError, fix docs - The optional-integration and Graph error-type import guards now catch ModuleNotFoundError instead of ImportError, so only a genuinely absent package reads as a missing extra; a broken-but-present SDK fails loudly with its real error instead of masquerading as one. The test blocker raises ModuleNotFoundError accordingly — the exact exception a missing package produces. - _missing_extra_hint docstring no longer calls every gated integration an output module (it also serves the msgraph/gmail_api mailbox sections). - Fix the pre-existing passsword typo in usage.md's kafka section; the INI key the code reads is password (cli.py _parse_config). Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Quote extras specs in copy-paste install commands From Copilot's second review round: zsh treats an unquoted .[build,all] as a glob and fails with 'no matches found', so the commands shown in AGENTS.md, CONTRIBUTING.md, dashboards/README.md, and the bootstrap script's comment are now quoted. The CI workflows keep the unquoted form: they run under bash, which passes unmatched globs through literally. The suggestion to change the 'Choosing what to install' heading level was rejected — it is a subsection of 'Installing parsedmarc', matching the file's existing hierarchy. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Fix upgrade command in the changelog * Documentation review: accuracy, spelling, grammar, and clarity pass A full prose review of docs/source, README, CONTRIBUTING, and the dashboards README, with every accuracy claim verified against the code before changing it. Highlights: - usage.md: documented six missing [general] options (the CSV/JSON filename options, prettify_json, normalize_timespan_threshold_hours), the required kafka smtp_tls_topic, [imap] timeout/max_retries, and the postgresql env-var prefix; corrected the maildir_path default (None, not INBOX — cli.py Namespace defaults), the mailbox check_timeout option name, the systemd restart interval (RestartSec is 5m), and merged the duplicate silent entry; quoted every copy-paste extras spec for zsh safety. - elasticsearch.md: fixed an invalid openssl command (rsa:4096 -nodes), the dashboards filename (opensearch_dashboards.ndjson, matching the file the link serves), and assorted grammar. - davmail.md: the service-enable command now enables davmail.service (was parsedmarc.service — a copy-paste error that left DavMail unenabled), plus a view typo and DavMail capitalization. - output.md: the example schema reference is RFC 7489 Appendix C (7480 is RDAP). kibana.md: SPF relies on the SMTP envelope, not session headers (RFC 7208). dmarc.md: DKM -> DKIM. - README: the intro now also names the OpenSearch/Grafana stack, matching the feature list. CONTRIBUTING: pre-PR checks now include ruff format --check and pyright, matching CI's lint job. - dashboards/README: the service table and seed description now include the PostgreSQL backend the compose stack runs. Sample data blocks, the CLI-help mirror block, and released CHANGELOG entries were deliberately left untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Docstring review: accuracy, spelling, grammar, and clarity pass Every docstring in parsedmarc/, parsedmarc/mail/, the maps maintainer scripts, and the test suite reviewed with each claim verified against the code it documents. Text-only — no behavior changes. Highlights: - Copy-paste errors corrected: parsed_smtp_tls_reports_to_csv and splunk/loganalytics save functions described aggregate or failure reports they do not handle; LogAnalyticsException claimed to be an Elasticsearch error. - Docstring/behavior mismatches: parse_report_email's report_type enumeration omitted smtp_tls; parse_failure_report typed msg_date as str (it is datetime); strip_attachment_payloads claimed payloads are replaced with None (the key is deleted); kafkaclient's failure and SMTP TLS savers claimed per-record slicing while sending the whole list in one message (docstrings now describe reality — whether slicing was intended is flagged for follow-up); the postgres savers claimed to take parse_report_file's return value but receive the inner report dict; elastic/opensearch save functions' Raises listed only AlreadySaved. - None-as-semantic-state documented where missing (get_base_domain, get_ip_address_country), enumeration completeness fixed (get_ip_address_info's 9 result keys, maps script outputs, TSV columns), and the stale 44-industry-types count corrected to the 46 the authoritative README list defines. - Test docstrings aligned with what the tests actually assert, including two that overstated coverage of the elastic/opensearch address-list tests. - Two argparse help strings fixed: file_path now names SMTP TLS report files alongside aggregate and failure, mirrored into usage.md's CLI-help block; --offline's doubled spaces removed (rendered help unchanged). - elasticsearch.md's security claim corrected against Elastic's docs: security is enabled and auto-configured on first startup since 8.0 (not "8.7 secure mode"), so the settings are verified, not hand-written. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
246 lines
8.6 KiB
Markdown
246 lines
8.6 KiB
Markdown
# Installation
|
|
|
|
## Prerequisites
|
|
|
|
`parsedmarc` works with Python 3 only.
|
|
|
|
### Testing multiple report analyzers
|
|
|
|
If you would like to test parsedmarc and another report processing
|
|
solution at the same time, you can have up to two `mailto` URIs in each of the rua and ruf
|
|
tags in your DMARC record, separated by commas.
|
|
|
|
### Using a web proxy
|
|
|
|
If your system is behind a web proxy, you need to configure your system
|
|
to use that proxy. To do this, edit `/etc/environment` and add your
|
|
proxy details there, for example:
|
|
|
|
```bash
|
|
http_proxy=http://user:password@prox-server:3128
|
|
https_proxy=https://user:password@prox-server:3128
|
|
ftp_proxy=http://user:password@prox-server:3128
|
|
```
|
|
|
|
Or if no credentials are needed:
|
|
|
|
```bash
|
|
http_proxy=http://prox-server:3128
|
|
https_proxy=https://prox-server:3128
|
|
ftp_proxy=http://prox-server:3128
|
|
```
|
|
|
|
This will set the proxy up for use system-wide, including for `parsedmarc`.
|
|
|
|
### Using Microsoft Exchange
|
|
|
|
If your mail server is Microsoft Exchange, ensure that it is patched to at
|
|
least:
|
|
|
|
- Exchange Server 2010 Update Rollup 22 ([KB4295699])
|
|
- Exchange Server 2013 Cumulative Update 21 ([KB4099855])
|
|
- Exchange Server 2016 Cumulative Update 11 ([KB4134118])
|
|
|
|
### IP-to-country database
|
|
|
|
`parsedmarc` ships with a copy of the [IPinfo Lite] database (under
|
|
the terms of the [Creative Commons Attribution-ShareAlike 4.0
|
|
License]), which is automatically refreshed from GitHub at startup
|
|
(and on `SIGHUP` in watch mode) unless the `offline` flag is set. No
|
|
IP database setup is required for the default configuration.
|
|
|
|
If you would prefer to use MaxMind's GeoLite2 Country database
|
|
instead, see [Using MaxMind GeoLite2](#using-maxmind-geolite2-optional)
|
|
below.
|
|
|
|
## Installing parsedmarc
|
|
|
|
On Debian or Ubuntu systems, run:
|
|
|
|
```bash
|
|
sudo apt-get install -y python3-pip python3-venv python3-dev libxml2-dev libxslt-dev
|
|
```
|
|
|
|
On CentOS, RHEL, or Rocky Linux systems, run:
|
|
|
|
```bash
|
|
sudo dnf install -y python3 python3-pip python3-devel libxml2-devel libxslt-devel
|
|
```
|
|
|
|
Python 3 installers for Windows and macOS can be found at
|
|
<https://www.python.org/downloads/>.
|
|
|
|
`parsedmarc` requires Python 3.10 or newer. If your distribution's
|
|
default `python3` is older, install a newer interpreter (e.g.
|
|
`python3.12`) and substitute it for `python3` in the commands below.
|
|
|
|
Create a dedicated system user, with `/opt/parsedmarc` as its home
|
|
directory so the directory is created with the correct ownership in
|
|
the same step
|
|
|
|
```bash
|
|
sudo useradd --system --create-home --home-dir /opt/parsedmarc \
|
|
--shell /usr/sbin/nologin --skel /dev/null parsedmarc
|
|
```
|
|
|
|
Create a virtualenv and install `parsedmarc` into it as that user, so
|
|
any files created later are also owned by `parsedmarc`
|
|
|
|
```bash
|
|
sudo -u parsedmarc python3 -m venv /opt/parsedmarc/venv
|
|
sudo -u parsedmarc /opt/parsedmarc/venv/bin/pip install --upgrade pip
|
|
sudo -u parsedmarc /opt/parsedmarc/venv/bin/pip install --upgrade "parsedmarc[all]"
|
|
```
|
|
|
|
To upgrade `parsedmarc` later, re-run the last command above and then
|
|
restart the service.
|
|
|
|
### Choosing what to install
|
|
|
|
Starting with the next major release, the integrations that talk to
|
|
external systems live in optional extras, so an install only carries the
|
|
dependencies it actually uses.
|
|
|
|
`pip install parsedmarc` — the base install — provides:
|
|
|
|
- the parsing library (aggregate, failure, and SMTP TLS reports),
|
|
- the CLI, reading reports from files, an IMAP mailbox, a Maildir, or an
|
|
mbox file,
|
|
- and CSV/JSON, Splunk HEC, webhook, and syslog output.
|
|
|
|
Everything else needs an extra:
|
|
|
|
| Extra | Enables |
|
|
|---|---|
|
|
| `elastic` | The `[elasticsearch]` output |
|
|
| `opensearch` | The `[opensearch]` output |
|
|
| `kafka` | The `[kafka]` output |
|
|
| `s3` | The `[s3]` output |
|
|
| `gelf` | The `[gelf]` output |
|
|
| `loganalytics` | The `[log_analytics]` (Azure Monitor) output |
|
|
| `msgraph` | The `[msgraph]` mailbox input (Microsoft 365) |
|
|
| `gmail` | The `[gmail_api]` mailbox input |
|
|
| `postgresql` | The `[postgresql]` output |
|
|
|
|
Extras can be combined: `pip install "parsedmarc[elastic,msgraph]"`.
|
|
|
|
`pip install "parsedmarc[all]"` installs every extra in the table
|
|
**except** `postgresql`, which stays separate because `psycopg`'s
|
|
prebuilt binary wheels are not available for every platform — folding it
|
|
into `all` would make `parsedmarc[all]` fail to install there. Add it
|
|
explicitly when you need it: `pip install "parsedmarc[all,postgresql]"`.
|
|
|
|
If a configuration file names a section whose extra is not installed,
|
|
`parsedmarc` exits at startup with an error naming the exact
|
|
`pip install` command to run.
|
|
|
|
:::{note}
|
|
**Upgrading from 10.x:** every 10.x install carried the Elasticsearch,
|
|
OpenSearch, Kafka, AWS, Azure, Gmail, and Microsoft Graph packages,
|
|
whether or not it used them. They are no longer installed by
|
|
`pip install parsedmarc`, so switch your install command to
|
|
`pip install --upgrade "parsedmarc[all]"` (adding `postgresql` if you
|
|
use it) to keep every integration available. An in-place upgrade does
|
|
not uninstall packages you already have, but a rebuilt virtualenv — or
|
|
any fresh install — gets only what the extras name. Users of the
|
|
prebuilt Docker image are unaffected: it bundles `[all,postgresql]`.
|
|
:::
|
|
|
|
## Optional system dependencies
|
|
|
|
If you would like to be able to parse emails saved from Microsoft
|
|
Outlook (i.e. OLE .msg files), install `msgconvert`:
|
|
|
|
On Debian or Ubuntu systems, run:
|
|
|
|
```bash
|
|
sudo apt-get install libemail-outlook-message-perl
|
|
```
|
|
|
|
On CentOS, RHEL, or Rocky Linux, the `Email::Outlook::Message` Perl
|
|
module is not packaged in the base repositories or EPEL, so install
|
|
it from CPAN:
|
|
|
|
```bash
|
|
sudo dnf install -y perl perl-CPAN make gcc
|
|
sudo cpan -i Email::Outlook::Message
|
|
```
|
|
|
|
This installs the `msgconvert` script to `/usr/local/bin/msgconvert`.
|
|
|
|
## Using MaxMind GeoLite2 (optional)
|
|
|
|
To use the [MaxMind GeoLite2 Country database] instead of the bundled
|
|
IPinfo Lite database, point the `ip_db_path` option at it explicitly:
|
|
|
|
```ini
|
|
[general]
|
|
ip_db_path = /usr/share/GeoIP/GeoLite2-Country.mmdb
|
|
```
|
|
|
|
**Use this only if you specifically prefer MaxMind data over the
|
|
bundled IPinfo Lite database — most users do not need it.** Country
|
|
databases like GeoLite2 carry no ASN data, so source attribution for
|
|
IP addresses without reverse DNS is reduced when one is used.
|
|
|
|
:::{note}
|
|
parsedmarc no longer picks up a GeoLite2/DBIP database from standard
|
|
system paths (e.g. `/usr/share/GeoIP/GeoLite2-Country.mmdb`)
|
|
automatically — a GeoIP file installed by an unrelated distro package
|
|
would silently override the bundled database and disable ASN
|
|
enrichment. System paths are now only consulted as a last resort when
|
|
the bundled database is missing. If you previously relied on the
|
|
automatic pickup, set `ip_db_path` as shown above.
|
|
:::
|
|
|
|
Install [geoipupdate] for your platform:
|
|
|
|
```bash
|
|
# Debian 10+ (requires the contrib component in apt sources)
|
|
sudo apt-get install -y geoipupdate
|
|
|
|
# Ubuntu
|
|
sudo add-apt-repository ppa:maxmind/ppa
|
|
sudo apt update
|
|
sudo apt install -y geoipupdate
|
|
|
|
# CentOS, RHEL, or Rocky Linux
|
|
sudo dnf install -y geoipupdate
|
|
```
|
|
|
|
Builds for Linux, macOS, and Windows are also available on the
|
|
[geoipupdate releases page on GitHub].
|
|
|
|
Since December 2019, MaxMind has required a free account to download
|
|
the GeoLite2 databases ([to comply with various privacy regulations]).
|
|
[Register for a free GeoLite2 account][registering for a free
|
|
geolite2 account], sign in, then create a new key on the [License
|
|
Keys] page (you can use `parsedmarc` as the description). Download the
|
|
pre-filled config file and save it to `/etc/GeoIP.conf` on Linux/macOS
|
|
or `%SystemDrive%\ProgramData\MaxMind\GeoIPUpdate\GeoIP.conf` on
|
|
Windows.
|
|
|
|
Then run
|
|
|
|
```bash
|
|
sudo geoipupdate
|
|
```
|
|
|
|
to download the databases for the first time. The GeoLite2 databases
|
|
are updated weekly (every Tuesday); add a cron job or scheduled task
|
|
to re-run `geoipupdate` weekly. More detail at the [MaxMind
|
|
geoipupdate page].
|
|
|
|
[KB4295699]: https://support.microsoft.com/KB/4295699
|
|
[KB4099855]: https://support.microsoft.com/KB/4099855
|
|
[KB4134118]: https://support.microsoft.com/kb/4134118
|
|
[geoipupdate]: https://github.com/maxmind/geoipupdate
|
|
[geoipupdate releases page on github]: https://github.com/maxmind/geoipupdate/releases
|
|
[ipinfo lite]: https://ipinfo.io/lite
|
|
[creative commons attribution-sharealike 4.0 license]: https://creativecommons.org/licenses/by-sa/4.0/deed.en
|
|
[license keys]: https://www.maxmind.com/en/accounts/current/license-key
|
|
[maxmind geoipupdate page]: https://dev.maxmind.com/geoip/updating-databases/
|
|
[maxmind geolite2 country database]: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
|
|
[registering for a free geolite2 account]: https://www.maxmind.com/en/geolite2/signup
|
|
[to comply with various privacy regulations]: https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/
|