MailHook converts phpIPAM notification emails into webhooks by intercepting mail in Postfix. No phpIPAM source changes are required.
Note: internal paths and service names still use mailhook for compatibility (for example /opt/mailhook, mailhook-ui.service).
This README is the simple deployment path for one host.
- phpIPAM emails are intercepted in Postfix
- matching phpIPAM messages are converted to JSON webhooks
- webhook attempts are logged to SQLite
- a small web UI shows each captured email and webhook payload in a modal
- Linux host with root access
- Postfix installed and running
- phpIPAM sending mail through local
sendmail/Postfix - Python 3.10+
- reachable webhook endpoint
mkdir -p /opt
cp -a /path/to/mailhook /opt/mailhook
cd /opt/mailhook
./bin/bootstrap-python.shinstall -d -o root -g root /etc/mailhook
install -m 0640 -o root -g root /opt/mailhook/config/mailhook.env.example /etc/mailhook/mailhook.envEdit /etc/mailhook/mailhook.env and set at least:
WEBHOOK_URLfor your receiverWEBHOOK_TOKENif receiver requiresX-Webhook-TokenLISTEN_ALL_MAIL=falsePHPIPAM_SENDER_PATTERN=^ipam@example\.net$(or your sender)RELAY_ORIGINAL_PHPIPAM_MAIL=falsefor webhook-only mode
id -u mailhook >/dev/null 2>&1 || useradd --system --home /nonexistent --shell /usr/sbin/nologin mailhook
install -d -o mailhook -g mailhook /var/lib/mailhook
install -d -o mailhook -g mailhook /var/lib/mailhook/captureAdd to /etc/postfix/main.cf:
content_filter = phpipamhook:
receive_override_options = no_address_mappings
Add to /etc/postfix/master.cf:
phpipamhook unix - n n - - pipe
flags=Rq user=mailhook argv=/opt/mailhook/bin/postfix-filter-wrapper.sh ${sender} ${recipient} ${queue_id}
Add reinjection listener to /etc/postfix/master.cf (required for non-matching mail):
127.0.0.1:10026 inet n - n - - smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o disable_vrfy_command=yes
Then:
postfix check
systemctl reload postfixinstall -m 0644 -o root -g root /opt/mailhook/systemd/mailhook-ui.service /etc/systemd/system/mailhook-ui.service
systemctl daemon-reload
systemctl enable --now mailhook-ui.serviceUI local URL:
http://127.0.0.1:8010/
If you already use Nginx basic-auth proxy on this host, expose it at:
http://<host>:8081/
- Make one small phpIPAM change (for example, change address state).
- Check Postfix:
journalctl --since '10 minutes ago' --no-pager | egrep -i 'postfix/(pickup|cleanup|qmgr|pipe|10026|smtp)|phpipamhook'
mailq- Check capture files:
ls -lt /var/lib/mailhook/capture | head- Open UI and click
#<id> Review.
You should see:
- email source in the top pane
- webhook JSON in the bottom pane
- webhook endpoint:
http://webhook-receiver.example.net:8080/v1/webhook - token header:
X-Webhook-Token - sender match:
^ipam@example\.net$ - mode: webhook-only for matched phpIPAM mail
- No events in UI: verify
MAILHOOK_DB_PATHand directory ownership (mailhook:mailhook) - Mail still delivered instead of webhook-only: verify
RELAY_ORIGINAL_PHPIPAM_MAIL=false - 401/403 at receiver: verify
WEBHOOK_TOKEN - No interception: verify Postfix
content_filterandphpipamhookservice are loaded
See docs/DEPLOYMENT.md for full reference, payload schema, and flow diagram.
Licensed under GNU General Public License v3.0 only (GPL-3.0-only).
See LICENSE.
Copyright (C) 2026 Anthony Burow https://github.com/aburow