5.7 KiB
Local mail protocol fixtures
These fixtures are intentionally bound to loopback and use non-standard ports. They are development tools, not production configuration.
Cyrus IMAP, POP3, and LMTP
Install net-mail/cyrus-imapd, then start the disposable fixture as root:
sudo ./contrib/testing/cyrus-fixture.py start
It creates no files outside /tmp/bongo-cyrus-fixture and listens on:
- IMAP:
127.0.0.1:18143 - POP3:
127.0.0.1:18110 - LMTP:
127.0.0.1:18024
The source mailboxes form a multi-account-per-user matrix:
| Bongo owner | Cyrus source account | Protocol | Bongo destination |
|---|---|---|---|
test1 |
test1-pop@cyrus.bongo.test |
POP3 | INBOX |
test1 |
test1-imap@cyrus.bongo.test |
IMAP | Cyrus IMAP |
test2 |
test2-pop@cyrus.bongo.test |
POP3 | INBOX |
test2 |
test2-imap@cyrus.bongo.test |
IMAP | Cyrus IMAP |
All source accounts use the test-only password
BongoCollector-Test-2026. Insert a complete RFC 5322 message through Cyrus'
real LMTP delivery path:
sudo ./contrib/testing/cyrus-fixture.py inject message.eml
Seed three different messages in each source mailbox and exercise Bongo's real Collector POP3 and IMAP transport implementation:
./contrib/testing/cyrus-fixture.py verify-collector \
--probe ./build/src/agents/collector/collector-remote-transport-probe \
--count 3
The probe lists and fetches every message, checks its fixture marker, deletes
it through the selected protocol, and verifies that every Cyrus source mailbox
is empty. A live end-to-end run creates all four Bongo external-account
records. This proves that accounts, remote UID/UIDL values, retry state and
deletion state remain scoped by account ID even when one Bongo user owns
multiple sources. All four use after_import, so Cyrus deletion happens only
after the Bongo Queue has durably accepted and committed the complete message.
From that point the normal scanner, rules, quota, and Store delivery pipeline
owns it.
The fixture can also seed deterministic scanner and quota cases. All ports remain loopback-only and the flood is deliberately bounded:
sudo ./contrib/testing/cyrus-fixture.py seed --profile gtube --count 1
sudo ./contrib/testing/cyrus-fixture.py seed --profile eicar --count 1
sudo ./contrib/testing/cyrus-fixture.py seed --profile flood --count 32 \
--message-size 131072
sudo ./contrib/testing/cyrus-fixture.py seed-suite
gtube contains SpamAssassin's standard GTUBE string. eicar creates the
harmless standard EICAR attachment at runtime; the complete signature is kept
out of the Git checkout to avoid host antivirus false alarms. seed-suite
places three normal messages, one GTUBE message, one EICAR message, and 32
128-KiB flood messages in every source mailbox (148 messages total). Set a
small quota on disposable Bongo users before collection, then restore it after
the test. The test passes only when clean messages are imported, scanner
policy is applied, quota cannot be exceeded, and a message rejected before a
durable import remains retrievable from Cyrus.
The same LMTP listener is the forwarding target for the exact transport-domain
mapping below. This accepts *@cyrus.bongo.test without making the test domain
a local Bongo domain:
"lmtp_transports": ["cyrus.bongo.test=127.0.0.1:18024"]
Cyrus lmtpd is pre-authorized only on this loopback-only fixture listener.
That matches a trusted local MTA-to-store LMTP hop and must not be copied to a
network-exposed Cyrus listener.
The generated short-lived test CA at
/tmp/bongo-cyrus-fixture/tls/ca.crt is the fixture trust anchor. Set
BONGO_COLLECTOR_CAINFO to that path for the Collector process during this
test; normal installations continue to use the operating-system trust store.
The packaged bongo.service uses PrivateTmp=true, so a live systemd test
must make the fixture visible inside that service namespace. A runtime-only
drop-in can bind precisely this fixture read-only:
[Service]
BindReadOnlyPaths=/tmp/bongo-cyrus-fixture
Install it with systemctl edit --runtime bongo.service, restart Bongo, and
set the Collector ca_file to the path above. Do not weaken certificate or
host-name verification for the test.
After a live collection cycle, show the source-mailbox counts with:
./contrib/testing/cyrus-fixture.py mailbox-status
Stop or remove all fixture state with:
sudo ./contrib/testing/cyrus-fixture.py stop
sudo ./contrib/testing/cyrus-fixture.py reset
Outbound SMTP capture
Use net-mail/xeams-devnullsmtp-bin from the Bongo Gentoo overlay:
xeams-devnullsmtp -p 2526 -d bongo.test -s /tmp/bongo-devnull-mail
Configure 127.0.0.1:2526 as Bongo's relay host before testing any non-local
recipient. Xeams DevNullSMTP has no listen-address option, so isolate it with a
firewall or network namespace; do not expose it on a production network.
HAProxy and PROXY v2
haproxy-bongo-test.cfg exposes loopback-only high ports and forwards every
connection to the corresponding normal Bongo listener with a PROXY v2 header.
Before starting it, temporarily enable proxy_protocol_enabled and set
proxy_protocol_networks to ["127.0.0.1/32"] in the smtp, imap, pop3,
and sieve documents. Never trust an unbounded network for PROXY headers.
Validate and run the fixture in the foreground:
haproxy -c -f contrib/testing/haproxy-bongo-test.cfg
haproxy -db -f contrib/testing/haproxy-bongo-test.cfg
The test listeners are SMTP 11025, submission 11587, submissions 11465,
IMAP 11143, IMAPS 11993, POP3 11110, POP3S 11995, and ManageSieve
14190. Exercise real protocol greetings, capabilities, authentication, and
TLS handshakes through these ports, then restore the original Bongo documents.