Wonderbolt LDA

Wonderbolt is a config based email modifier, acting as local delivery agent and resubmitting emails via SMTP after modification.

Wonderbolt’s main purpose is to enable simple email lists with external management of subscribers.

  • Depends: python >= 3.4
  • Recommends: python3-systemd

Command-Line Options

--config file Required. This option takes one or more paths to config files. Later config files overwrite values from earlier ones.
--sasl-username username
 Optional. See config option require_sasl_username.

Configuration Options

All configuration options are optional. However, you probably want to change an option like envelope_rcpt_to to avoid loops.

bounce_from:

string or null

The From header that is used for bounce messages generated by Wonderbolt. If not specified or null, the header is set to Mail Delivery System <MAILER-DAEMON@hostname>, where hostname is replaced by the configured hostname.

envelope_mail_from:
 

string or null

Bounce address for the new delivery of the email. If this setting is null, it will be derived from the From email header.

envelope_rcpt_to:
 

list of strings or null

Recipients for new delivery of the email. If this setting is null, it will be derived from the To email header.

header_add:

mapping

Adds header values without removing/changing existing header lines. Performed after header_replace and header_add_if_missing. Therefore, header_add adds a header a second time if key overlaps with header_replace and/or header_add_if_missing are present.

header_add_if_missing:
 

mapping

Adds header values only if header with the given key does not exist. Performed after header_replace, but before header_add. Therefore, header_add adds a header a second time if key overlaps with header_add_if_missing are present.

header_replace:

mapping

Removes all existing headers with the given keys and adds the new values.

hostname:

string

The configured hostname is used in the content of bounce messages generated by Wonderbolt and is part of the default value for the bounce_from option.

reject_msg_requirements:
 

string

Error message used if emails are rejected by Wonderbolt due to violated require_ configurations. This message is usually contained in a bounce message generated by the MTA and delivered to the sender afterwards.

require_from:

list of strings or "envelope_rcpt_to" or false

Enables to reject mails if the From email header does not fulfill a condition.

  • list of strings: From must be contained in this list.
  • "envelope_rcpt_to": From must be contained in the envelope_rcpt_to list. If this option is set, envelope_rcpt_to must be set and not null.
  • false: Disables checks (default).
require_sasl_username:
 

list of strings or "envelope_rcpt_to" or false

Enables to reject mails if the SASL username does not fulfill a condition. Same parameters as for require_from.

For this feature to work, --sasl-username has to be specified on delivery.

Note

While this feature is named after the SASL (Simple Authentication and Security Layer), there is no aspect of the implementation that limits the functionality to this exact authentication protocol.

sasl_recipient_delimiter:
 

string

Recipient delimiters only affect the interpretation of envelope_rcpt_to if require_sasl_username is set to this value. The local part of all recipients is stripped from all characters occurring after a first delimiter for comparing with the SASL username.

This option should be set to the same value as the recipient_delimiter option of the postfix server. Every character in the string is treated as a delimiter. An empty string (default) corresponds to no delimiters.

smtp_server:

string

SMTP server via which the email is submitted. Default is “localhost:25”.

Configuration Examples

Example of a wonderbolt config without a specific use case.

{
    "reject_msg_requirements": "Rejected due to unprivileged SASL user",
    "header_add": {
        "X-Header-1": 1,
        "X-Header-3": "Value 3"
    },
    "header_replace": {
        "X-Header-1": "Value 1",
        "X-Header-2": "Value 2"
    },
    "envelope_mail_from": "Bounce To <bounce_to@example.com>",
    "envelope_rcpt_to": [
        "User Name <user@example.org>",
        "user2@example.org"
    ],
    "require_from": false,
    "require_sasl_username": "envelope_rcpt_to",
    "smtp_server": "mail.example.com:25"
}

Complete Mailing List under Postfix

master.cfg

wonderbolt   unix  -       n       n       -       -       pipe
  flags=Ohu
  user=wonderbolt:wonderbolt
  argv=/usr/local/bin/wonderbolt.py --config /etc/wonderbolt/${nexthop}.json --sasl-username ${sasl_username}

main.cfg

wonderbolt_destination_recipient_limit = 1

/etc/wonderbolt/list@example.org.json

{
    "envelope_mail_from": "list+bounce@example.org",
    "envelope_rcpt_to": [
        "listadmin@example.org",
        "user1@example.com",
        "user2_lists@example.com"
    ],
    "header_add_if_missing": {
        "List-Id": "<test.example.org>",
        "List-Post": "<mailto:list@example.org>",
        "Precedence": "bulk"
    },
    "header_replace": {
        "List-Help": "<mailto:listadmin@example.org>",
        "List-Owner": "<mailto:listadmin@example.org>",
        "List-Subscribe": "<mailto:listadmin@example.org?body=subscribe%20list%20list@example.org>",
        "List-Unsubscribe": "<mailto:listadmin@example.org?body=unsubscribe%20list%20list@example.org>"
    },
    "require_sasl_username": "envelope_rcpt_to",
    "sasl_recipient_delimiter": "_"
}

Note

The choice of which headers are kept and which are replaced is made such that the list should conform with all currently applicable RFCs.

This configuration follows RFC 2919 by not removing the List-Id of a “parent” mailing list by not removing any List-Id. Since it is hard to tell what an unexpected source for such a header is, it does pass a given List-Id through to the list in any case, which violates a SHOULD NOT of this RFC.

It further follows RFC 2369 by replacing the List-Help, List-Owner, List-Subscribe and List-Unsubscribe headers. The List-Post header could also be replaced.

maps/aliases (postfix virtual_alias_maps)

list+bounce@example.org listadmin@example.org

Note

This aliasing of the list-admin address is done to use it as an envelope sender, which does not conflict with any sender policies defined by via the SPF and similar mechanisms.

maps/transport (postfix transport_maps)

list@example.org wonderbolt:list@example.org

See also

pipe(8), Postfix delivery to external command

Dedication

                                     ooooooo
                                 oO0.....00OOOoo
                              oO0...........0Oo
                            oO000000000000000000o
                      o00Ooo000000000000000000OoOOo
                      0....000000000000000000000o
                      ...........0000000000000000o
                      0...............000..00000000o
               oOoO0OO..................O..0Oo0oooooo
               O........0.....0OOooo..O0....O 0O
            00OO0.......000....00o  ooO.::.......o
            O............000.....00o  O.:.......0
             O...........000000......0......00oo
              o0.........000000000...........0o
                o0........0000000.......0OOoo
              OOOO0.......0O0000000......0o       oooo
              O............0OO000000.......O    o0....0O
               oO...........0OO000000.......00OO........0o
                  oO.........0OO00.00..............00....0o
                     o0.......OOO0..0............0oo......0
                     O........0OO.................o 0......o
                      O0.......00.................0  O0...0
        ooooooooo        oo0.......................o   ooo
    oOOOOOOOOOOO000OOOoo  0::......................
  OOOOOOOOO000000000000000...0.............Oo0....O
 OOOOOOO000000...........................Oo   oOOo
oO oOOO00000.::..00OOoooO00...........0o
   0OO00000::.000Oo    0.............0o
   0OO0000.:.0000      o............0o
   OOO0000.:.0000o      o..........0
    OOO0000.:.00OOo      O..........o
     OOO0000::.00ooo     o..........0
      oOO0000.:.00O      o...........O
        OO0000.:.000o     oO0.........O
         oO00000.:.OOO        0.......0o
           oO0000.:.ooOo      oO00....0o
             oO000.:.o oO
               oOO0.:0   o
                 o O.0
                    Oo

GitLab Thumbnail Copyright BlackGryph0n Licensed under CC BY-NC 3.0