Commit Graph
56 Commits
Author SHA1 Message Date
Linus Rath cf0eb03c4a feat: show the sender's BIMI logo as the sender icon when the message passes DMARC
Stalwart does no BIMI, so sender icons were only ever favicons, which
anyone controls for any domain. The webmail server now does the
receiver side itself at /api/bimi, and avatars ask it only for
messages whose own Authentication-Results say dmarc=pass for the exact
From domain.

- `lib/bimi/`: DMARC policy check (quarantine or reject, pct=100, the
  parent domain's sp and p for subdomains), the assertion record with
  fallback to the parent domain, mark certificate validation (chain to
  pinned DigiCert, GlobalSign and SSL.com VMC roots, BIMI key purpose,
  validity, SAN, SCTs present, CRL revocation, logo from the logotype
  extension), SVG Tiny PS checks and rendering to PNG, caching
- logos backed only by the DNS record show by default; the admin
  setting "Require a mark certificate" (`BIMI_REQUIRE_CERTIFICATE`)
  limits them to VMC and CMC backed ones
- a check mark beside the sender's name for certificate-backed logos
- avatars try contact photo, BIMI logo, plugin avatar, favicon; the
  sender warning shield still wins, and logos follow the sender icons
  setting and the no-third-party-traffic mode
- the two-label public suffix list moved to `lib/root-domain.ts`

SCT signatures are not verified and only the default selector is used.
2026-10-30 00:12:24 +01:00
Linus Rath 50b3ddccec feat: let admins keep the refresh token valid on sign-out so Stalwart keeps the consent #1388 2026-10-29 20:47:18 +01:00
Linus Rath 0b4e501142 feat: make the login email placeholder configurable #1423 2026-10-29 20:24:26 +01:00
Linus Rath d875714f35 feat: offer remember me on the sso-only login and apply it to every sso path #1437 2026-10-29 20:06:44 +01:00
Linus Rath 623c9e1792 feat: let operators set accessibility statement, barrier report, help, Easy Read and sign language links 2026-10-29 18:27:35 +01:00
Linus Rath cf2c27157d Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	components/contacts/contacts-app.tsx
#	components/email/__tests__/composer-discard.test.tsx
#	components/email/calendar-invitation-banner.tsx
#	components/email/email-composer.tsx
#	components/mail/mail-app.tsx
#	components/pro/pro-compose-tab-body.tsx
#	components/pro/pro-email-tab-body.tsx
#	components/ui/__tests__/avatar.test.tsx
#	components/ui/avatar.tsx
#	hooks/use-mailbox-drop.ts
#	lib/__tests__/calendar-alerts.test.ts
#	lib/__tests__/jmap-calendar-tasks.test.ts
#	lib/__tests__/jmap-send-threading.test.ts
#	lib/demo/demo-client.ts
#	lib/demo/fixtures/calendars.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/web-push.ts
#	stores/__tests__/contact-store.test.ts
#	stores/__tests__/email-store-thread-key.test.ts
#	stores/calendar-store.ts
#	stores/contact-store.ts
#	stores/email-store.ts
2026-10-26 10:14:12 +01:00
Linus Rath 4f942417c8 fix: show pdf attachment previews in safari #1301 2026-10-20 21:08:01 +02:00
Linus Rath 4adbad25f6 feat: end the provider session through a configured logout URL #1279 2026-10-18 13:46:48 +02:00
Linus Rath 41a0716c50 Merge branch 'main' into feat/stalwart-1.0 2026-10-16 01:41:48 +02:00
Linus Rath 8ad072e458 feat: generate a session secret on first start when none is configured 2026-10-13 13:17:34 +02:00
Linus Rath 3da46b5a0d feat: remember every sign-in unless the admin shows the remember me box 2026-10-13 13:13:56 +02:00
Linus Rath c633185cda Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	CONTRIBUTING.md
#	LICENSE
#	README.md
#	app/api/calendar-agenda/route.ts
#	app/api/wopi/files/[fileId]/contents/route.ts
#	app/api/wopi/launch/route.ts
#	components/calendar/calendar-app.tsx
#	components/calendar/calendar-day-view.tsx
#	components/calendar/calendar-month-view.tsx
#	components/calendar/calendar-week-view.tsx
#	components/calendar/event-modal.tsx
#	components/contacts/contact-detail.tsx
#	components/email/email-composer.tsx
#	components/email/email-list.tsx
#	components/files/file-browser.tsx
#	components/files/files-app.tsx
#	components/files/folder-tree-sidebar.tsx
#	components/filters/filter-rule-modal.tsx
#	components/mail/mail-app.tsx
#	hooks/use-mailbox-drop.ts
#	integration/run-tests.sh
#	lib/__tests__/calendar-agenda-route.test.ts
#	lib/__tests__/jmap-draft-lifecycle.test.ts
#	lib/__tests__/web-push.test.ts
#	lib/account-state-manager.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/jmap/types.ts
#	lib/message-list-order.ts
#	lib/sieve/generator.ts
#	lib/sieve/parser.ts
#	lib/telemetry/payload.ts
#	lib/thread-utils.ts
#	lib/unified-mailbox.ts
#	lib/web-push.ts
#	lib/wopi/token.ts
#	locales/ar/common.json
#	locales/ca/common.json
#	locales/cs/common.json
#	locales/da/common.json
#	locales/de/common.json
#	locales/en/common.json
#	locales/es/common.json
#	locales/fa/common.json
#	locales/fr/common.json
#	locales/he/common.json
#	locales/hu/common.json
#	locales/it/common.json
#	locales/ja/common.json
#	locales/ko/common.json
#	locales/lv/common.json
#	locales/mn/common.json
#	locales/nb/common.json
#	locales/nl/common.json
#	locales/pl/common.json
#	locales/pt/common.json
#	locales/ro/common.json
#	locales/ru/common.json
#	locales/sk/common.json
#	locales/tr/common.json
#	locales/uk/common.json
#	locales/zh-TW/common.json
#	locales/zh/common.json
#	scripts/lite/lib.mjs
#	stores/__tests__/calendar-store-synthetic-ids.test.ts
#	stores/__tests__/email-store-shared-folder-keywords.test.ts
#	stores/__tests__/email-store-unified-actions.test.ts
#	stores/__tests__/file-store.test.ts
#	stores/email-store.ts
#	stores/file-store.ts
#	stores/message-list-tabs-store.ts
2026-10-12 08:35:08 +02:00
Linus Rath 0e39b199a1 feat: link the running build's source from the About card #1161 2026-10-02 22:10:29 +02:00
Linus Rath 5597eadc28 fix: give a server its own sign-in button only when it has a button label #1135
A server entry's OAuth client ID already has a meaning while OAuth is
off globally: it is the registered client that password and TOTP logins
use with Stalwart's require_client_registration. The PR made every such
entry offer OAuth on its own, so existing installs would suddenly run
discovery and show SSO buttons on the login page, and multi-IdP setups
would get one extra button per server.

A server now gets its own button only with both a client ID and a button
label, which no existing config has. The rule lives in `offersOwnOAuth`
with a test. Also:
- the OAuth-only login form uses the selected server's label
- the public config validator checks `buttonLabel` is a string
- the admin hint and `.env.example` say the label enables the button
2026-10-01 11:01:17 +02:00
Linus Rath 29c74c3b77 feat: sign in with an access token 2026-10-01 00:24:47 +02:00
Linus Rath 70dee66966 Merge pull request #996 from mulatta/feat/external-plugin-signing-key
feat: support external plugin signing keys
2026-09-30 14:23:45 +02:00
Linus Rath fee0e7c9e7 fix: show default oauth scopes in the admin dashboard #1126 2026-09-30 12:17:25 +02:00
Linus Rath 32280b9cc1 fix: cap admin sign-in attempts across all clients (GHSA-7pj2-232x-6698)
The admin login limit keys on the client IP taken from
X-Forwarded-For. With no reverse proxy in front, that header is
whatever the client sends (Next only fills it from the socket when the
request carries none), so each forged address got a fresh bucket of
five guesses. Route handlers cannot see the socket address, so the
limiter now also stops at 50 attempts per 15 minutes across all
clients. `.env.example` says why a proxy that appends the header is
still needed for trustworthy per-IP limits and audit addresses.
2026-09-26 15:07:09 +02:00
Linus Rath 11eb0bfb16 fix: keep the Stalwart master password out of impersonated sessions
An impersonation handoff sealed `<target>%<master>` and the master
password into the session cookie, and `PUT /api/auth/session` hands that
cookie's contents to the browser on every restore. Anyone who received
a handoff could read a credential that signs in as every mailbox and
into Stalwart administration, with no expiry and no audit trail.

The impersonate route now uses the master credential server-side, once,
to create an app password on the target mailbox that expires after
8 hours. Only that app password reaches the cookies. Signing out
revokes it through a sealed grant cookie, and PUT refuses any session
that still holds the configured master password, so cookies minted
before this change are dropped instead of returned.
2026-09-26 14:05:05 +02:00
Linus Rath 9f6b546ffe fix: stop reporting a proxy's version as the Stalwart version in telemetry
The heartbeat's `stalwart_version` came from the `Server` header of
`/.well-known/jmap`. Stalwart never sends one (0.16.0 through 1.0), so
the field was null, or the version of a reverse proxy in front of
Stalwart. The probe is gone: the version is reported only when
`STALWART_VERSION` is set.
2026-09-25 19:32:35 +02:00
Linus Rath f97218375e fix: end the identity provider session on sign-out #905 2026-09-23 20:44:46 +02:00
Linus Rath f8592bc6b7 fix: accept oauth endpoints on the configured issuer's own host #1028 2026-09-23 19:26:07 +02:00
Linus Rath 691cde6468 fix: explain why calendar subscriptions fail with not authenticated #1073 2026-09-23 18:31:27 +02:00
mulatta c13b4105be feat: support external plugin signing keys 2026-09-09 01:32:18 +09:00
Linus Rath ed340cc2c1 feat: make Stalwart admin access to the dashboard configurable #870 2026-08-25 18:39:07 +02:00
Linus Rath 934967b9df docs: document remaining env vars in env templates 2026-07-25 17:46:12 +02:00
Linus Rath 755201c92a docs: fix facts and rewrite tone 2026-07-25 17:38:55 +02:00
Loïs Postula 638fc7db4e feat(oauth): add OAUTH_AUTHORIZE_URL to override authorize endpoint
Lets a per-brand authorize host front a single canonical issuer, so the
IdP token's `iss` stays constant for downstream validation while login
branding varies per domain. Discovery, token exchange and refresh keep
using OAUTH_ISSUER_URL.
2026-06-19 12:30:23 +02:00
Linus Rath 3e12fca517 fix: make telemetry opt-in 2026-06-14 14:31:26 +02:00
Linus Rath 6b1a99a70b docs: document DOMAIN_BRANDING env var in examples and README #332 2026-05-28 20:13:11 +02:00
Linus Rath 956acb69ce feat: add NEXT_PUBLIC_DEFAULT_LOCALE for fallback UI locale #243 2026-05-25 17:01:52 +02:00
Linus Rath 5aa6d7a2f0 docs: document OAUTH_ALLOW_PRIVATE_ENDPOINTS in env/config examples 2026-05-22 17:57:41 +02:00
Linus Rath 51745ea03d feat: web setup wizard + admin config/state dir split (#226) 2026-05-09 17:37:41 +02:00
Linus Rath ec581ce53e feat: update Docker configuration 2026-04-28 17:27:47 +02:00
Linus Rath 0f3b506604 feat: add extension preview page and API for detailed extension information 2026-04-28 15:55:23 +02:00
Linus Rath 9c7452e7fd chore: add admin dashboard data directory configuration to environment files 2026-04-23 11:22:14 +02:00
Linus Rath 6b7c849332 refactor: remove Stalwart API URL configuration 2026-04-21 17:50:18 +02:00
Linus Rath 8bdadc7ba3 fix: standardize punctuation 2026-04-16 19:07:42 +02:00
nesgarbo fb2f0c9158 fix: use 'company' consistently in .env.example branding comments 2026-04-15 11:25:16 +02:00
nesgarbo 7daa46e73e docs: document PWA and branding env vars in .env.example
Reorganize the Branding section with subsections (App identity, Icons &
favicon, PWA appearance, Logos, Login page) and document the new variables
APP_SHORT_NAME, APP_DESCRIPTION, PWA_ICON_URL, PWA_THEME_COLOR and
PWA_BACKGROUND_COLOR.
2026-04-15 11:25:16 +02:00
Pascal Dietrich 60efb047d8 docs: add SESSION_SECRET_FILE and OAUTH_CLIENT_SECRET_FILE env vars 2026-04-09 22:13:08 +02:00
Linus Rath 99d5276cfa feat: add support for custom JMAP server endpoints in login and settings 2026-03-29 00:47:35 +01:00
Linus Rath 415c961937 feat: enforce forced/managed plugins and policy. Split user upload permission 2026-03-27 16:33:17 +01:00
Linus Rath a835af2d71 fix: update .env.example to clarify Docker volume mounting for settings data directory 2026-03-21 20:45:22 +01:00
Linus Rath 8a2ef5a6c5 feat: integrate webcrypto-liner for legacy algorithm support in S/MIME handling 2026-03-18 14:29:29 +01:00
Linus Rath 7c5785e9e8 feat: enhance branding options with custom favicon and logos in configuration 2026-03-17 15:25:06 +01:00
Linus Rath 6680b65863 feat: add server listen address configuration to .env and README 2026-03-17 14:58:12 +01:00
Linus Rath 85b5b3c4f1 feat: refactor authentication handling to use centralized Stalwart credentials management 2026-03-14 15:55:59 +01:00
Linus Rath 2fe1b01d4d feat: add configurable logo to login page with light/dark mode support
- Display Bulwark logo on the login page, with theme-aware switching
  between light and dark variants based on the resolved theme
- Add LOGIN_LOGO_LIGHT_URL and LOGIN_LOGO_DARK_URL env variables to
  allow custom logo overrides (defaults to bundled Bulwark branding)
- Expose logo config through /api/config endpoint and useConfig hook
- Add logo URL prompts to the setup.sh installer branding step
- Rename branding assets to use underscores instead of spaces
2026-03-13 19:45:09 +01:00
Linus Rath e85d0b946e chore: rename JMAP Webmail to Bulwark Webmail and update all URLs 2026-03-13 13:14:08 +01:00