local_email_bridge/README.md

62 lines
3.6 KiB
Markdown

# email_tunnel
Poll Proton Bridge via IMAP and inject messages into a local SMTP server (e.g., Haraka). The script is designed for headless, continuous operation with basic safety/observability baked in.
## What it does
- Connects to Proton Bridge IMAP via STARTTLS and selects a required folder.
- Polls for new messages by UID, fetches each, and relays it verbatim to a local SMTP server using the original headers.
- Strips `Bcc`, deduplicates recipients, and skips malformed addresses.
- Tracks progress in a JSON state file so messages are processed once, even across restarts.
- Retries IMAP fetch/search and SMTP delivery with bounded attempts/backoff; advances state past permanent delivery failures to avoid loops.
- Enforces single-instance execution via a pidfile lock.
- Emits scrape-friendly INFO logs each cycle with counts, last UID, and cycle duration.
## Requirements
- Python 3.x
- Proton Bridge IMAP reachable at the configured host/port
- Local SMTP server reachable (e.g., Haraka bound to a non-25 port)
## Configuration (environment variables)
- `IMAP_IP` (required): Proton Bridge IMAP host.
- `IMAP_PORT` (required): Proton Bridge IMAP port (typically 1143).
- `IMAP_USER` (required): IMAP username.
- `IMAP_PASSWORD` (required): IMAP password.
- `IMAP_FOLDER` (required): IMAP folder to poll; must exist (no fallback).
- `IMAP_TLS_VERIFY` (default `1`): Set to `0`/`false` to disable cert/hostname checks (dev only).
- `SMTP_IP` (default `127.0.0.1`): SMTP host to deliver to.
- `SMTP_PORT` (default `2525`): SMTP port to deliver to.
- `POLL_INTERVAL` (default `15`): Seconds between mailbox polls.
- `STATE_FILE` (default `./state.json`): Path to persist last processed UID.
- `PIDFILE` (default `/tmp/email_tunnel.pid`): Pidfile for single-instance lock.
- `LOG_LEVEL` (default `INFO`): Standard logging levels (`DEBUG`, `INFO`, etc.).
## Usage
```bash
export IMAP_IP=127.0.0.1
export IMAP_PORT=1143
export IMAP_USER=...
export IMAP_PASSWORD=...
export IMAP_FOLDER=loomio
export SMTP_IP=127.0.0.1
export SMTP_PORT=2525
python3 email_tunnel.py
```
Run under a process supervisor (systemd, supervisord, etc.) so restarts and log rotation are handled.
## Operational behavior
- State tracking: `STATE_FILE` records the last successfully handled UID. It is only advanced after successful delivery, or after a logged `DeliveryError` to avoid reprocessing a permanently failed message.
- Retries: IMAP SEARCH/FETCH and SMTP SEND are retried up to 3 times with small backoff. Persistent failures log and move on.
- Single instance: pidfile lock prevents multiple concurrent runs; stale pidfiles are replaced if the recorded PID is not running.
- Metrics logging: every poll cycle emits a single INFO line with `metrics` prefix and key/value pairs (`cycle_processed`, `cycle_delivered`, `cycle_failed`, `session_*`, `last_uid`, `cycle_duration_ms`).
- Missing state: if `STATE_FILE` is absent on startup, the script initializes it to the current max UID (or 0 for an empty mailbox) to avoid reprocessing the entire mailbox.
## Notes and safety
- Leave `IMAP_TLS_VERIFY` enabled in production; disable only for trusted, local endpoints.
- Ensure the `STATE_FILE` and `PIDFILE` paths are writable by the service user.
- If delivering to a server that rejects certain recipients, the script will log the error, advance the UID, and continue.
## Troubleshooting
- Increase verbosity with `LOG_LEVEL=DEBUG` to see raw message dumps and IMAP folder listings.
- If the script exits immediately, verify required env vars and that `IMAP_FOLDER` exists on the server.
- For pidfile conflicts, check the process holding the PID or remove a stale pidfile if no process is running.***