SkillAgentSearch skills...

Idmail

An email alias and account management interface for self-hosted mailservers

Install / Use

/learn @oddlama/Idmail
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Installation | Building | API Endpoints | Stalwart configuration | Provisioning

<p float="left"> <img src="https://github.com/user-attachments/assets/d48ed681-950d-41f3-bce9-dac1acf09bae" height="250" /> <img src="https://github.com/user-attachments/assets/58e01aab-2eb0-4dd4-bf44-4d53296731a4" height="250" /> </p>

[!IMPORTANT] Sent and recv counts require MTA-specific hook setups that are currently not documented!

📧 idmail

Idmail is an email alias and account management interface for self-hosted mailservers, which you can use to hide your true email address from online services. This is NOT an email forwarding service like addy.io! Idmail is a frontend to a sqlite database which contains a table of mailboxes and aliases to be consumed by a mailsever like Stalwart, maddy, Postfix or others. The following features are available:

  • 🧑,🌐 Manage user accounts and domains (as an admin)
  • 📫,🕵️ Manage mailboxes and aliases (per user)
  • 🔄 Generate random aliases
  • 🔑 API endpoint allows integration with password managers (Bitwarden, ...)
  • 📈 Track sent/received statistics per alias
  • 🌌 Per-domain catch-all
  • 🌟 Provisioning support

If you login with a mailbox account, you can change the mailbox password and manage its aliases. Mailbox accounts can use the API to create new aliases with the API token from their settings page. Logging in with a user account (these have no @domain.tld suffix), you can additionally create new mailboxes and manage any domains assigned to you by an admin.

You will have to integrate this with a mailserver that supports querying an sqlite database for mailbox accounts and aliases. We recommend using Stalwart and provide the necessary queries for it, but any other server will work fine if you adjust the queries accordingly.

🚀 Installation

❓ Other distributions

Refer to the second part of the Building section for details on how to build and deploy this application.

❄️ NixOS

Installation under NixOS is straightforward. This repository provides an overlay and NixOS module for simple deployment. First, add this repository flake input and import the module on your NixOS system(s):

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    idmail.url = "github:oddlama/idmail";
    idmail.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, nixpkgs, idmail }: {
    # Add the module to your system(s)
    nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ./configuration.nix
        idmail.nixosModules.default
      ];
    };
  };
}

Afterwards, simply enable the service in your configuration and proxy the web interface:

{
  services.idmail.enable = true;

  services.nginx.virtualHosts."alias.example.com" = {
    forceSSL = true;
    locations."/" = {
      proxyPass = "http://localhost:3000";
      proxyWebsockets = true;
    };
  };
}

The database will be available under /var/lib/idmail/idmail.db for consumption by other services, the service listens on 127.0.0.1:3000 by default. The example above uses nginx to reverse proxy the application. If the admin user was not provisioned, it will be recovered on start and a generated password will be printed to the journal.

You can provision anything by using the services.idmail.provision configuration. See Provisioning or view the module source for more information.

{
  services.idmail.provision = {
    enable = true;
    users.admin = {
      admin = true;
      # Generate hash with `echo -n "password" | nix run nixpkgs#libargon2 -- somerandomsalt -id`
      password_hash = "$argon2id$v=19$m=4096,t=3,p=1$YXJnbGluYXJsZ2luMjRvaQ$DXdfVNRSFS1QSvJo7OmXIhAYYtT/D92Ku16DiJwxn8U";
      #password_hash = "%{file:/path/to/secret}%"; # Or read a file at runtime
    };
    domains."example.com" = {
      owner = "admin";
      public = true;
    };
    mailboxes."me@example.com" = {
      password_hash = "$argon2id$v=19$m=4096,t=3,p=1$YXJnbGluYXJsZ2luMjRvaQ$fiD9Bp3KidVI/E+mGudu6+h9XmF9TU9Bx4VGX0PniDE";
      owner = "admin";
      #api_token = "VC0lZ6O49nfxU4oK0KbahlSMsqBFiHyYFGUQvzzki6ky5mSM"; # Please don't hardcode api tokens
      api_token = "%{file:/path/to/secret}%";
    };
    aliases."somealias@example.com" = {
      target = "me@example.com";
      owner = "me@example.com";
      comment = "Used for xyz";
    };
  };
}

For a working in-the-field configuration, feel free to have a look at my personal repository. Specifically stalwart-mail.nix and idmail.nix.

🧰 Building

This project is made to be build via nix. If you have nix installed, the project can be built simply by running:

nix build github:oddlama/idmail

If you want to build it yourself instead, you can do so by executing:

export RUSTFLAGS="--cfg=web_sys_unstable_apis"
export LEPTOS_ENV="PROD"
cargo leptos build --release -vvv

You can then run the server like this:

export LEPTOS_SITE_ADDR="0.0.0.0:3000" # only if you want to change listen address or port
./target/release/idmail

You can host binary in any way you prefer (Docker, systemd services, ...). Afterwards, configure your mailserver to utilize the database for lookups (see Stalwart configuration) and optionally configure your password manager to use one of the provided API Endpoints. If the admin user doesn't exist on start, it will be recovered and a generated password will be printed to stdout.

☁️ API Endpoints

API endpoints are provided which allow you to generate random aliases, compatible with those provided by addy.io (AnonAddy) or SimpleLogin. This means you can use it with a password manager to automatically create aliases for your logins. Aliases will be generated via the faker_rand Username generator, and may produce the following results:

<details> <summary>Example of generated email addresses</summary>
ycrona62@example.com
eunicecole@example.com
hschulist@example.com
rwalter25@example.com
ydach15@example.com
pansywisozk@example.com
uroob30@example.com
earlinebayer@example.com
zhoppe26@example.com
lauramayert@example.com
quinnnitzsche@example.com
whauck98@example.com
iglover5@example.com
stancollins@example.com
fchamplin08@example.com
bmurphy2@example.com
ywelch4@example.com
erolfson@example.com
ldicki2@example.com
margarettlueilwitz@example.com
eusebioernser@example.com
clynch@example.com
seanoberbrunner@example.com
arielstiedemann@example.com
zhamill3@example.com
clueilwitz76@example.com
bonitajenkins@example.com
leannsanford@example.com
vkirlin50@example.com
bobernier@example.com
jazminbeatty@example.com
</details>

There are two different API endpoints available:

  • addy.io compatible: Allows you to select a domain. A random avaliable domain is selected by the server if left empty or filled with the special value random.
  • SimpleLogin compatible: Does not allow selecting a domain, so a random available domain is always selected

Both endpoints always generate the same random usernames and ignore any format options in case the original API provides those. The required API token can be generated on the settings page when logging into the Web interface as a mailbox account.

<details> <summary>

addy.io compatible endpoint

</summary>
  • Url: https://idmail.example.com/api/v1/aliases

  • Method: POST

  • Token: Via header Authorization: Bearer {token}

  • Success: 201

  • In Bitwarden, just use idmail.example.com as the endpoint.

<details> <summary>Example request and response (curl)</summary>

Request:

curl -X POST \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -H "Authorization: Bearer {token}" \
    --data '{"domain":"example.com","description":"An optional comment added to the entry"}' \
    localhost:3000/api/v1/aliases

Response:

{
    "data": {
        "active": true,
        "aliasable_id": null,
        "aliasable_type": null,
        "created_at": "2000-01-01 00:00:00",
        "deleted_at": null,
        "description": "An optional comment added to the entry",
        "domain": "example.com",
        "email": "zhoppe26@example.com",
        "emails_blocked": 0,
        "emails_forwarded": 0,
        "emails_replied": 0,
        "emails_sent": 0,
        "extension": null,
        "from_name": null,
        "id": "00000000-0000-0000-0000-000000000000",
        "last_blocked": null,
        "last_forwarded": "2000-01-01 00:00:00",
        "last_replied": null,
        "last_sent": null,
        "local_part": "00000000-0000-0000-0000-000000000000",
        "recipients": [],
        "updated_at": "2000-01-01 00:00:00",
        "user_id": "00000000-0000-0000-0000-000000000000"
    }
}
</details> </details> <details> <summary>

SimpleLogin compatible endpoint

</summary>
  • Url: https://idmail.example.com/api/alias/random/new

  • Method: POST

  • Token: Via header Authorization: {token}

  • Success: 201

  • In Bitwarden, just use idmail.example.com as the endpoint.

<details> <summary>Example request and response (curl)</summary>

Request:

curl -X POST \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -H "Authorization: {token}" \
    --data '{"note":"A comment added to the entry"}' \
    localhost:3000/api/alias/random/new

Response:

{
    "alias": "
View on GitHub
GitHub Stars25
CategoryDevelopment
Updated4d ago
Forks6

Languages

Rust

Security Score

95/100

Audited on Mar 25, 2026

No findings