selfhost.directory

The index of self-hostable projects — ranked, categorized and served with live updates.
Own your data and stop giving it to big tech.

mailez logo

Self-host mailez

v1.0.2

Self-hosted mail server with webmail and admin console

ReleaseOpen SourceAGPL-3.0
Updated2 weeks ago
LanguageGo
Setup difficultyModerate
MobilePWA
ThemeDark mode
Stars
288
Ports
25 (SMTP), 465 (SMTPS (implicit TLS)), 1587 (SMTP Submission), 110 (POP3), 995 (POP3S (implicit TLS)), 143 (IMAP), 993 (IMAPS (implicit TLS)), 4190 (ManageSieve), 8081 (Backend API), 8082 (Admin console)
Requires
Redis
Install with Docker Compose
Webmail three-pane inbox viewWebmail conversation view with quoted history foldingAdmin console domain managementAdmin console domain health checks

What is mailez?

This mail platform bundles a custom-built engine (mailezine), a React-based webmail and admin interface, and all supporting infrastructure into one Docker Compose deployment. It handles SMTP, IMAP, POP3, ManageSieve, CardDAV, and CalDAV protocols, and provides a three-pane webmail with conversation view, PGP encryption, two-factor authentication, and PWA offline support. The admin console manages domains, mailboxes, aliases, DKIM keys, domain health checks with live DNS verification, audit logs, and configuration import/export. Spam filtering uses an integrated Rspamd setup with optional greylisting. The community edition runs on SQLite, Pebble, and local filesystem storage with optional MySQL or PostgreSQL for the control plane; an enterprise edition adds distributed storage (TiDB/S3), ActiveSync, LDAP/AD integration, DLP, archiving, and AI features. Both editions share the same engine and control plane. Deployment is managed by a single script (mailezctl.sh) that handles Docker Compose profiles and environment configuration.

Should you self-host mailez?

mailez scores 49/100 on selfhost.directory (how scoring works) and ranks #61 of 106 in Email. It has 288 GitHub stars.

It shipped 3 stable releases in the past year. The latest, v1.0.0, came out on 14 October 2026.

Setup is moderate: expect some configuration beyond a single command. It is AGPL-3.0-licensed and written mostly in Go.

Its closest alternative on selfhost.directory is Listmonk (80/100, 24 019 stars). It scores higher overall, so compare the two before you pick. See mailez vs Listmonk side by side.

Features

  • Admin console with domain health checks
  • App tokens
  • Audit log and role-based access
  • CardDAV/CalDAV sync
  • Configuration import/export
  • Delta Chat integration
  • One-click DKIM key generation
  • PGP sign and encrypt
  • Rspamd spam filtering
  • Sieve filter editor
  • Two-factor authentication (TOTP)

mailez README

How to install mailez

Install mailez with Docker Compose

Environment variables
MAILEZ_SECRET_KEY, MAILEZ_STACK_SECRET, MAILEZ_DOMAIN, MAILEZ_HOSTNAMES, MAILEZ_TLS, MAILEZ_DB_DRIVER, MAILEZ_DB_DSN

cd deploy cp mailez.env.example mailez.env

edit MAILEZ_SECRET_KEY / MAILEZ_DOMAIN / MAILEZ_HOSTNAMES

./deploy/mailezctl.sh up ce

Pulls prebuilt images from ghcr.io; requires MAILEZ_SECRET_KEY and MAILEZ_STACK_SECRET in mailez.env

How to configure mailez

  • COMPOSE_PROJECT_NAMEmailez
  • LOG_LEVELinfo--- misc ---

    --- misc ---

  • MAILEZ_ADMIN_PORT
  • MAILEZ_ANTIVIRUSnone
  • MAILEZ_APItrue--- features ---

    --- features ---

  • MAILEZ_API_PORT
  • MAILEZ_BACKEND_ADDRESSbackend--- control plane wiring ---

    --- control plane wiring ---

  • MAILEZ_BACKUP_HOUR
  • MAILEZ_BACKUP_KEEP
  • MAILEZ_BACKUP_KEY定时加密备份:控制面 SQLite VACUUM INTO 快照 + 附件/云盘目录,分块 AES-256-GCM 加密后投递。没配 MAILEZ_BACKUP_KEY 就完全不跑(也不会产生 明文归档),健康中心会把备份新鲜度评为失败(>7 天告警、>14 天失败)。 TARGET 为 local:<目录> 或 s3;本地目录要落在挂载卷里(容器内 /data 即 宿主的 deploy/data/),否则归档只存在容器可写层、重建即丢。s3 复用引擎 侧的 MAILEZINE_S3_ENDPOINT / _ACCESS_KEY / _SECRET_KEY / _BUCKET / _USE_SSL 一组变量。

    定时加密备份:控制面 SQLite VACUUM INTO 快照 + 附件/云盘目录,分块 AES-256-GCM 加密后投递。没配 MAILEZ_BACKUP_KEY 就完全不跑(也不会产生 明文归档),健康中心会把备份新鲜度评为失败(>7 天告警、>14 天失败)。 TARGET 为 local:<目录> 或 s3;本地目录要落在挂载卷里(容器内 /data 即 宿主的 deploy/data/),否则归档只存在容器可写层、重建即丢。s3 复用引擎 侧的 MAILEZINE_S3_ENDPOINT / _ACCESS_KEY / _SECRET_KEY / _BUCKET / _USE_SSL 一组变量。

  • MAILEZ_BACKUP_TARGET
  • MAILEZ_BAN_FINDTIME_SEC
  • MAILEZ_BAN_MAX_RETRY登录封禁:MAILEZ_BAN_FINDTIME_SEC 秒内认证失败 MAILEZ_BAN_MAX_RETRY 次 即封禁来源 IP(Web 登录与邮件代理 SASL 共用同一套计数),时长按 30 天 内累犯从 15 分钟递增到 24 小时。回环地址与本部署自身地址始终豁免; 办公出口、监控探针网段请加白名单(CIDR 逗号分隔),否则会被自己封掉。

    登录封禁:MAILEZ_BAN_FINDTIME_SEC 秒内认证失败 MAILEZ_BAN_MAX_RETRY 次 即封禁来源 IP(Web 登录与邮件代理 SASL 共用同一套计数),时长按 30 天 内累犯从 15 分钟递增到 24 小时。回环地址与本部署自身地址始终豁免; 办公出口、监控探针网段请加白名单(CIDR 逗号分隔),否则会被自己封掉。

  • MAILEZ_BAN_WHITELIST
  • MAILEZ_BIND--- 对外绑定地址 --- 控制台/API(8081-8083)默认只绑本机:管理台与 Webmail 走网关 (https://<主机名>/admin 与 /),8082/8083 仅作调试直连。想让它们 直接对外时改 MAILEZ_BIND,不必改 compose。 邮件协议默认对外(25/465/587/143/993/110/995/4190 需要接收外部邮件); 评估实例想只用本机时设成 127.0.0.1。

    --- 对外绑定地址 --- 控制台/API(8081-8083)默认只绑本机:管理台与 Webmail 走网关 (https://<主机名>/admin 与 /),8082/8083 仅作调试直连。想让它们 直接对外时改 MAILEZ_BIND,不必改 compose。 邮件协议默认对外(25/465/587/143/993/110/995/4190 需要接收外部邮件); 评估实例想只用本机时设成 127.0.0.1。

  • MAILEZ_DB_DRIVER--- 控制面数据库(ce 默认 SQLite,零外部依赖) --- 留空即 SQLite(./data/mailez.db,随数据目录整体备份)。可选 MySQL / PostgreSQL,并配合 docker-compose.ce.yml 的 --profile mysql / postgres:

    --- 控制面数据库(ce 默认 SQLite,零外部依赖) --- 留空即 SQLite(./data/mailez.db,随数据目录整体备份)。可选 MySQL / PostgreSQL,并配合 docker-compose.ce.yml 的 --profile mysql / postgres:

  • MAILEZ_DB_DSN
  • MAILEZ_DKIM_SELECTORdkim--- DKIM / full-text search ---

    --- DKIM / full-text search ---

  • MAILEZ_DOMAIN--- identity ---

    --- identity ---

  • MAILEZ_GREYLISTINGfalse
  • MAILEZ_HEALTH_ALERT--- 运维告警 / 登录封禁 / 加密备份(v1.0.1 新增,全部可选) --- 变更式健康告警:后台按 MAILEZ_HEALTH_ALERT_INTERVAL_MIN 分钟重跑健康 检查,只在状态发生变化时通知——首轮只记基线,状态须连续两次巡检一致 才推送,恢复同样通知。送达管理员邮箱;配了 WEBHOOK 就同时推 JSON (Slack / 钉钉 / 企业微信兼容)。MUTE 静音单个检查项,逗号分隔,键为 system:<id> 或 domain:<域名>:<id>;MAILEZ_HEALTH_ALERT=off 整体关闭。

    --- 运维告警 / 登录封禁 / 加密备份(v1.0.1 新增,全部可选) --- 变更式健康告警:后台按 MAILEZ_HEALTH_ALERT_INTERVAL_MIN 分钟重跑健康 检查,只在状态发生变化时通知——首轮只记基线,状态须连续两次巡检一致 才推送,恢复同样通知。送达管理员邮箱;配了 WEBHOOK 就同时推 JSON (Slack / 钉钉 / 企业微信兼容)。MUTE 静音单个检查项,逗号分隔,键为 system:<id> 或 domain:<域名>:<id>;MAILEZ_HEALTH_ALERT=off 整体关闭。

  • MAILEZ_HEALTH_ALERT_INTERVAL_MIN
  • MAILEZ_HEALTH_ALERT_MUTE
  • MAILEZ_HEALTH_ALERT_WEBHOOK
  • MAILEZ_HOSTNAMES
  • MAILEZ_HTTP_PORT--- 宿主端口映射(默认值见下;被占用时改这里,compose 插值自动生效) ---

    --- 宿主端口映射(默认值见下;被占用时改这里,compose 插值自动生效) ---

  • MAILEZ_HTTPS_PORT
  • MAILEZ_IMAGE_TAG--- release image tag / registry --- Tag for all mailez images (13 package names, see docker-bake.hcl). Production deployments pull; pin a release here for controlled upgrades:

    --- release image tag / registry --- Tag for all mailez images (13 package names, see docker-bake.hcl). Production deployments pull; pin a release here for controlled upgrades:

  • MAILEZINE_IMAGE_TAGPin the mailezine engine image separately (e.g. engine and control plane releasing apart); unset tracks MAILEZ_IMAGE_TAG:

    Pin the mailezine engine image separately (e.g. engine and control plane releasing apart); unset tracks MAILEZ_IMAGE_TAG:

  • MAILEZINE_JUNK_BLACKLIST
  • MAILEZINE_JUNK_ENABLED--- 引擎内置基础反垃圾(internal/junk;配置 MAILEZINE_RSPAMD_URL 后自动让位: 内置 rspamd 扫描) ---

    --- 引擎内置基础反垃圾(internal/junk;配置 MAILEZINE_RSPAMD_URL 后自动让位: 内置 rspamd 扫描) ---

  • MAILEZINE_JUNK_GREYLIST
  • MAILEZINE_JUNK_HEADER_SCORE
  • MAILEZINE_JUNK_RBLS
  • MAILEZINE_JUNK_REJECT_SCORE
  • MAILEZINE_JUNK_WHITELIST
  • MAILEZINE_S3_ENDPOINT对象存储(可选):默认全部走本地盘;接 S3 兼容服务(rustfs/minio/任意 云 S3)时设下面这组变量,引擎附件、云盘与大附件中继共用。内置对象存储 服务的 profile 用法见各 compose 文件内注释。

    对象存储(可选):默认全部走本地盘;接 S3 兼容服务(rustfs/minio/任意 云 S3)时设下面这组变量,引擎附件、云盘与大附件中继共用。内置对象存储 服务的 profile 用法见各 compose 文件内注释。

  • MAILEZINE_STACK_SECRET
  • MAILEZINE_TLS_CERT_FILE引擎侧隐式 TLS(465/993/995)与 STARTTLS 用同一套证书;letsencrypt 模式下 网关把证书写到 ./certs/letsencrypt/live/mailez/,直接引用即可:

    引擎侧隐式 TLS(465/993/995)与 STARTTLS 用同一套证书;letsencrypt 模式下 网关把证书写到 ./certs/letsencrypt/live/mailez/,直接引用即可:

  • MAILEZINE_TLS_KEY_FILE
  • MAILEZ_LOCAL_BUILD(leave unset to track :latest — releases move that tag to the newest stable version). Local source builds ignore this and use :local automatically:

    (leave unset to track :latest — releases move that tag to the newest stable version). Local source builds ignore this and use :local automatically:

  • MAILEZ_MAIL_BIND
  • MAILEZ_MAX_ATTACHMENT_BYTES单个附件大小上限(字节)。Webmail 的上传选择器按 20MB 拦,但 API 可以 直接调用、网关只限制整个请求体,所以服务端也要挡一道;超限返回 422 attachment_too_large。设 0 关闭该检查。

    单个附件大小上限(字节)。Webmail 的上传选择器按 20MB 拦,但 API 可以 直接调用、网关只限制整个请求体,所以服务端也要挡一道;超限返回 422 attachment_too_large。设 0 关闭该检查。

  • MAILEZ_MESSAGE_RATELIMIT200
  • MAILEZ_MESSAGE_SIZE_LIMIT50000000--- mail routing ---

    --- mail routing ---

  • MAILEZ_OIDC_CLIENT_ID
  • MAILEZ_OIDC_CLIENT_SECRET
  • MAILEZ_OIDC_ISSUER--- SSO(OIDC 联合登录,可选) --- 配置后 webmail/admin 登录页出现"统一身份登录"入口:跳转 IdP 授权、 回调后按 email 匹配本地已启用账号(不自动开户),成功即建会话。 RedirectURL 留空时自动推导为 https://<站点域名>/api/v1/sso/oidc/callback, 该地址需在 IdP 处登记为重定向 URI。四项全部配置才会启用。

    --- SSO(OIDC 联合登录,可选) --- 配置后 webmail/admin 登录页出现"统一身份登录"入口:跳转 IdP 授权、 回调后按 email 匹配本地已启用账号(不自动开户),成功即建会话。 RedirectURL 留空时自动推导为 https://<站点域名>/api/v1/sso/oidc/callback, 该地址需在 IdP 处登记为重定向 URI。四项全部配置才会启用。

  • MAILEZ_OIDC_REDIRECT_URL
  • MAILEZ_OUTBOUND_PROBE_HOST出站网络体检的探测目标:默认拨测 aspmx.l.google.com:25,用来确认本机 到底能不能向外投递(云厂商封 25 端口时其余检查全是绿的);想换成自建 中继或别的 MTA 时设这里。

    出站网络体检的探测目标:默认拨测 aspmx.l.google.com:25,用来确认本机 到底能不能向外投递(云厂商封 25 端口时其余检查全是绿的);想换成自建 中继或别的 MTA 时设这里。

  • MAILEZ_POSTMASTERpostmaster
  • MAILEZ_RECIPIENT_DELIMITER+
  • MAILEZ_REGISTRYRegistry override (default ghcr.io/mailez-hq), e.g. for a mirror:

    Registry override (default ghcr.io/mailez-hq), e.g. for a mirror:

  • MAILEZ_RELAYNETS
  • MAILEZ_SCAN_MACROSfalse
  • MAILEZ_SECRET_KEYTokenEnc / 外部账号密码的加密密钥(16 字节)。生产部署必须更换: openssl rand -hex 16

    TokenEnc / 外部账号密码的加密密钥(16 字节)。生产部署必须更换: openssl rand -hex 16

  • MAILEZ_STACK_SECRET--- 内部 /stack API 共享密钥(所有 compose 档必填) --- mailezine 引擎与 backend 之间的内部回调(认证/目录/DKIM vault/外部账号 密码读取)走共享密钥鉴权。两行必须同值;compose 的 ${MAILEZ_STACK_SECRET:?} 插值要求非空(留空无法启动生产/社区 compose 档——这正是防止内部 API 裸奔的保护:同网络任何容器都能读取 DKIM 私钥与外部邮箱明文密码)。 同值还充当引擎管理 API(8090)的 Bearer secret:backend 删除用户时经 MAIL_ENGINE_MGMT_SECRET 级联清除引擎侧邮箱数据(两个 compose 文件都 引用 MAILEZ_STACK_SECRET,无需重复设置)。 生成:openssl rand -hex 32

    --- 内部 /stack API 共享密钥(所有 compose 档必填) --- mailezine 引擎与 backend 之间的内部回调(认证/目录/DKIM vault/外部账号 密码读取)走共享密钥鉴权。两行必须同值;compose 的 ${MAILEZ_STACK_SECRET:?} 插值要求非空(留空无法启动生产/社区 compose 档——这正是防止内部 API 裸奔的保护:同网络任何容器都能读取 DKIM 私钥与外部邮箱明文密码)。 同值还充当引擎管理 API(8090)的 Bearer secret:backend 删除用户时经 MAIL_ENGINE_MGMT_SECRET 级联清除引擎侧邮箱数据(两个 compose 文件都 引用 MAILEZ_STACK_SECRET,无需重复设置)。 生成:openssl rand -hex 32

  • MAILEZ_SUBNET192.168.206.0/24--- docker 网络 --- 邮件栈 compose 使用固定私有网段(受信网段:引擎 TRUSTED_NETS 与 gateway 代理信任共用)。默认 192.168.206.0/24, 如需改网段,必须同时导出同名变量给 compose 插值: $env:MAILEZ_SUBNET = "10.20.30.0/24" 容器间一律走服务名(Docker DNS),不再依赖固定容器 IP。

    --- docker 网络 --- 邮件栈 compose 使用固定私有网段(受信网段:引擎 TRUSTED_NETS 与 gateway 代理信任共用)。默认 192.168.206.0/24, 如需改网段,必须同时导出同名变量给 compose 插值: $env:MAILEZ_SUBNET = "10.20.30.0/24" 容器间一律走服务名(Docker DNS),不再依赖固定容器 IP。

  • MAILEZ_SUBNET6
  • MAILEZ_TLS--- TLS --- off: plaintext only (local dev) cert: provide cert.pem / key.pem in ./certs (see deploy/certs/README.md) letsencrypt: automated ACME (needs exposed 80/443)

    --- TLS --- off: plaintext only (local dev) cert: provide cert.pem / key.pem in ./certs (see deploy/certs/README.md) letsencrypt: automated ACME (needs exposed 80/443)

  • MAILEZ_TLS_CERT_FILE
  • MAILEZ_TLS_KEY_FILE
  • MAILEZ_TLS_PORTS80,443
  • MAILEZ_WEBMAIL_PORT
  • MAIL_FORCE_TLSAPI 后端与引擎之间内部 IMAP/SMTP 链接的降级策略:默认 0,STARTTLS 协商 失败时回退明文(标准部署由网关终结 TLS,内部链路保持明文)。仅当引擎 自身配了上面的证书、要求内部链路也必须加密升级时设 1——此时协商失败 直接报错,不回退明文。

    API 后端与引擎之间内部 IMAP/SMTP 链接的降级策略:默认 0,STARTTLS 协商 失败时回退明文(标准部署由网关终结 TLS,内部链路保持明文)。仅当引擎 自身配了上面的证书、要求内部链路也必须加密升级时设 1——此时协商失败 直接报错,不回退明文。

  • MAIL_SIEVE_ADDRManageSieve endpoint used by the webmail filter editor (the mailezine engine's ManageSieve port; authenticated with the per-session temp token)

    ManageSieve endpoint used by the webmail filter editor (the mailezine engine's ManageSieve port; authenticated with the per-session temp token)

mailez releases & version history

More in Calendar & Contacts

Rate this project

Click to rate — no account needed.

0 comments

Posting as guest
Loading comments…