diff --git a/dagelijks_overzicht.py b/dagelijks_overzicht.py index 9a301d0..14463e3 100644 --- a/dagelijks_overzicht.py +++ b/dagelijks_overzicht.py @@ -7,7 +7,7 @@ berichten die gisteren zijn binnengekomen, en stuurt een HTML-samenvatting naar hans@australius.nl. Eenmalige setup: python3 dagelijks_overzicht.py --setup -Handmatig testen: python3 dagelijks_overzicht.py [--gisteren | --datum 2026-07-01] +Handmatig testen: python3 dagelijks_overzicht.py [--gisteren | --datum 2026-07-01] [--mail-to adres] Plannen (macOS): zie dagelijks_overzicht.plist """ @@ -27,6 +27,7 @@ from collections import defaultdict from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from imap_utils import list_folders, quote_mailbox +from mail_imap_ops import fetch_body # Mappen die NIET in het overzicht komen (systeem + inbox zelf) UITSLUITINGEN = { @@ -59,6 +60,17 @@ def load_config(): } +def arg_value(args: list[str], flag: str) -> str | None: + """Return the value after a simple command-line flag.""" + if flag not in args: + return None + idx = args.index(flag) + if idx + 1 >= len(args): + print(f"Ontbrekende waarde voor {flag}") + sys.exit(2) + return args[idx + 1] + + # ── helpers ─────────────────────────────────────────────────────────────────── def decode_hdr(value) -> str: @@ -128,10 +140,11 @@ def haal_berichten_op(mail: imaplib.IMAP4_SSL, zoekdatum: date) -> dict[str, lis status, msg_data = mail.fetch( uid, "(BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)])" ) - if status != "OK" or not msg_data or not msg_data[0]: + raw_header = fetch_body(msg_data) + if status != "OK" or raw_header is None: continue - msg = email.message_from_bytes(msg_data[0][1]) + msg = email.message_from_bytes(raw_header) from_raw = decode_hdr(msg.get("From", "")) subject = decode_hdr(msg.get("Subject", "(geen onderwerp)")) date_str = msg.get("Date", "") @@ -232,12 +245,13 @@ def stuur_overzicht(html: str, zoekdatum: date, config: dict): def run(): args = sys.argv[1:] cfg_dict = load_config() + if mail_to := arg_value(args, "--mail-to"): + cfg_dict["to"] = mail_to print(f"Account: {cfg_dict['username']}\n") # Datum bepalen - if "--datum" in args: - idx = args.index("--datum") - zoekdatum = date.fromisoformat(args[idx + 1]) + if datum := arg_value(args, "--datum"): + zoekdatum = date.fromisoformat(datum) else: zoekdatum = date.today() - timedelta(days=1) # standaard: gisteren @@ -256,10 +270,6 @@ def run(): totaal = sum(len(v) for v in berichten.values()) print(f"{totaal} berichten gevonden in {len(berichten)} mappen.") - if totaal == 0: - print("Niets te sturen.") - return - html = bouw_html(berichten, zoekdatum) stuur_overzicht(html, zoekdatum, cfg_dict) diff --git a/deploy_vps.sh b/deploy_vps.sh index aac8e9e..022b11c 100755 --- a/deploy_vps.sh +++ b/deploy_vps.sh @@ -14,6 +14,7 @@ fi APP_USER="${APP_USER:-mailcat}" SERVICE_NAME="${SERVICE_NAME:-mailcat-sort-backup}" ACCOUNT="${ACCOUNT:-backup}" +DAILY_REPORT_TO="${DAILY_REPORT_TO:-hans@australius.nl}" REMOTE_PATH="${REMOTE_PATH:-/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin}" SERVICE_MANAGER="${SERVICE_MANAGER:-systemd}" MAILCAT_HOME="${MAILCAT_HOME:-/share/homes/$APP_USER}" @@ -202,11 +203,27 @@ echo "logs: \$LOG_DIR" exit 1 STATUS_SCRIPT + cat > /tmp/mailcat-daily-report.sh <> "\$LOG_DIR/daily_report.out" 2>&1 +REPORT_SCRIPT + "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-start.sh "$APP_DIR/bin/start_mailcat.sh" "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-stop.sh "$APP_DIR/bin/stop_mailcat.sh" "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-status.sh "$APP_DIR/bin/status_mailcat.sh" - "$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/bin/start_mailcat.sh" "$APP_DIR/bin/stop_mailcat.sh" "$APP_DIR/bin/status_mailcat.sh" - "$RM" -f /tmp/mailcat-start.sh /tmp/mailcat-stop.sh /tmp/mailcat-status.sh + "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-daily-report.sh "$APP_DIR/bin/run_daily_report.sh" + "$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/bin/start_mailcat.sh" "$APP_DIR/bin/stop_mailcat.sh" "$APP_DIR/bin/status_mailcat.sh" "$APP_DIR/bin/run_daily_report.sh" + "$RM" -f /tmp/mailcat-start.sh /tmp/mailcat-stop.sh /tmp/mailcat-status.sh /tmp/mailcat-daily-report.sh else "$SUDO" "$INSTALL" -m 0644 "$APP_DIR/systemd/mailcat-sort.service" "/etc/systemd/system/$SERVICE_NAME.service" "$SUDO" "$SED" -i \ @@ -229,6 +246,7 @@ echo "Create/check $APP_DIR/config.json, then run:" if [ "$SERVICE_MANAGER" = "plain" ]; then echo " sudo -u $APP_USER $APP_DIR/bin/start_mailcat.sh" echo " sudo -u $APP_USER $APP_DIR/bin/status_mailcat.sh" + echo " sudo -u $APP_USER $APP_DIR/bin/run_daily_report.sh" echo " tail -f $LOG_DIR/sort_mail_daemon.log" else echo " sudo systemctl start $SERVICE_NAME.service" @@ -239,5 +257,5 @@ REMOTE scp "$ARCHIVE" "$REMOTE_USER@$REMOTE_HOST:/tmp/mailcat-deploy.tar.gz" scp "$REMOTE_SCRIPT" "$REMOTE_USER@$REMOTE_HOST:/tmp/mailcat-remote-deploy.sh" -REMOTE_COMMAND=$(printf "APP_USER=%q APP_DIR=%q SERVICE_NAME=%q ACCOUNT=%q REMOTE_PATH=%q SERVICE_MANAGER=%q MAILCAT_HOME=%q STATE_DIR=%q LOG_DIR=%q RUN_DIR=%q PID_FILE=%q PYTHON=%q SUDO=%q USERADD=%q INSTALL=%q SED=%q TAR=%q MKDIR=%q CHOWN=%q CHMOD=%q RM=%q SYSTEMCTL=%q /bin/sh /tmp/mailcat-remote-deploy.sh" "$APP_USER" "$APP_DIR" "$SERVICE_NAME" "$ACCOUNT" "$REMOTE_PATH" "$SERVICE_MANAGER" "$MAILCAT_HOME" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$PID_FILE" "$PYTHON" "$SUDO" "$USERADD" "$INSTALL" "$SED" "$TAR" "$MKDIR" "$CHOWN" "$CHMOD" "$RM" "$SYSTEMCTL") +REMOTE_COMMAND=$(printf "APP_USER=%q APP_DIR=%q SERVICE_NAME=%q ACCOUNT=%q DAILY_REPORT_TO=%q REMOTE_PATH=%q SERVICE_MANAGER=%q MAILCAT_HOME=%q STATE_DIR=%q LOG_DIR=%q RUN_DIR=%q PID_FILE=%q PYTHON=%q SUDO=%q USERADD=%q INSTALL=%q SED=%q TAR=%q MKDIR=%q CHOWN=%q CHMOD=%q RM=%q SYSTEMCTL=%q /bin/sh /tmp/mailcat-remote-deploy.sh" "$APP_USER" "$APP_DIR" "$SERVICE_NAME" "$ACCOUNT" "$DAILY_REPORT_TO" "$REMOTE_PATH" "$SERVICE_MANAGER" "$MAILCAT_HOME" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$PID_FILE" "$PYTHON" "$SUDO" "$USERADD" "$INSTALL" "$SED" "$TAR" "$MKDIR" "$CHOWN" "$CHMOD" "$RM" "$SYSTEMCTL") ssh -tt "$REMOTE_USER@$REMOTE_HOST" "$REMOTE_COMMAND" diff --git a/restart_prompt.md b/restart_prompt.md index fa554ac..682e489 100644 --- a/restart_prompt.md +++ b/restart_prompt.md @@ -91,6 +91,14 @@ Scripts using shared IMAP folder handling: - `dagelijks_overzicht.py` - `sort_mail_daemon.py` +`dagelijks_overzicht.py` current behavior: + +- Builds an HTML digest of messages that arrived on the selected date, defaulting to yesterday. +- Uses central `config.py`; select the mailbox account with `--account`, for example `--account backup`. +- Sends the digest via SMTP using the selected account credentials. +- Supports `--mail-to
`; the NAS daily report target is `hans@australius.nl`. +- Sends the report even when zero messages are found, so scheduled runs are visible. + Shared operation helpers: - `mail_imap_ops.py` centralizes header decoding, FETCH payload extraction, routing fetched headers to full IMAP destinations, destination mailbox creation, and copy/delete move semantics for live sorting. @@ -153,7 +161,8 @@ Remote/NAS deployment files: - For the local NAS, use `SERVICE_MANAGER=plain`, `MAILCAT_HOME=/share/homes/mailcat`, and `PYTHON=/opt/bin/python3`. In plain mode, default paths are `APP_DIR=$MAILCAT_HOME/mailcat`, `STATE_DIR=$APP_DIR/state`, `LOG_DIR=$APP_DIR/log`, `RUN_DIR=$APP_DIR/run`, and `PID_FILE=$RUN_DIR/mailcat.pid`. - QNAP path facts supplied by the user: `SUDO=/usr/bin/sudo`, `USERADD=/usr/local/bin/useradd`, `PYTHON=/opt/bin/python3`, `INSTALL=/usr/bin/install`, `SED=/bin/sed`, `TAR=/bin/tar`, `MKDIR=/bin/mkdir`, `CHOWN=/bin/chown`, `CHMOD=/bin/chmod`, and `RM=/bin/rm`. `nologin`, `python3`, `systemctl`, and `nohup` are not in the user's default PATH. - The deploy script accepts absolute tool overrides for those commands and passes them into the remote script. In plain mode, the generated start/stop/status scripts also bake in absolute `MKDIR` and `RM` paths. -- In plain mode, the deploy script does not install systemd files. It writes executable scripts to `$APP_DIR/bin/start_mailcat.sh`, `$APP_DIR/bin/stop_mailcat.sh`, and `$APP_DIR/bin/status_mailcat.sh`. +- In plain mode, the deploy script does not install systemd files. It writes executable scripts to `$APP_DIR/bin/start_mailcat.sh`, `$APP_DIR/bin/stop_mailcat.sh`, `$APP_DIR/bin/status_mailcat.sh`, and `$APP_DIR/bin/run_daily_report.sh`. +- `DAILY_REPORT_TO` controls the report recipient during deploy and defaults to `hans@australius.nl`. The daily report wrapper appends output to `$LOG_DIR/daily_report.out`. - `systemd/mailcat-sort.service` is a template consumed by `deploy_vps.sh`; after placeholder replacement it runs `sort_mail_daemon.py --account backup --folder INBOX` and stores state/logs under `/var/lib/mailcat` and `/var/log/mailcat`. - `config.json` remains ignored and must be created manually on the remote host with mode `600` before starting the service. @@ -255,8 +264,10 @@ Recommended next work: - `sudo -u mailcat /share/homes/mailcat/mailcat/bin/start_mailcat.sh` - `sudo -u mailcat /share/homes/mailcat/mailcat/bin/status_mailcat.sh` - `tail -f /share/homes/mailcat/mailcat/log/sort_mail_daemon.log` -4. Send controlled test messages to `backup@australius.nl` for invoices, clear AI providers, a newsletter/service route, and unmatched mail; verify expected folder moves and daemon logs. -5. Add `List-ID` header support to mailing-list routing if live daemon tests show sender/domain matching is too coarse. +4. Test the daily report manually: `sudo -u mailcat /share/homes/mailcat/mailcat/bin/run_daily_report.sh`, then check `tail -100 /share/homes/mailcat/mailcat/log/daily_report.out` and confirm mail delivery to `hans@australius.nl`. +5. Add the daily report wrapper to QNAP scheduler after the manual test succeeds. +6. Send controlled test messages to `backup@australius.nl` for invoices, clear AI providers, a newsletter/service route, and unmatched mail; verify expected folder moves and daemon logs. +7. Add `List-ID` header support to mailing-list routing if live daemon tests show sender/domain matching is too coarse. ## Persistent File Rule