listenwicht


Namelistenwicht JSON
Version 0.0.2 PyPI version JSON
download
home_pagehttps://github.com/johndoe31415/listenwicht
SummaryFlexible Python-based mailing list daemon
upload_time2025-10-09 12:11:13
maintainerNone
docs_urlNone
authorJohannes Bauer
requires_pythonNone
licensegpl-3.0
keywords mailing list
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # listenwicht
listenwicht is a Python-based, highly flexible client that is able to resend
email according to static redistribution rules. In particular, compared to the
exceptionally simple forwarding configuration, listenwicht actually has an MTA
deliver the mail locally in mboxdir format, where they are picked up and
resent. Before resending, they can be rewritten. This is useful when your MTA
is not a valid according to the set SPF rules. It allows resending from a
SPF-legal "From" address.


## Dependencies
listenwicht depends on the command-line utility `inotifywatch` in order to
monitor the list directory.


## Caveats
listenwicht monitors in the `new/` subdirectory for `CREATE` and `MOVE_TO`
permissions. This is needed because while in newer systems, `MOVE_TO` is called
while on older systems `CREATE` (without any `MODIFY` or `WRITE_CLOSE`) is
used. This means that when testing and writing a file to the `new/`
subdirectory in a non-atomic fashion (e.g., `echo foo >mail.txt`), listenwicht
will misbehave (it might probably try to parse an empty/partial file).


## Usage: MTA setup
First, configure your MTA to perform delivery of emails in a maildir spool
directory. For example, in `main.cf`:

```
mail_spool_directory = /var/spool/mail/
```

Note the trailing slash for the spool directory, which forces maildir mode.

Then, typically, you will want to redirect traffic to a virtual user. For
example, consider there is a `mailinglist` user that listenwicht will run
under. Then, install the Postfix-PCRE module and create a
`/etc/postfix/virtual.pcre` file:

```
/^inf[0-9][0-9]...?[0-9]@my-mailserver\.de$/   mailinglist
/^inf-sgl@my-mailserver\.de$/                  mailinglist
```

This will redirect all traffic to these particular addresses to the maildir
`/var/spool/mail/mailinglist/new`. Enable that PCRE virtual address table by
putting in your `main.cf`:

```
virtual_alias_maps = pcre:/etc/postfix/virtual.pcre
```

Lastly, if you want to filter by `From` addresses, make sure SPF is enabled in
your Postfix configuration for local deliveries.

At this stage, try if you can send mails to postfix and they get accepted. For
example, using the above configuration, write an email to
`inf99abc4@my-mailserver.de` and check the logs to see everything works
properly (SPF configuration, local delivery in the expected directory).


## Usage: listenwicht configuration
When the mails are correctly delivered, you need to setup a listenwicht
configuration file, which is in JSON format. This is an example file, provided
in `listenwicht.json`:

```json
{
  "bounces": {
    "via": "smtp://127.0.0.1",
    "from": [ "listenwicht Bounces", "mailinglist-bounce@my-mailserver.de" ],
    "admin_email": "admin@my-mailserver.de"
  },
  "mailing_lists": [
    {
      "name": "23CS1",
      "conditions": [
        { "condtype": "match-header", "key": "Message-ID", "regex": "<.*@listenwicht>", "invert": true },
        { "condtype": "match-address", "key": "To", "regex": ".*bounce.*", "invert": true },
        { "condtype": "match-address", "key": "To", "regex": "inf(23cs1|23cs|23)@.*" },
        { "condtype": "match-address", "key": "From", "regex": ".*@allowed-users.de", "error": "Your 'From' address is not authorized to post on the ${mailing_list_name} mailing list." }
      ],
      "actions": [
        { "action": "remove-header", "key": [ "Autocrypt", "DKIM-Signature", "Reply-To", "Return-Path", "X-Original-To", "Delivered-To", "Authentication-Results" ] },
        { "action": "rename-header", "old": "From", "new": "Reply-To" },
        { "action": "set-address", "key": "From", "value": [ [ "My Mailing List", "mailinglist@my-mailserver.de" ] ] },
        { "action": "set-address", "key": "To", "value": [ [ "My Mailing List", "mailinglist@my-mailserver.de" ] ] },
        { "action": "set-header", "key": "List-Id", "value": "inf23cs1@my-mailserver.de" },
        { "action": "set-address", "key": "Bcc", "value": [ [ "Cee Ess One", "cs1@foobar.com"], [ "Next cs1 usr", "other@cs1.de" ] ] },
        { "action": "deliver", "via": "smtp://127.0.0.1" }
      ]
    },
    {
      "name": "23CS2",
      "conditions": [
        { "condtype": "match-header", "key": "Message-ID", "regex": "<.*@listenwicht>", "invert": true },
        { "condtype": "match-address", "key": "To", "regex": ".*bounce.*", "invert": true },
        { "condtype": "match-address", "key": "To", "regex": "inf(23cs2|23cs|23)@.*" },
        { "condtype": "match-address", "key": "From", "regex": ".*@allowed-users.de", "error": "Your 'From' address is not authorized to post on the ${mailing_list_name} mailing list." }
      ],
      "actions": [
        { "action": "remove-header", "key": [ "Autocrypt", "DKIM-Signature", "Reply-To", "Return-Path", "X-Original-To", "Delivered-To", "Authentication-Results" ] },
        { "action": "rename-header", "old": "From", "new": "Reply-To" },
        { "action": "set-address", "key": "From", "value": [ [ "My Mailing List", "mailinglist@my-mailserver.de" ] ] },
        { "action": "set-address", "key": "To", "value": [ [ "My Mailing List", "mailinglist@my-mailserver.de" ] ] },
        { "action": "set-header", "key": "List-Id", "value": "inf23cs2@my-mailserver.de" },
        { "action": "set-address", "key": "Bcc", "value": [ [ "CS2 user", "cs2-user@foo.org"], [ "Other CS2 User", "cs2-user-2@invalid.com" ] ] },
        { "action": "deliver", "via": "smtp://127.0.0.1" }
      ]
    },
    {
      "name": "SGL",
      "conditions": [
        { "condtype": "match-header", "key": "Message-ID", "regex": "<.*@listenwicht>", "invert": true },
        { "condtype": "match-address", "key": "To", "regex": ".*bounce.*", "invert": true },
        { "condtype": "match-address", "key": "To", "regex": "inf-sgl@.*" },
        { "condtype": "match-address", "key": "From", "regex": ".*@allowed-users.de", "error": "Your 'From' address is not authorized to post on the ${mailing_list_name} mailing list." }
      ],
      "actions": [
        { "action": "remove-header", "key": [ "Autocrypt", "DKIM-Signature", "Reply-To", "Return-Path", "X-Original-To", "Delivered-To", "Authentication-Results" ] },
        { "action": "set-address", "key": "Reply-To", "value": [ [ "My Mailing List", "inf-sgl@my-mailserver.de" ] ] },
        { "action": "set-address", "key": "From", "value": [ [ "My Mailing List", "mailinglist@my-mailserver.de" ] ] },
        { "action": "set-address", "key": "To", "value": [ [ "My Mailing List", "mailinglist@my-mailserver.de" ] ] },
        { "action": "set-header", "key": "List-Id", "value": "inf-sgl@my-mailserver.de" },
        { "action": "set-address", "key": "Bcc", "value": [ [ "Admin One", "admin1@foo.org"], [ "Admin Two", "admin2@bar.com" ] ] },
        { "action": "deliver", "via": "smtp://127.0.0.1" }
      ]
    }
  ]
}
```

Note that the first two mailing list configurations are very similar. The only
difference is that they match different `To` addresses and, therefore,
constitute different lists (with different recipients). When a new email comes
in, it is matched against all lists. If all conditions of a list apply, the
respective actions are executed.

This is the explanation of the conditions presented in the first mailing list:
  - The first condition of the first list checks that the `Message-ID` header
    is *not* ending in `@listenwicht>`, which may prevent mail loops.
  - The second condition also verifies that the `From` address does not include
    the word `bounce`. This is to prevent autoresponders (which respond to the
    `From` address, not the `Reply-To`) from being forwarded to the list.
  - The third condition verifies that the `From` address is valid (anything
    from `allowed-users.de` may post to the list). Note that this requires your
    ingress email treatment to be rigid (e.g., ensure that ingress mail is not
    delivered on softfail or that the SPF record requires hardfail or that you have
    alternative authentication in place).
  - The last condition of the first rule verifies that the user of the `To` address
    is either `inf23cs1`, `inf23cs`, or `inf23`. Note that the last condition of
    the second rule only differes in that it triggers when the `To` address is
    either `inf23cs2`, `inf23cs`, or `inf23`. This means that sending to
    `inf23cs1@my-mailserver.de` will trigger the first list,
    `inf23cs2@my-mailserver.de` will trigger the second list and either
    `inf23cs@my-mailserver.de` or `inf23@my-mailserver.de` will trigger *both*.

When a mailing list is triggered (because all conditions are satisfied), the
actions are executed:

  - Any header field in the enumeration is completely removed (e.g.,
    `Autocrypt`, `DKIM-Signature`, etc).
  - The `From` header field is rewritten to `Reply-To`. Anything that was
    previously a `From` now is a `Reply-To`.
  - The `From` header field is set to `mailinglist@my-mailserver.de` (which is
    a valid address that we are allowed to send mail from)
  - The `To` header field is set to that same value.
  - A `List-Id` header field is added
  - The recipients of the mail are all added as BCC.
  - The mail is sent via a SMTP connection to `127.0.0.1`.

Note that the example contains a third list which is slightly different in that
the `Reply-To` address equates to the mailing list address. This has the effect
that any reply automatically goes to all participants of the mailing list. In
contrast, a reply on the first or seconds list only goes to the original
sender.


## Usage: listenwicht setup
Once you have a configuration file, you can validate the behavior by using the
listenwicht CLI `display` command:

```
$ listenwicht display example_mails/silent_discard_autoresponder
Processing mail in example_mails/silent_discard_autoresponder
Matching condition: MatchHeader field "Message-ID" does NOT match regex "<.*@listenwicht>"
Matching condition: MatchAddress field "To" does NOT match regex ".*bounce.*"
Matching condition: MatchAddress field "To" matches regex "inf(23cs1|23cs|23)@.*"
Condition result in mailing list 23CS1: condition verification failed, silently discarding

Matching condition: MatchHeader field "Message-ID" does NOT match regex "<.*@listenwicht>"
Matching condition: MatchAddress field "To" does NOT match regex ".*bounce.*"
Matching condition: MatchAddress field "To" matches regex "inf(23cs2|23cs|23)@.*"
Condition result in mailing list 23CS2: condition verification failed, silently discarding

Matching condition: MatchHeader field "Message-ID" does NOT match regex "<.*@listenwicht>"
Matching condition: MatchAddress field "To" does NOT match regex ".*bounce.*"
Matching condition: MatchAddress field "To" matches regex "inf-sgl@.*"
Condition result in mailing list SGL: condition verification failed, silently discarding

========================================================================================================================
```

You can see that the incoming mail triggered none of the three lists, so it
would be silently discarded. You can also see that the failing condition in all
three cases was the `MatchAddress` of the `To` header field. This means the
sender simply posted to a non-existent mailing list.

Once you have confidence that your configuration is sound, you can use the
`daemon` facility of listenwicht to continuously watch for incoming mail and
resend them. You can also install a systemd unit for this. First, ensure your
user has lingering enabled (as root):

```
# loginctl enable-linger mailinglist
```

Then, as user `mailinglist`, create a config for example at
`~/.config/listenwicht.json` and install the systemd unit:

```
$ listenwicht systemd --install --config-file ~/.config/listenwicht.json /var/spool/mail/mailinglist
```

That's it!

## License
GNU GPL-3.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/johndoe31415/listenwicht",
    "name": "listenwicht",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "mailing, list",
    "author": "Johannes Bauer",
    "author_email": "joe@johannes-bauer.com",
    "download_url": "https://files.pythonhosted.org/packages/43/90/7640247939ae54e5414e3518f9d1bf20d0fd36982b6e8d56c87709ad42f3/listenwicht-0.0.2.tar.gz",
    "platform": null,
    "description": "# listenwicht\nlistenwicht is a Python-based, highly flexible client that is able to resend\nemail according to static redistribution rules. In particular, compared to the\nexceptionally simple forwarding configuration, listenwicht actually has an MTA\ndeliver the mail locally in mboxdir format, where they are picked up and\nresent. Before resending, they can be rewritten. This is useful when your MTA\nis not a valid according to the set SPF rules. It allows resending from a\nSPF-legal \"From\" address.\n\n\n## Dependencies\nlistenwicht depends on the command-line utility `inotifywatch` in order to\nmonitor the list directory.\n\n\n## Caveats\nlistenwicht monitors in the `new/` subdirectory for `CREATE` and `MOVE_TO`\npermissions. This is needed because while in newer systems, `MOVE_TO` is called\nwhile on older systems `CREATE` (without any `MODIFY` or `WRITE_CLOSE`) is\nused. This means that when testing and writing a file to the `new/`\nsubdirectory in a non-atomic fashion (e.g., `echo foo >mail.txt`), listenwicht\nwill misbehave (it might probably try to parse an empty/partial file).\n\n\n## Usage: MTA setup\nFirst, configure your MTA to perform delivery of emails in a maildir spool\ndirectory. For example, in `main.cf`:\n\n```\nmail_spool_directory = /var/spool/mail/\n```\n\nNote the trailing slash for the spool directory, which forces maildir mode.\n\nThen, typically, you will want to redirect traffic to a virtual user. For\nexample, consider there is a `mailinglist` user that listenwicht will run\nunder. Then, install the Postfix-PCRE module and create a\n`/etc/postfix/virtual.pcre` file:\n\n```\n/^inf[0-9][0-9]...?[0-9]@my-mailserver\\.de$/   mailinglist\n/^inf-sgl@my-mailserver\\.de$/                  mailinglist\n```\n\nThis will redirect all traffic to these particular addresses to the maildir\n`/var/spool/mail/mailinglist/new`. Enable that PCRE virtual address table by\nputting in your `main.cf`:\n\n```\nvirtual_alias_maps = pcre:/etc/postfix/virtual.pcre\n```\n\nLastly, if you want to filter by `From` addresses, make sure SPF is enabled in\nyour Postfix configuration for local deliveries.\n\nAt this stage, try if you can send mails to postfix and they get accepted. For\nexample, using the above configuration, write an email to\n`inf99abc4@my-mailserver.de` and check the logs to see everything works\nproperly (SPF configuration, local delivery in the expected directory).\n\n\n## Usage: listenwicht configuration\nWhen the mails are correctly delivered, you need to setup a listenwicht\nconfiguration file, which is in JSON format. This is an example file, provided\nin `listenwicht.json`:\n\n```json\n{\n  \"bounces\": {\n    \"via\": \"smtp://127.0.0.1\",\n    \"from\": [ \"listenwicht Bounces\", \"mailinglist-bounce@my-mailserver.de\" ],\n    \"admin_email\": \"admin@my-mailserver.de\"\n  },\n  \"mailing_lists\": [\n    {\n      \"name\": \"23CS1\",\n      \"conditions\": [\n        { \"condtype\": \"match-header\", \"key\": \"Message-ID\", \"regex\": \"<.*@listenwicht>\", \"invert\": true },\n        { \"condtype\": \"match-address\", \"key\": \"To\", \"regex\": \".*bounce.*\", \"invert\": true },\n        { \"condtype\": \"match-address\", \"key\": \"To\", \"regex\": \"inf(23cs1|23cs|23)@.*\" },\n        { \"condtype\": \"match-address\", \"key\": \"From\", \"regex\": \".*@allowed-users.de\", \"error\": \"Your 'From' address is not authorized to post on the ${mailing_list_name} mailing list.\" }\n      ],\n      \"actions\": [\n        { \"action\": \"remove-header\", \"key\": [ \"Autocrypt\", \"DKIM-Signature\", \"Reply-To\", \"Return-Path\", \"X-Original-To\", \"Delivered-To\", \"Authentication-Results\" ] },\n        { \"action\": \"rename-header\", \"old\": \"From\", \"new\": \"Reply-To\" },\n        { \"action\": \"set-address\", \"key\": \"From\", \"value\": [ [ \"My Mailing List\", \"mailinglist@my-mailserver.de\" ] ] },\n        { \"action\": \"set-address\", \"key\": \"To\", \"value\": [ [ \"My Mailing List\", \"mailinglist@my-mailserver.de\" ] ] },\n        { \"action\": \"set-header\", \"key\": \"List-Id\", \"value\": \"inf23cs1@my-mailserver.de\" },\n        { \"action\": \"set-address\", \"key\": \"Bcc\", \"value\": [ [ \"Cee Ess One\", \"cs1@foobar.com\"], [ \"Next cs1 usr\", \"other@cs1.de\" ] ] },\n        { \"action\": \"deliver\", \"via\": \"smtp://127.0.0.1\" }\n      ]\n    },\n    {\n      \"name\": \"23CS2\",\n      \"conditions\": [\n        { \"condtype\": \"match-header\", \"key\": \"Message-ID\", \"regex\": \"<.*@listenwicht>\", \"invert\": true },\n        { \"condtype\": \"match-address\", \"key\": \"To\", \"regex\": \".*bounce.*\", \"invert\": true },\n        { \"condtype\": \"match-address\", \"key\": \"To\", \"regex\": \"inf(23cs2|23cs|23)@.*\" },\n        { \"condtype\": \"match-address\", \"key\": \"From\", \"regex\": \".*@allowed-users.de\", \"error\": \"Your 'From' address is not authorized to post on the ${mailing_list_name} mailing list.\" }\n      ],\n      \"actions\": [\n        { \"action\": \"remove-header\", \"key\": [ \"Autocrypt\", \"DKIM-Signature\", \"Reply-To\", \"Return-Path\", \"X-Original-To\", \"Delivered-To\", \"Authentication-Results\" ] },\n        { \"action\": \"rename-header\", \"old\": \"From\", \"new\": \"Reply-To\" },\n        { \"action\": \"set-address\", \"key\": \"From\", \"value\": [ [ \"My Mailing List\", \"mailinglist@my-mailserver.de\" ] ] },\n        { \"action\": \"set-address\", \"key\": \"To\", \"value\": [ [ \"My Mailing List\", \"mailinglist@my-mailserver.de\" ] ] },\n        { \"action\": \"set-header\", \"key\": \"List-Id\", \"value\": \"inf23cs2@my-mailserver.de\" },\n        { \"action\": \"set-address\", \"key\": \"Bcc\", \"value\": [ [ \"CS2 user\", \"cs2-user@foo.org\"], [ \"Other CS2 User\", \"cs2-user-2@invalid.com\" ] ] },\n        { \"action\": \"deliver\", \"via\": \"smtp://127.0.0.1\" }\n      ]\n    },\n    {\n      \"name\": \"SGL\",\n      \"conditions\": [\n        { \"condtype\": \"match-header\", \"key\": \"Message-ID\", \"regex\": \"<.*@listenwicht>\", \"invert\": true },\n        { \"condtype\": \"match-address\", \"key\": \"To\", \"regex\": \".*bounce.*\", \"invert\": true },\n        { \"condtype\": \"match-address\", \"key\": \"To\", \"regex\": \"inf-sgl@.*\" },\n        { \"condtype\": \"match-address\", \"key\": \"From\", \"regex\": \".*@allowed-users.de\", \"error\": \"Your 'From' address is not authorized to post on the ${mailing_list_name} mailing list.\" }\n      ],\n      \"actions\": [\n        { \"action\": \"remove-header\", \"key\": [ \"Autocrypt\", \"DKIM-Signature\", \"Reply-To\", \"Return-Path\", \"X-Original-To\", \"Delivered-To\", \"Authentication-Results\" ] },\n        { \"action\": \"set-address\", \"key\": \"Reply-To\", \"value\": [ [ \"My Mailing List\", \"inf-sgl@my-mailserver.de\" ] ] },\n        { \"action\": \"set-address\", \"key\": \"From\", \"value\": [ [ \"My Mailing List\", \"mailinglist@my-mailserver.de\" ] ] },\n        { \"action\": \"set-address\", \"key\": \"To\", \"value\": [ [ \"My Mailing List\", \"mailinglist@my-mailserver.de\" ] ] },\n        { \"action\": \"set-header\", \"key\": \"List-Id\", \"value\": \"inf-sgl@my-mailserver.de\" },\n        { \"action\": \"set-address\", \"key\": \"Bcc\", \"value\": [ [ \"Admin One\", \"admin1@foo.org\"], [ \"Admin Two\", \"admin2@bar.com\" ] ] },\n        { \"action\": \"deliver\", \"via\": \"smtp://127.0.0.1\" }\n      ]\n    }\n  ]\n}\n```\n\nNote that the first two mailing list configurations are very similar. The only\ndifference is that they match different `To` addresses and, therefore,\nconstitute different lists (with different recipients). When a new email comes\nin, it is matched against all lists. If all conditions of a list apply, the\nrespective actions are executed.\n\nThis is the explanation of the conditions presented in the first mailing list:\n  - The first condition of the first list checks that the `Message-ID` header\n    is *not* ending in `@listenwicht>`, which may prevent mail loops.\n  - The second condition also verifies that the `From` address does not include\n    the word `bounce`. This is to prevent autoresponders (which respond to the\n    `From` address, not the `Reply-To`) from being forwarded to the list.\n  - The third condition verifies that the `From` address is valid (anything\n    from `allowed-users.de` may post to the list). Note that this requires your\n    ingress email treatment to be rigid (e.g., ensure that ingress mail is not\n    delivered on softfail or that the SPF record requires hardfail or that you have\n    alternative authentication in place).\n  - The last condition of the first rule verifies that the user of the `To` address\n    is either `inf23cs1`, `inf23cs`, or `inf23`. Note that the last condition of\n    the second rule only differes in that it triggers when the `To` address is\n    either `inf23cs2`, `inf23cs`, or `inf23`. This means that sending to\n    `inf23cs1@my-mailserver.de` will trigger the first list,\n    `inf23cs2@my-mailserver.de` will trigger the second list and either\n    `inf23cs@my-mailserver.de` or `inf23@my-mailserver.de` will trigger *both*.\n\nWhen a mailing list is triggered (because all conditions are satisfied), the\nactions are executed:\n\n  - Any header field in the enumeration is completely removed (e.g.,\n    `Autocrypt`, `DKIM-Signature`, etc).\n  - The `From` header field is rewritten to `Reply-To`. Anything that was\n    previously a `From` now is a `Reply-To`.\n  - The `From` header field is set to `mailinglist@my-mailserver.de` (which is\n    a valid address that we are allowed to send mail from)\n  - The `To` header field is set to that same value.\n  - A `List-Id` header field is added\n  - The recipients of the mail are all added as BCC.\n  - The mail is sent via a SMTP connection to `127.0.0.1`.\n\nNote that the example contains a third list which is slightly different in that\nthe `Reply-To` address equates to the mailing list address. This has the effect\nthat any reply automatically goes to all participants of the mailing list. In\ncontrast, a reply on the first or seconds list only goes to the original\nsender.\n\n\n## Usage: listenwicht setup\nOnce you have a configuration file, you can validate the behavior by using the\nlistenwicht CLI `display` command:\n\n```\n$ listenwicht display example_mails/silent_discard_autoresponder\nProcessing mail in example_mails/silent_discard_autoresponder\nMatching condition: MatchHeader field \"Message-ID\" does NOT match regex \"<.*@listenwicht>\"\nMatching condition: MatchAddress field \"To\" does NOT match regex \".*bounce.*\"\nMatching condition: MatchAddress field \"To\" matches regex \"inf(23cs1|23cs|23)@.*\"\nCondition result in mailing list 23CS1: condition verification failed, silently discarding\n\nMatching condition: MatchHeader field \"Message-ID\" does NOT match regex \"<.*@listenwicht>\"\nMatching condition: MatchAddress field \"To\" does NOT match regex \".*bounce.*\"\nMatching condition: MatchAddress field \"To\" matches regex \"inf(23cs2|23cs|23)@.*\"\nCondition result in mailing list 23CS2: condition verification failed, silently discarding\n\nMatching condition: MatchHeader field \"Message-ID\" does NOT match regex \"<.*@listenwicht>\"\nMatching condition: MatchAddress field \"To\" does NOT match regex \".*bounce.*\"\nMatching condition: MatchAddress field \"To\" matches regex \"inf-sgl@.*\"\nCondition result in mailing list SGL: condition verification failed, silently discarding\n\n========================================================================================================================\n```\n\nYou can see that the incoming mail triggered none of the three lists, so it\nwould be silently discarded. You can also see that the failing condition in all\nthree cases was the `MatchAddress` of the `To` header field. This means the\nsender simply posted to a non-existent mailing list.\n\nOnce you have confidence that your configuration is sound, you can use the\n`daemon` facility of listenwicht to continuously watch for incoming mail and\nresend them. You can also install a systemd unit for this. First, ensure your\nuser has lingering enabled (as root):\n\n```\n# loginctl enable-linger mailinglist\n```\n\nThen, as user `mailinglist`, create a config for example at\n`~/.config/listenwicht.json` and install the systemd unit:\n\n```\n$ listenwicht systemd --install --config-file ~/.config/listenwicht.json /var/spool/mail/mailinglist\n```\n\nThat's it!\n\n## License\nGNU GPL-3.\n",
    "bugtrack_url": null,
    "license": "gpl-3.0",
    "summary": "Flexible Python-based mailing list daemon",
    "version": "0.0.2",
    "project_urls": {
        "Download": "https://github.com/johndoe31415/listenwicht/archive/v0.0.2.tar.gz",
        "Homepage": "https://github.com/johndoe31415/listenwicht"
    },
    "split_keywords": [
        "mailing",
        " list"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "43907640247939ae54e5414e3518f9d1bf20d0fd36982b6e8d56c87709ad42f3",
                "md5": "92c0dcff66194c1c197714127021005c",
                "sha256": "b53f7b43ba732b7c7d814daa95bf301a8f78e04a34df7ed9c515a2878d9e27e0"
            },
            "downloads": -1,
            "filename": "listenwicht-0.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "92c0dcff66194c1c197714127021005c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 18060,
            "upload_time": "2025-10-09T12:11:13",
            "upload_time_iso_8601": "2025-10-09T12:11:13.816353Z",
            "url": "https://files.pythonhosted.org/packages/43/90/7640247939ae54e5414e3518f9d1bf20d0fd36982b6e8d56c87709ad42f3/listenwicht-0.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-09 12:11:13",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "johndoe31415",
    "github_project": "listenwicht",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "listenwicht"
}
        
Elapsed time: 2.59281s