Skip to content

v2.80.0

Latest

Choose a tag to compare

@github-actions github-actions released this 09 Sep 13:06
9816931

2.80.0 (2026-09-09)

Overview

TLS certificates get their own page. Certificates are managed at Configuration > TLS Certificates instead of a checkbox on the SMTP and IMAP proxy pages. The page shows what each listener (API, SMTP server, IMAP proxy) actually serves, one row per hostname, and a certificate can be uploaded on its own subpage. Every listener with TLS switched on now has a self-signed fallback, so a missing certificate no longer crash-loops the worker. Material from EENGINE_API_TLS_*, EENGINE_SMTP_TLS_* and EENGINE_IMAPPROXY_TLS_* outranks anything EmailEngine manages itself, encrypted operator keys load again, and a renewal swaps the certificate in place without restarting the SMTP or IMAP proxy worker. A first Let's Encrypt order is only placed while a listener would serve the certificate, so an instance behind a TLS-terminating reverse proxy is not asked to answer ACME challenges it cannot.

Let's Encrypt on a maintained ACME client. The abandoned @root/acme stack is replaced by an in-house RFC 8555 client in @postalsys/certs, which finalizes orders correctly, asks the CA when to renew (ARI) and drops fourteen packages from the bundle. Renewal timing was inverted before and ran a month after expiry. EENGINE_ACME_DIRECTORY_URL and EENGINE_ACME_ENVIRONMENT point a build at a different CA, for example Let's Encrypt staging.

Exchange autodiscovery works. The Exchange branch of GET /v1/autoconfig and the hosted setup form had never resolved a real server (wrong content type, wrong element order, no authentication). It now handles both the legacy and the SOAP endpoint, offers the password only after a 401 that asks for Basic over https, and an answer naming no server no longer ends the lookup.

Fewer false authentication webhooks. A throttled or unavailable credential service (an OAuth2 token endpoint, the operator's authentication server) is treated as transient instead of a refused credential, so accounts stop flapping between authenticationError and authenticationSuccess and are not parked for an outage. The authentication server's own HTTP status no longer leaks into API responses or IMAP proxy replies.

Outlook and Gmail change notifications are visible when they break. An Outlook account whose Graph subscription cannot be created (for example a disabled Exchange Online service principal) reports a connectError instead of silently receiving nothing, and subscription retries continue after the fast retries give up. A dead Gmail Pub/Sub watch is reported on the account page and in GET /v1/account/{account} as gmailWatch, and retried hourly instead of once a day.

IMAP sync correctness. The first sync of a new account emits messageNew for existing mail again (broken since 2.69.0), sync no longer reads the counters of whichever folder an API call happened to select, mailboxDeleted is announced once, folder paths are matched the way the server spells them (Inbox vs INBOX), a folder created while the primary connection was down is announced, and a disconnect mid-sync no longer publishes a message with missing inline images. A malformed message id answers a 400 instead of a 500.

Admin UI. Forced SSO no longer swallows form submissions after a session expires, and the Re-authenticate button on the account page works again under the Content-Security-Policy.

Features

  • tls: manage certificates on their own page, with a real self-signed fallback (42a1546)

Bug Fixes

  • accounts: keep the authentication server's status out of API and IMAP proxy answers (79264b0)
  • accounts: stop a credential-service blip from flooding auth webhooks (51f4f35)
  • admin: let the account page re-authenticate an OAuth2 account again (56245f7)
  • admin: stop forced SSO from silently swallowing admin form submissions (9653c2d)
  • api: reload the TLS listeners only when a settings write changed a value (b2052ac)
  • autodiscovery: keep a usable server entry when a hostless sibling follows it (3796668)
  • autodiscovery: make Exchange autodiscovery work at all (271d85c)
  • autodiscovery: stop a result that names no server from ending a lookup (e698c3c)
  • deps: update @bull-board/api and @bull-board/hapi to 9.9.0 (14720fb)
  • deps: update @postalsys/certs to 1.2.1 (eb2c958)
  • deps: update @postalsys/certs to 1.3.0 (08c2d1b)
  • gmail: clear a stale watch failure once push is no longer configured (b5884fe)
  • gmail: report no watch for an account whose application has no Pub/Sub app (7e53a20)
  • gmail: stop a dead Pub/Sub watch from being invisible and self-perpetuating (206e17d)
  • imap: announce a folder that appeared while the primary was down (2afd207)
  • imap: announce the deletion of a tracked folder missing from the stored listing (2ead02f)
  • imap: answer a malformed message identifier instead of throwing at it (9be0c9c)
  • imap: collect the connection-closed error and the attachment download (8d0e589)
  • imap: keep a folder found by a pass that could not register it (0971a4d)
  • imap: match configured folder paths against the spelling the server reports (328e56a)
  • imap: restore the first-sync backfill and the return to the main mailbox (b0b229c)
  • imap: stop a disconnect mid-sync from announcing a message without its images (fab2c15)
  • imap: stop a read-only folder listing from swallowing the mailboxNew event (ab76f0d)
  • imap: stop the duplicate mailboxDeleted and the dropped inbox counters (edd0b0c)
  • outlook: keep retrying a subscription the fast retries gave up on (9583780)
  • outlook: report an account that can no longer subscribe to changes (9da07ad)
  • outlook: stop a subscription recovery from dropping a newer failure (bd613fe)
  • outlook: take a subscription report back when the subscription is healthy, keep it across a login (9bccba8)
  • tls: let an operator point ACME at a different CA without editing source (13b382f)
  • tls: order a first certificate only for a listener that would serve it (950185f)
  • tls: read the failed renewal from the certificate library instead of inferring it (c0e4bfd)
  • tls: redesign the certificates page around what each listener serves (7dc42ba)
  • tls: replace the abandoned ACME stack and ask the CA when to renew (9364eeb)
  • tls: report a failed renewal, converge concurrent self-signed replacement (b1ac9e3)
  • tls: report a half-set ACME override, drop the unused listener restart (fe7771e)
  • tls: say plainly that the API listener serves HTTP by default (31e75ae)
  • tls: serve an encrypted operator key, keep the listener settings on reload (75d16d9)
  • tls: stop a repeated request from starting a second order, report the listener's own state (845d4e7)