Pfxhttp is a lightweight HTTP proxy designed to integrate Postfix with external HTTP APIs for socket maps and policy services. This enables dynamic and flexible email workflows by connecting Postfix to modern APIs.
Pfxhttp allows you to:
- Perform dynamic lookups via socket maps, such as resolving virtual mailboxes or domains.
- Implement custom mail policy checks through HTTP-based policy services.
The application is configured using a YAML file, specifying HTTP endpoints, the format of requests, and field mappings. It supports key Postfix features like query lookups and policy service hooks.
Pfxhttp is written in Go and can be compiled with the following commands:
make
make install
By default, Pfxhttp and its associated man pages are installed in /usr/local
.
The configuration is located in one of the following directories, based on priority:
/usr/local/etc/pfxhttp/
/etc/pfxhttp/
$HOME/.pfxhttp/
- Current directory (
.
)
The expected configuration file name is pfxhttp.yml
.
Note: This first implementation was tested using Go version 1.23.
Pfxhttp is typically run as a systemd service. Below is an example unit file:
[Unit]
Description=PfxHTTP Postfix-to-HTTP server
After=network.target
[Service]
Type=simple
Restart=always
User=pfxhttp
Group=pfxhttp
EnvironmentFile=-/etc/default/pfxhttp
ExecStart=/usr/local/sbin/pfxhttp
StandardOutput=journal
StandardError=journal
SyslogIdentifier=pfxhttp
MemoryMax=50M
CPUQuota=10%
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_CHOWN
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
ReadOnlyPaths=/etc
ProtectKernelModules=true
MemoryDenyWriteExecute=true
ProtectControlGroups=true
ProtectKernelLogs=true
ProtectClock=true
RestrictSUIDSGID=true
ProtectProc=invisible
LimitNOFILE=1024
#RestrictAddressFamilies=AF_INET AF_INET6
[Install]
WantedBy=multi-user.target
You must create a user pfxhttp and a group pfxhttp before using this unit file!
To install and start the service:
sudo systemctl daemon-reload
sudo systemctl enable pfxhttp
sudo systemctl start pfxhttp
Pfxhttp provides the following command-line flags:
-
--config: Specifies the path to the configuration file. Overrides the default configuration file location.
./pfxhttp --config=/path/to/config.yml
-
--format: Sets the logging format. Available options are
yaml
,toml
orjson
../pfxhttp --format=json
Use these flags as needed to customize the behavior of the application during runtime.
Pfxhttp is configured through a YAML file named pfxhttp.yml
(or a custom file specified with the --config
and --format
flags). The following are the main sections:
The server
section contains global options, including:
- Listeners: Define socket map and policy service listeners for Postfix integration.
- Logging: Enable JSON-formatted logs and set verbosity (
debug
,info
, orerror
). - HTTP Client Options: Configure connection limits, timeouts, and optional TLS settings.
Below is a detailed example configuration for pfxhttp.yml
:
server:
listen:
- kind: "socket_map"
name: "demo_map"
type: "tcp"
address: "[::]"
port: 23450
- kind: "policy_service"
name: "example_policy"
type: "tcp"
address: "[::]"
port: 23451
logging:
json: true
level: info
tls:
enabled: true
http_client_skip_verify: true
socket_maps:
demo_map:
target: "https://127.0.0.1:9443/api/v1/custom/map"
custom_headers:
- "Authorization: Bearer <token>"
payload: >
{
"key": "{{ .Key }}"
}
status_code: 200
value_field: "data.result"
error_field: "error"
no_error_value: "not-found"
policy_services:
example_policy:
target: "https://127.0.0.1:9443/api/v1/custom/policy"
custom_headers:
- "Authorization: Bearer <token>"
payload: "{{ .Key }}"
status_code: 200
value_field: "policy.result"
error_field: "policy.error"
no_error_value: "OK"
Important: Postfix has a hardcoded socket map reply size limit of 100,000 bytes (Postfix 3.9.1 or older).
To configure Postfix to use a socket map, simply add it to your main.cf
:
# main.cf
virtual_mailbox_domains = socketmap:tcp:127.0.0.1:23450:demo_map
Here, Postfix connects to the TCP socket map listener defined in pfxhttp.yml
for demo_map
.
To use a policy service, include it in your recipient restrictions list in main.cf
:
# main.cf
smtpd_recipient_restrictions =
permit_mynetworks,
reject_unauth_destination,
check_policy_service inet:127.0.0.1:23451
This setup enables Postfix to query the policy service defined in pfxhttp.yml
for example_policy
.
Logs are output to the console by default and should be captured by the service manager (e.g., systemd). Log verbosity is configurable in the pfxhttp.yml
file.
If Pfxhttp fails to start, verify the following:
- Ensure the configuration file (
/etc/pfxhttp/pfxhttp.yml
) is valid and complete. - Ensure the service is running with the appropriate permissions for the configured resources.
Contributions are welcome! Feel free to submit pull requests or issues to improve the project. The project is distributed under the MIT License.
- Postfix Documentation
- Nauthilus
- Manpages:
pfxhttp(8)
: Overview and service managementpfxhttp.yml(5)
: Detailed configuration guide