A vertical email slice written in Go
Go to file
Nick Thomas 08d80cc661
Update README.md with a link to the features board
2018-07-02 00:16:51 +01:00
cmd/crockery Convert from BoltDB to Maildir storage for emails 2018-06-28 00:01:23 +01:00
internal imap: ListMessages: handle body viewing, etc 2018-06-28 01:10:31 +01:00
vendor Update vendor/ 2018-06-28 01:09:56 +01:00
.gitignore Hack in command-line specification of domain, cert and key 2018-03-05 19:53:48 +00:00
DESIGN.md Convert from BoltDB to Maildir storage for emails 2018-06-28 00:01:23 +01:00
Gopkg.lock Update vendor/ 2018-06-28 01:09:56 +01:00
Gopkg.toml Update vendor/ 2018-06-28 01:09:56 +01:00
LICENSE.md Add AGPLv3 licensing 2018-07-01 23:56:32 +01:00
Makefile Convert from BoltDB to Maildir storage for emails 2018-06-28 00:01:23 +01:00
README.md Update README.md with a link to the features board 2018-07-02 00:16:51 +01:00



Simple self-hosted email

Not all features are implemented. See the features board for more details of current status.


  • Email!
  • Devoted to the task of being a vertically-integrated email solution for a single domain
  • SMTP+IMAP email, autodiscovery, and bundled HTTP(S) webmail client
  • Can get its own valid TLS certificates via LE, or use supplied ones
  • Built-in anti-spam & anti-virus measures
  • Built-in DKIM support
  • Built-in DMARC support
  • Can tell you what DNS records you need, and check them for validity
  • Multiple email accounts for your domain
  • A "master" wildcard account (if desired)
  • Simple import from GMail, etc
  • Simple export to GMail, etc
  • Nice, fast search
  • Interact with crockery with simple, natural-ish emails to do things
    • SMTP TLS verification - enabled by default
    • Try to email foo@shady.net - verification fails, email marked pending, fail in 7 days
    • Crockery emails user, "Yo. We can't send this email securely. Here are your options:"
    • User hits reply-to (goes to unique email address on same domain) saying what to do:
      • Cancel
      • Retry
      • Send just this email
      • Whitelist shady.net (pins certificate)
    • What other interactions might we like?
    • Use HTTPS links instead of emails?

What not

  • JMAP. Not today.
  • Bring your own X (where X is MTA, IMAP server, database, etc, etc)
  • Multiple-domain support (maaaaaaaaaaaaybe later)
  • CalDAV/Carddav (yet)
  • Externally sourced accounts (yet)
  • Sending email without having an account
  • Managesieve (for now)


Email architecture is really complicated, and setting up a mail server of your own is painful. Various projects exist to try to make it easier, eg:

  • iRedMail
  • docker-mailserver
  • symbiosis
  • ...

(Personally, I had some ansible recipes!)

Even among people who run their own websites, it's rare to run your own email. It's just too painful. Much of this pain is caused by ultra-configurable components that need to be orchestrated. Each has its own (remarkably obtuse) configuration language, and each can do far more than the common case for a small, single-domain site.

So, let's make a single binary where all you have to do is:

  • Register a domain
  • Upload some DNS records
  • Run the binary

and it gives you a sensible email setup without any additional configuration!

If it has to share the domain with a HTTP server (quite common), allow the HTTP-specific parts of mail to be served via reverse proxying. This includes:

  • activesync push notifications
  • autodiscovery

Probably other stuff. Email is big, and just keeps getting bigger.


Copyright (C) 2018 Nick Thomas crockery@ur.gs

This program is free software: you can redistribute it and/or modify it under the terms of version 3 of the GNU Affero General Public License as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.


Contributions are very welcome. Feel free to open a merge request against the GitLab hosted project, or to email patches or a link to a hosted git branch, directly to the author.

To be accepted, contributions must:

  • Accept copyright assignment to the author
  • Be licensed according to the foregoing terms
  • Consist entirely of signed commits
  • Indicate acceptance of the above with a Signed-off-by: line in each commit message


Building a binary

$ go build ur.gs/crockery/cmd/crockery
$ sudo setcap 'cap_net_bind_service=+ep' ./crockery

The second step allows crockery to bind to the various low-numbered ports it needs (25, 587, 149, 993) without running as root. Don't bother with it if you're going to be running crockery as root, e.g., as a container or a single- purpose system.

You may also provide these capabilities via systemd by using lines like these in the [Service] definition:



If you're doing this, you may also want to set:


TODO: write up a .service file that can be dropped in

Initialize a new database

$ crockery init \
  --domain <domain-name> \
  --cert <cert-file> \
  --key <key-file> \
  --postmaster-password <password>

You can also provide the postmaster password in an environment variable:

$ CROCKERY_POSTMASTER_PASSWORD="<password>" crockery init \
  --domain <domain-name> \
  --cert <cert-file> \
  --key <key-file>

By default, crockery will initialize the current user's home directory. You can provide a custom directory to work with by specifying --home, e.g.:

$ crockery \
  --home <home-directory> \
  init \
  --domain <domain-name> \
  --cert <cert-file> \
  --key <key-file> \
  --postmaster-password <password>

Run the server

./crockery run

Again, you can use --home <directory> if the default of $HOME doesn't suit. Crockery will load the configuration from the database and begin serving mail based on it. Received emails are stored in a mailbox determined by the username, to be found in the <home>/mailboxes directory


Mostly non-existent, aside from that listed above.

We'll need to have a few offline commands baked into the crockery binary, apart from init as detailed above. Some ideas:

$ crockery change x y z (domain, user password, etc)
$ crockery reindex [account] (throw away existing indexes, regenerate)
$ crockery whitelist tls <domain> (allow the domain to be sent to with insecure/no TLS)
$ crockery whitelist receipt <domain> (bypass antispam for this domain)
$ crockery blacklist receipt <domain> (no emails to be permitted from this domain

It's inconvenient for some of these functions to require the server to be offline, so we'll need to provide another configuration interface too.

I like sending emails to it.

Since we're going to need a HTTP server anyway, we could expose admin functions using that, if logged in as postmaster. It could also expose an API that the crockery X commands could connect to, rather than hitting the store directly. We can use the .well-known integration to avoid the need to configure there, too.