Giter VIP home page Giter VIP logo

mailpot's Introduction

mailpot - mailing list manager

Latest Version Coverage docs.rs Top Language License

ℹī¸ 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: "Tue, 04 Aug 2020 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: "Tue, 04 Aug 2020 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

use mailpot::{models::*, *};
use tempfile::TempDir;

let tmp_dir = TempDir::new().unwrap();
let db_path = tmp_dir.path().join("mpot.db");
let config = 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!["[email protected]".to_string()],
};
let db = Connection::open_or_create_db(config)?.trusted();

// Create a new mailing list
let list_pk = db.create_list(MailingList {
    pk: 0,
    name: "foobar chat".into(),
    id: "foo-chat".into(),
    address: "[email protected]".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.
let mut db = 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
let subscribe_bytes = b"From: Name <[email protected]>
To: <[email protected]>
Subject: subscribe
Date: Thu, 29 Oct 2020 13:58:16 +0000
Message-ID: <[email protected]>

";
let envelope = 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
let post_bytes = b"From: Name <[email protected]>
To: <[email protected]>
Subject: my first post
Date: Thu, 29 Oct 2020 14:01:09 +0000
Message-ID: <[email protected]>

Hello
";
let envelope =
    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>(())

mailpot's People

Contributors

epilys avatar kevinschoon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

div72

mailpot's Issues

Parse DKIM header

See what headers are signed by reading the DKIM header to avoid messing with them.

Consider if migration to `axum-login` v0.7.0 is appropriate

Hi there,

I'm reaching out because we've recently released axum-login v0.7.0. This release replaces axum-sessions with tower-sessions, eliminating potential deadlocking issues, but also reimagines the axum-login API.

Because this is a significant breaking change, it may not make sense for all applications to migrate. On the other hand, future development will be on this new API and so I want to make sure crate consumers are aware.

I'm also happy to help answer any questions or otherwise be of assistance to folks looking to migrate.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤ī¸ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.