Skip to main content

Egress

Applies to both dlr_url on a submission and forward.mo.url on a connector.
smsg.webhook.redirects changed from following redirects to not following them. It is the setting the others depend on: once a redirect is followed, the address that was checked is not the address that is fetched. An endpoint relying on a redirect now fails loudly rather than quietly going somewhere else.
private.targets changed to deny in 0.11. A receipt URL resolving to a private, loopback or link-local address is refused unless you set allow. The old default let a customer’s dlr_url address anything your gateway could reach, which is a request-forgery surface handed to whoever sends you traffic. If you post receipts to an application on your own network, set allow before you upgrade — the refusal is silent to the customer and shows up only as receipts that never arrive.
It resolves the host and then connects, so a name that answers differently in between defeats it. It raises the cost rather than closing the hole — egress firewall rules are what close it.
The retry ladder is exponential with full jitter, and that changed in 0.11. At the defaults the ceilings are 2, 4, 8, 16 and 32 minutes, then an hour before each of the last four attempts — ten attempts spanning at most 5h 2m, where the old flat 120-second wait gave up eighteen minutes after the first failure and lost every receipt for an endpoint down over a lunchtime deploy. Each wait is drawn uniformly from zero up to its ceiling, so ten attempts average nearer two and a half hours, and receipts that failed together do not come due together at a host already in trouble. A first wait longer than an hour is honoured rather than cut to the ceiling. A receipt between attempts holds nothing open against the endpoint, so a long schedule costs nothing while it waits — and the gateway keeps at most ten calls in flight to any one host, so a slow endpoint cannot occupy the whole forwarder.

Receipt forwarding

kannel carries information only where the registered URL has placeholders for it. A URL without them receives a request with nothing in it, and nothing reports a problem. That silent failure is why json is the default.
vendor is off by default because it discloses your supplier to your customer, at an endpoint they control — usually commercially sensitive. The payload is documented at Delivery receipts.

The delivery receipt store

Correlation state for messages awaiting a receipt, and receipts held for a disconnected SMPP client. The only persistent state outside PostgreSQL. The path was previously settable only as a -D fireflo.dlr.db.path system property. That is still honoured when smsg.dlr.store.path is unset, so an existing deployment is not relocated on upgrade.
smsg.dlr.correlation.days bounds smsg.cdr.deadline.hours. Past the correlation window a receipt can no longer be matched to its submission, so waiting longer for one only delays the same answer. The expiry sweeper derives its cap from this value rather than holding a constant of its own, so widening the window raises the cap and narrowing it lowers it. A deadline above the cap is clamped and logged.