1
0
Fork
You've already forked mailpot
0
project goal: extensible, flexible mailing list manager
  • Rust 86.1%
  • HTML 9.9%
  • M4 1.7%
  • Pawn 1.3%
  • Python 0.5%
  • Other 0.5%
Manos Pitsidianakis 228240e52c
Fix list_thread not working with stripped carets
Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
2025年12月07日 16:33:22 +02:00
.cargo Update various dependencies 2024年06月08日 19:47:57 +03:00
.github .github: replace ~ with /home/runner 2023年11月02日 15:22:40 +02:00
docs cli: add --fix-message-ids repair lint 2025年12月07日 14:26:07 +02:00
mailpot Fix list_thread not working with stripped carets 2025年12月07日 16:33:22 +02:00
mailpot-archives Fix double caret stripping of message ids 2025年12月05日 11:33:37 +02:00
mailpot-cli cli: add --fix-message-ids repair lint 2025年12月07日 14:26:07 +02:00
mailpot-http Update my e-mail address in Cargo.toml files 2025年12月05日 11:04:29 +02:00
mailpot-tests Update my e-mail address in Cargo.toml files 2025年12月05日 11:04:29 +02:00
mailpot-web Fix list_thread not working with stripped carets 2025年12月07日 16:33:22 +02:00
.gitignore Initial commit 2022年05月07日 18:17:03 +03:00
Cargo.lock Re-arrange wildcard imports and public exports 2025年12月05日 11:04:29 +02:00
Cargo.toml Rename workspace dirs to their actual crate names 2024年02月13日 09:53:24 +02:00
CODE_OF_CONDUCT.md Add CODE_OF_CONDUCT.md, CONTRIBUTING.md 2023年04月18日 14:45:44 +03:00
CONTRIBUTING.md Add CODE_OF_CONDUCT.md, CONTRIBUTING.md 2023年04月18日 14:45:44 +03:00
LICENSE Initial commit 2022年05月07日 18:17:03 +03:00
Makefile Makefile: echo command before running it 2025年12月01日 22:29:29 +02:00
README.md cli: Add set-message-filter-setting list subcommand 2024年09月01日 20:51:13 +03:00
rustfmt.toml web: add typed paths 2023年04月15日 17:32:10 +03:00

mailpot - mailing list manager

Latest Version Coverage docs.rs Top Language License

i️ Interested in contributing? Consult CONTRIBUTING.md.

crates:

  • mailpot the core library
  • mailpot-cli a command line tool to manage lists
  • mailpot-web an axum based web server capable of serving archives and authenticating list owners and members
  • mailpot-archives static web archive generation or with a dynamic http server
  • mailpot-http a REST http server to manage lists

Features

  • easy setup
  • extensible through Rust API as a library
  • basic management through CLI tool
  • optional lightweight web archiver (static and dynamic)
  • useful for both newsletters, communities and for static article comments

Roadmap

  • extensible through HTTP REST API as an HTTP server, with webhooks

Initial setup

Create a configuration file and a database:

$ mkdir -p /home/user/.config/mailpot
$ export MPOT_CONFIG=/home/user/.config/mailpot/config.toml
$ cargo run --bin mpot -- sample-config > "$MPOT_CONFIG"
$ # edit config and set database path e.g. "/home/user/.local/share/mailpot/mpot.db"
$ cargo run --bin mpot -- -c "$MPOT_CONFIG" list-lists
No lists found.

This creates the database file in the configuration file as if you executed the following:

$ sqlite3 /home/user/.local/share/mailpot/mpot.db < ./core/src/schema.sql

Examples

% mpot help
GNU Affero version 3 or later <https://www.gnu.org/licenses/>
Tool for mailpot mailing list management.
Usage: mpot [OPTIONS] <COMMAND>
Commands:
 sample-config
 Prints a sample config file to STDOUT
 dump-database
 Dumps database data to STDOUT
 list-lists
 Lists all registered mailing lists
 list
 Mailing list management
 create-list
 Create new list
 post
 Post message from STDIN to list
 flush-queue
 Flush outgoing e-mail queue
 error-queue
 Mail that has not been handled properly end up in the error queue
 queue
 Mail that has not been handled properly end up in the error queue
 import-maildir
 Import a maildir folder into an existing list
 update-postfix-config
 Update postfix maps and master.cf (probably needs root permissions)
 print-postfix-config
 Print postfix maps and master.cf entry to STDOUT
 accounts
 All Accounts
 account-info
 Account info
 add-account
 Add account
 remove-account
 Remove account
 update-account
 Update account info
 repair
 Show and fix possible data mistakes or inconsistencies
 help
 Print this message or the help of the given subcommand(s)
Options:
 -d, --debug
 Print logs
 -c, --config <CONFIG>
 Configuration file to use
 -q, --quiet
 Silence all output
 -v, --verbose...
 Verbose mode (-v, -vv, -vvv, etc)
 -t, --ts <TS>
 Debug log timestamp (sec, ms, ns, none)
 -h, --help
 Print help (see a summary with '-h')
 -V, --version
 Print version

Receiving mail

$ cat list-request.eml | cargo run --bin mpot -- -vvvvvv post --dry-run
output
TRACE - Received envelope to post: Envelope {
 Subject: "unsubscribe",
 Date: "2020年8月04日 14:10:13 +0300",
 From: [
 Address::Mailbox {
 display_name: "Mxxxx Pxxxxxxxxxxxx",
 address_spec: "exxxxx@localhost",
 },
 ],
 To: [
 Address::Mailbox {
 display_name: "",
 address_spec: "test-announce+request@localhost",
 },
 ],
 Message-ID: "<ejduu.fddf8sgen4j7@localhost>",
 In-Reply-To: None,
 References: None,
 Hash: 12581897380059220314,
}
TRACE - unsubscribe action for addresses [Address::Mailbox { display_name: "Mxxxx Pxxxxxxxxxxxx", address_spec: "exxxxx@localhost" }] in list [#2 test-announce] test announcements <test-announce@localhost>
TRACE - Is post related to list [#1 test] Test list <test@localhost>? false
$ cat list-post.eml | cargo run --bin mpot -- -vvvvvv post --dry-run
output
TRACE - Received envelope to post: Envelope {
 Subject: "[test-announce] new test releases",
 Date: "2020年8月04日 14:10:13 +0300",
 From: [
 Address::Mailbox {
 display_name: "Mxxxx Pxxxxxxxxxxxx",
 address_spec: "exxxxx@localhost",
 },
 ],
 To: [
 Address::Mailbox {
 display_name: "",
 address_spec: "test-announce@localhost",
 },
 ],
 Message-ID: "<ejduu.sddf8sgen4j7@localhost>",
 In-Reply-To: None,
 References: None,
 Hash: 10220641455578979007,
}
TRACE - Is post related to list [#1 test] Test list <test@localhost>? false
TRACE - Is post related to list [#2 test-announce] test announcements <test-announce@localhost>? true
TRACE - Examining list "test announcements" <test-announce@localhost>
TRACE - List subscriptions [
 ListSubscription {
 list: 2,
 address: "exxxxx@localhost",
 name: None,
 digest: false,
 hide_address: false,
 receive_duplicates: false,
 receive_own_posts: true,
 receive_confirmation: true,
 enabled: true,
 },
]
TRACE - Running FixCRLF filter
TRACE - Running PostRightsCheck filter
TRACE - Running AddListHeaders filter
TRACE - Running FinalizeRecipients filter
TRACE - examining subscription ListSubscription { list: 2, address: "exxxxx@localhost", name: None, digest: false, hide_address: false, receive_duplicates: false, receive_own_posts: true, receive_confirmation: true, enabled: true }
TRACE - subscription is submitter
TRACE - subscription gets copy
TRACE - result Ok(
 Post {
 list: MailingList {
 pk: 2,
 name: "test announcements",
 id: "test-announce",
 address: "test-announce@localhost",
 description: None,
 archive_url: None,
 },
 from: Address::Mailbox {
 display_name: "Mxxxx Pxxxxxxxxxxxx",
 address_spec: "exxxxx@localhost",
 },
 subscriptions: 1,
 bytes: 851,
 policy: None,
 to: [
 Address::Mailbox {
 display_name: "",
 address_spec: "test-announce@localhost",
 },
 ],
 action: Accept {
 recipients: [
 Address::Mailbox {
 display_name: "",
 address_spec: "exxxxx@localhost",
 },
 ],
 digests: [],
 },
 },
)

Using mailpot as a library

usemailpot::{models::*,*};usetempfile::TempDir;lettmp_dir=TempDir::new().unwrap();letdb_path=tmp_dir.path().join("mpot.db");letconfig=Configuration{send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),db_path: db_path.clone(),data_path: tmp_dir.path().to_path_buf(),administrators: vec!["myaddress@example.com".to_string()],};letdb=Connection::open_or_create_db(config)?.trusted();// Create a new mailing list
letlist_pk=db.create_list(MailingList{pk: 0,name: "foobar chat".into(),id: "foo-chat".into(),address: "foo-chat@example.com".into(),description: None,topics: vec![],archive_url: None,})?.pk;db.set_list_post_policy(PostPolicy{pk: 0,list: list_pk,announce_only: false,subscription_only: true,approval_needed: false,open: false,custom: false,},)?;// Drop privileges; we can only process new e-mail and modify subscriptions from now on.
letmutdb=db.untrusted();assert_eq!(db.list_subscriptions(list_pk)?.len(),0);assert_eq!(db.list_posts(list_pk,None)?.len(),0);// Process a subscription request e-mail
letsubscribe_bytes=b"From: Name <user@example.com>
To: <foo-chat+subscribe@example.com>
Subject: subscribe
Date: 2020年10月29日 13:58:16 +0000
Message-ID: <1@example.com>
";letenvelope=melib::Envelope::from_bytes(subscribe_bytes,None)?;db.post(&envelope,subscribe_bytes,/* dry_run */false)?;assert_eq!(db.list_subscriptions(list_pk)?.len(),1);assert_eq!(db.list_posts(list_pk,None)?.len(),0);// Process a post
letpost_bytes=b"From: Name <user@example.com>
To: <foo-chat@example.com>
Subject: my first post
Date: 2020年10月29日 14:01:09 +0000
Message-ID: <2@example.com>
Hello
";letenvelope=melib::Envelope::from_bytes(post_bytes,None).expect("Could not parse message");db.post(&envelope,post_bytes,/* dry_run */false)?;assert_eq!(db.list_subscriptions(list_pk)?.len(),1);assert_eq!(db.list_posts(list_pk,None)?.len(),1);#Ok::<(),Error>(())