These steps will guide you to run an example app locally together with a Postfix instance running in a Docker container.
- Have a modern Python at your current
PATH(e.g. Python 3.10+).- Alternatively, obtain a modern Python and follow the steps below from a virtualenv
using Pyenv+Direnv with the supplied
.envrc; that's up to you.
- Alternatively, obtain a modern Python and follow the steps below from a virtualenv
using Pyenv+Direnv with the supplied
- Docker installed with privileges to build and run containers as the current user on the system.
- Internet access for building the container that pulls in the base layer and downloads packages.
- Assumption of a default Docker network set up at
172.17.0.1/16(for the steps below, or else adjust accordingly). - No firewall in the way blocking connections from the Postfix container to your host.
- Have GNU Make (
make) installed.
-
Install Purepythonmilter, e.g. like this from sources:
$ git clone https://github.com/gertvdijk/purepythonmilter.git $ cd purepythonmilter # N.B. You may want to create and activate a Python virtualenv at this point. # This installs the package at the current location (`.`) with the `examples` option # to indicate extra dependencies to be installed. $ python -m pip install -e .[examples]
-
Run an example Milter app, bound to the Docker default network bridge interface with debug logging enabled.
$ python -m purepythonmilter.examples.debug_log_all \ --bind-host 172.17.0.1 \ --log-level=INFO
💡 Change
--log-level=INFOto--log-level=DEBUGand be ready to get a lot of output, perhaps relevant when testing. -
Use the helpers in
postfixtest/to build and run a Postfix instance in Docker. This will start a Postfix container namedpurepythonmilter-postfixtestand runs it in the foreground.$ make -C postfixtestWait until Postfix is ready, e.g.: when a line like this is printed:
postfix/master[1]: daemon started -- version 3.5.6, configuration /etc/postfix -
Send an email to
[email protected]using your mail client (e.g. Thunderbird as SMTP outgoing server or SWAKS) to submit email to this Postfix instance.To find out what is the IP of the container, you can use the following command:
$ make --silent -C postfixtest get-ipv4One-liner to use SWAKS:
$ swaks --to [email protected] --server $(make --silent -C postfixtest get-ipv4) -
Observe the output in the terminal where you started the Milter in step 2 as well as the output of Postfix.
The Milter app should print now something like:
INFO:purepythonmilter.server.milterserver:Milter server started, awaiting connections... INFO:debug_log_all:bb5bec76: On connect: args=ConnectionInfoArgsIPv4(hostname='[172.17.0.1]', addr=IPv4Address('172.17.0.1'), port=53286), macros={'j': ... INFO:debug_log_all:bb5bec76: On HELO: hostname=[172.17.0.1], macros={} INFO:debug_log_all:bb5bec76: On MAIL FROM: [email protected], esmtp_args={'BODY': '8BITMIME', 'SIZE': ... INFO:debug_log_all:bb5bec76: On RCPT TO: [email protected], esmtp_args={}, ... [...] INFO:debug_log_all:bb5bec76: On abort INFO:debug_log_all:bb5bec76: On quitYou will still see errors on relaying the mail to
test.local, but that does not exist and you can safely ignore that. It does not matter for the Milter. -
Both the Postfix container and the Milter app can be stopped by pressing
<Ctrl>+Cin the terminal where they're running.
You have now seen a demonstration of the hooks that the Milter gives you with the 'debug_log_all' example app. 🎉
If you don't have a mail client at hand, you could use plain 'Old School' telnet too:
- In another terminal, initiate a connection to Postfix using
telnet. Note that the container has been given a dynamic IP address by Docker.$ telnet "$(make --silent -C postfixtest get-ipv4)" 25 - Observe the output in the terminal... (as above).
- Back in the terminal where you started
telnet, stop the connection to Postfix by either:- Type
QUITfollowed by pressing<Enter>, or - Quit the telnet client using the printed escape sequence (e.g.
<Ctrl>+]), followed by typingquitand pressing<Enter>.
- Type