chore: rename JMAP Webmail to Bulwark Webmail and update all URLs

This commit is contained in:
Linus Rath
2026-03-13 13:14:08 +01:00
parent 02344d169c
commit e85d0b946e
14 changed files with 74 additions and 74 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
# JMAP Webmail — Production Configuration # Bulwark Webmail — Production Configuration
# Copy this file to .env.local and fill in your values. # Copy this file to .env.local and fill in your values.
# For development with the built-in mock server, see .env.dev.example instead. # For development with the built-in mock server, see .env.dev.example instead.
@@ -7,7 +7,7 @@
# ============================================================================= # =============================================================================
# App name displayed in the UI # App name displayed in the UI
APP_NAME=JMAP Webmail APP_NAME=Bulwark Webmail
# URL of your JMAP-compatible mail server (required) # URL of your JMAP-compatible mail server (required)
JMAP_SERVER_URL=https://your-jmap-server.com JMAP_SERVER_URL=https://your-jmap-server.com
@@ -94,5 +94,5 @@ JMAP_SERVER_URL=https://your-jmap-server.com
# These are baked into the bundle at build time. The runtime variables above # These are baked into the bundle at build time. The runtime variables above
# take priority when both are set. # take priority when both are set.
# #
# NEXT_PUBLIC_APP_NAME=JMAP Webmail # NEXT_PUBLIC_APP_NAME=Bulwark Webmail
# NEXT_PUBLIC_JMAP_SERVER_URL=https://your-jmap-server.com # NEXT_PUBLIC_JMAP_SERVER_URL=https://your-jmap-server.com
+6 -6
View File
@@ -1,6 +1,6 @@
# Contributing to JMAP Webmail # Contributing to Bulwark Webmail
Thank you for your interest in contributing to JMAP Webmail! This document provides guidelines and information for contributors. Thank you for your interest in contributing to Bulwark Webmail! This document provides guidelines and information for contributors.
## Getting Started ## Getting Started
@@ -8,8 +8,8 @@ Thank you for your interest in contributing to JMAP Webmail! This document provi
1. **Fork and clone** the repository: 1. **Fork and clone** the repository:
```bash ```bash
git clone https://github.com/root-fr/jmap-webmail.git git clone https://github.com/bulwarkmail/webmail.git
cd jmap-webmail cd webmail
``` ```
2. **Install dependencies**: 2. **Install dependencies**:
@@ -156,7 +156,7 @@ docs: update README with keyboard shortcuts
## Project Structure ## Project Structure
``` ```
jmap-webmail/ webmail/
├── app/ # Next.js App Router pages ├── app/ # Next.js App Router pages
│ └── [locale]/ # Locale-aware routing │ └── [locale]/ # Locale-aware routing
├── components/ # React components ├── components/ # React components
@@ -187,4 +187,4 @@ If you have questions about contributing, feel free to:
- Open an issue for discussion - Open an issue for discussion
- Check existing issues and pull requests - Check existing issues and pull requests
Thank you for helping improve JMAP Webmail! Thank you for helping improve Bulwark Webmail!
+3 -3
View File
@@ -8,10 +8,10 @@ RUN npx next build --webpack
FROM node:24-alpine AS runner FROM node:24-alpine AS runner
LABEL org.opencontainers.image.title="JMAP Webmail" LABEL org.opencontainers.image.title="Bulwark Webmail"
LABEL org.opencontainers.image.description="Modern webmail client built with Next.js and the JMAP protocol" LABEL org.opencontainers.image.description="Modern webmail client built with Next.js and the JMAP protocol"
LABEL org.opencontainers.image.source="https://github.com/root-fr/jmap-webmail" LABEL org.opencontainers.image.source="https://github.com/bulwarkmail/webmail"
LABEL org.opencontainers.image.url="https://github.com/root-fr/jmap-webmail" LABEL org.opencontainers.image.url="https://github.com/bulwarkmail/webmail"
LABEL org.opencontainers.image.licenses="MIT" LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.vendor="root.cloud" LABEL org.opencontainers.image.vendor="root.cloud"
+8 -8
View File
@@ -1,4 +1,4 @@
# JMAP Webmail # Bulwark Webmail
A webmail client for [Stalwart Mail Server](https://stalw.art/), built with Next.js and the JMAP protocol. A webmail client for [Stalwart Mail Server](https://stalw.art/), built with Next.js and the JMAP protocol.
@@ -126,7 +126,7 @@ Stalwart is a mail server written in Rust with native JMAP support, not IMAP/SMT
### Deployment ### Deployment
- Pre-built Docker images on [Docker Hub](https://hub.docker.com/r/rootfr/jmap-webmail) and [GHCR](https://ghcr.io/root-fr/jmap-webmail) (amd64/arm64) - Pre-built Docker images on [Docker Hub](https://hub.docker.com/r/bulwarkmail/webmail) and [GHCR](https://ghcr.io/bulwarkmail/webmail) (amd64/arm64)
- Multi-stage build with standalone output - Multi-stage build with standalone output
- Runtime environment variables (no rebuild needed) - Runtime environment variables (no rebuild needed)
- Health check endpoint - Health check endpoint
@@ -153,8 +153,8 @@ Stalwart is a mail server written in Rust with native JMAP support, not IMAP/SMT
### Installation ### Installation
```bash ```bash
git clone https://github.com/root-fr/jmap-webmail.git git clone https://github.com/bulwarkmail/webmail.git
cd jmap-webmail cd webmail
npm install npm install
cp .env.example .env.local cp .env.example .env.local
``` ```
@@ -215,10 +215,10 @@ npm start
```bash ```bash
# Pre-built image # Pre-built image
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com rootfr/jmap-webmail:latest docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com bulwarkmail/webmail:latest
# From GHCR # From GHCR
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com ghcr.io/root-fr/jmap-webmail:latest docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com ghcr.io/bulwarkmail/webmail:latest
# With docker compose # With docker compose
cp .env.example .env.local cp .env.example .env.local
@@ -226,8 +226,8 @@ cp .env.example .env.local
docker compose up -d docker compose up -d
# Build from source # Build from source
docker build -t jmap-webmail . docker build -t bulwark-webmail .
docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com jmap-webmail docker run -p 3000:3000 -e JMAP_SERVER_URL=https://mail.example.com bulwark-webmail
``` ```
## Keyboard shortcuts ## Keyboard shortcuts
+3 -3
View File
@@ -1,6 +1,6 @@
# JMAP Webmail - Roadmap # Bulwark Webmail - Roadmap
This document tracks the development status and planned features for JMAP Webmail. This document tracks the development status and planned features for Bulwark Webmail.
## Completed Features ## Completed Features
@@ -230,7 +230,7 @@ This document tracks the development status and planned features for JMAP Webmai
- [x] Health check endpoint - [x] Health check endpoint
- [x] Docker support (multi-stage build, docker-compose, standalone output) - [x] Docker support (multi-stage build, docker-compose, standalone output)
- [x] Structured server-side logger (text/JSON format, configurable level) - [x] Structured server-side logger (text/JSON format, configurable level)
- [x] Pre-built Docker image on [Docker Hub](https://hub.docker.com/r/rootfr/jmap-webmail) and [GHCR](https://ghcr.io/root-fr/jmap-webmail) with multi-arch support (amd64/arm64) - [x] Pre-built Docker image on [Docker Hub](https://hub.docker.com/r/bulwarkmail/webmail) and [GHCR](https://ghcr.io/bulwarkmail/webmail) with multi-arch support (amd64/arm64)
- [x] GitHub Actions CI/CD for automated image publishing on releases - [x] GitHub Actions CI/CD for automated image publishing on releases
- [x] CVE remediation: remove npm from production image, upgrade Alpine packages - [x] CVE remediation: remove npm from production image, upgrade Alpine packages
- [x] Server-side update check (logs newer version availability on startup) - [x] Server-side update check (logs newer version availability on startup)
+13 -13
View File
@@ -108,14 +108,14 @@ const emails: MockEmail[] = [
id: 'email-001', threadId: 'thread-001', mailboxIds: { 'mb-inbox': true }, keywords: {}, size: 4200, receivedAt: daysAgo(0), id: 'email-001', threadId: 'thread-001', mailboxIds: { 'mb-inbox': true }, keywords: {}, size: 4200, receivedAt: daysAgo(0),
from: [{ name: 'Sophie Müller', email: 'sophie@eurotech.example' }], from: [{ name: 'Sophie Müller', email: 'sophie@eurotech.example' }],
to: [{ name: 'Dev User', email: 'dev@localhost' }], cc: [], to: [{ name: 'Dev User', email: 'dev@localhost' }], cc: [],
subject: 'Willkommen bei JMAP Webmail!', subject: 'Willkommen bei Bulwark Webmail!',
preview: 'Hallo! This is a sample email to help you get started with the JMAP Webmail development environment.', preview: 'Hallo! This is a sample email to help you get started with the Bulwark Webmail development environment.',
hasAttachment: false, hasAttachment: false,
textBody: [{ partId: 'p1', blobId: 'blob-001', size: 280, type: 'text/plain' }], textBody: [{ partId: 'p1', blobId: 'blob-001', size: 280, type: 'text/plain' }],
htmlBody: [{ partId: 'p2', blobId: 'blob-002', size: 420, type: 'text/html' }], htmlBody: [{ partId: 'p2', blobId: 'blob-002', size: 420, type: 'text/html' }],
bodyValues: { bodyValues: {
p1: { value: 'Hallo!\n\nThis is a sample email to help you get started with the JMAP Webmail development environment.\n\nFeel free to explore the UI — all data here is mock data.\n\nBeste Grüße,\nSophie' }, p1: { value: 'Hallo!\n\nThis is a sample email to help you get started with the Bulwark Webmail development environment.\n\nFeel free to explore the UI — all data here is mock data.\n\nBeste Grüße,\nSophie' },
p2: { value: '<p>Hallo!</p><p>This is a sample email to help you get started with the <strong>JMAP Webmail</strong> development environment.</p><p>Feel free to explore the UI — all data here is mock data.</p><p>Beste Grüße,<br>Sophie</p>' }, p2: { value: '<p>Hallo!</p><p>This is a sample email to help you get started with the <strong>Bulwark Webmail</strong> development environment.</p><p>Feel free to explore the UI — all data here is mock data.</p><p>Beste Grüße,<br>Sophie</p>' },
}, },
}, },
{ {
@@ -154,7 +154,7 @@ const emails: MockEmail[] = [
id: 'email-004', threadId: 'thread-004', mailboxIds: { 'mb-inbox': true }, keywords: { '$label:red': true }, size: 6200, receivedAt: daysAgo(0), id: 'email-004', threadId: 'thread-004', mailboxIds: { 'mb-inbox': true }, keywords: { '$label:red': true }, size: 6200, receivedAt: daysAgo(0),
from: [{ name: 'GitHub Notifications', email: 'notifications@github.com' }], from: [{ name: 'GitHub Notifications', email: 'notifications@github.com' }],
to: [{ name: 'Dev User', email: 'dev@localhost' }], cc: [], to: [{ name: 'Dev User', email: 'dev@localhost' }], cc: [],
subject: '[jmap-webmail] New issue: Add dark mode toggle (#42)', subject: '[bulwark-webmail] New issue: Add dark mode toggle (#42)',
preview: 'A new issue has been opened by @contributor. It would be great to have a dark mode toggle in the settings panel.', preview: 'A new issue has been opened by @contributor. It would be great to have a dark mode toggle in the settings panel.',
hasAttachment: false, hasAttachment: false,
textBody: [{ partId: 'p1', blobId: 'blob-007', size: 350, type: 'text/plain' }], textBody: [{ partId: 'p1', blobId: 'blob-007', size: 350, type: 'text/plain' }],
@@ -236,8 +236,8 @@ const emails: MockEmail[] = [
textBody: [{ partId: 'p1', blobId: 'blob-034', size: 380, type: 'text/plain' }], textBody: [{ partId: 'p1', blobId: 'blob-034', size: 380, type: 'text/plain' }],
htmlBody: [{ partId: 'p2', blobId: 'blob-035', size: 520, type: 'text/html' }], htmlBody: [{ partId: 'p2', blobId: 'blob-035', size: 520, type: 'text/html' }],
bodyValues: { bodyValues: {
p1: { value: 'Salut,\n\nI just pushed the contact vCard import feature (JMAP-342). Could you review when you get a chance?\n\nPR: https://github.example/jmap-webmail/pull/342\n\nKey changes:\n- New vCard parser with v3/v4 support\n- Batch import with progress indicator\n- Duplicate detection and merge UI\n- Unit tests for edge cases\n\nMerci d\'avance,\nÉlise' }, p1: { value: 'Salut,\n\nI just pushed the contact vCard import feature (JMAP-342). Could you review when you get a chance?\n\nPR: https://github.example/bulwark-webmail/pull/342\n\nKey changes:\n- New vCard parser with v3/v4 support\n- Batch import with progress indicator\n- Duplicate detection and merge UI\n- Unit tests for edge cases\n\nMerci d\'avance,\nÉlise' },
p2: { value: '<p>Salut,</p><p>I just pushed the contact vCard import feature (<code>JMAP-342</code>). Could you review when you get a chance?</p><p>PR: <a href="#">jmap-webmail/pull/342</a></p><h4>Key changes:</h4><ul><li>New vCard parser with v3/v4 support</li><li>Batch import with progress indicator</li><li>Duplicate detection and merge UI</li><li>Unit tests for edge cases</li></ul><p>Merci d\'avance,<br>Élise</p>' }, p2: { value: '<p>Salut,</p><p>I just pushed the contact vCard import feature (<code>JMAP-342</code>). Could you review when you get a chance?</p><p>PR: <a href="#">bulwark-webmail/pull/342</a></p><h4>Key changes:</h4><ul><li>New vCard parser with v3/v4 support</li><li>Batch import with progress indicator</li><li>Duplicate detection and merge UI</li><li>Unit tests for edge cases</li></ul><p>Merci d\'avance,<br>Élise</p>' },
}, },
}, },
{ {
@@ -407,7 +407,7 @@ const emails: MockEmail[] = [
textBody: [{ partId: 'p1', blobId: 'blob-063', size: 350, type: 'text/plain' }], textBody: [{ partId: 'p1', blobId: 'blob-063', size: 350, type: 'text/plain' }],
htmlBody: [], htmlBody: [],
bodyValues: { bodyValues: {
p1: { value: '¡Hola!\n\nThe new brand guidelines are finalized. Key updates:\n\n- Primary color shifted to #7c3aed (from #6366f1)\n- New typography scale (Inter for body, Cal Sans for headings)\n- Updated icon set (Lucide → custom icon font)\n- Dark mode color tokens added\n\nI\'ve also updated the Figma component library. Link: figma.example/jmap-webmail-v2\n\nBrand guidelines PDF attached.\n\nMaría' }, p1: { value: '¡Hola!\n\nThe new brand guidelines are finalized. Key updates:\n\n- Primary color shifted to #7c3aed (from #6366f1)\n- New typography scale (Inter for body, Cal Sans for headings)\n- Updated icon set (Lucide → custom icon font)\n- Dark mode color tokens added\n\nI\'ve also updated the Figma component library. Link: figma.example/bulwark-webmail-v2\n\nBrand guidelines PDF attached.\n\nMaría' },
}, },
attachments: [ attachments: [
{ partId: 'att10', blobId: 'blob-att-010', size: 3200000, name: 'Markenrichtlinien-v2.pdf', type: 'application/pdf' }, { partId: 'att10', blobId: 'blob-att-010', size: 3200000, name: 'Markenrichtlinien-v2.pdf', type: 'application/pdf' },
@@ -430,14 +430,14 @@ const emails: MockEmail[] = [
id: 'email-039', threadId: 'thread-034', mailboxIds: { 'mb-inbox': true }, keywords: {}, size: 3400, receivedAt: hoursAgo(0.25), id: 'email-039', threadId: 'thread-034', mailboxIds: { 'mb-inbox': true }, keywords: {}, size: 3400, receivedAt: hoursAgo(0.25),
from: [{ name: 'CI/CD Pipeline', email: 'ci@github.example' }], from: [{ name: 'CI/CD Pipeline', email: 'ci@github.example' }],
to: [{ name: 'Dev User', email: 'dev@localhost' }], cc: [], to: [{ name: 'Dev User', email: 'dev@localhost' }], cc: [],
subject: '❌ Build failed: main — jmap-webmail #1337', subject: '❌ Build failed: main — bulwark-webmail #1337',
preview: 'Build #1337 on branch main failed. 2 test(s) failed in email-sanitization.test.ts.', preview: 'Build #1337 on branch main failed. 2 test(s) failed in email-sanitization.test.ts.',
hasAttachment: false, hasAttachment: false,
textBody: [{ partId: 'p1', blobId: 'blob-060', size: 450, type: 'text/plain' }], textBody: [{ partId: 'p1', blobId: 'blob-060', size: 450, type: 'text/plain' }],
htmlBody: [{ partId: 'p2', blobId: 'blob-061', size: 600, type: 'text/html' }], htmlBody: [{ partId: 'p2', blobId: 'blob-061', size: 600, type: 'text/html' }],
bodyValues: { bodyValues: {
p1: { value: '❌ Build #1337 FAILED\n\nRepository: jmap-webmail\nBranch: main\nCommit: a3f9c21 "fix: sanitize CSS in email body"\nTriggered by: @elise-moreau\n\nFailed tests:\n ✗ email-sanitization.test.ts > should strip javascript: URLs\n ✗ email-sanitization.test.ts > should handle nested style tags\n\nPassed: 247 | Failed: 2 | Skipped: 0\nDuration: 42.0s\n\nView full logs: https://github.example/jmap-webmail/actions/runs/1337' }, p1: { value: '❌ Build #1337 FAILED\n\nRepository: bulwark-webmail\nBranch: main\nCommit: a3f9c21 "fix: sanitize CSS in email body"\nTriggered by: @elise-moreau\n\nFailed tests:\n ✗ email-sanitization.test.ts > should strip javascript: URLs\n ✗ email-sanitization.test.ts > should handle nested style tags\n\nPassed: 247 | Failed: 2 | Skipped: 0\nDuration: 42.0s\n\nView full logs: https://github.example/bulwark-webmail/actions/runs/1337' },
p2: { value: '<h3>❌ Build #1337 FAILED</h3><table><tr><td>Repository</td><td>jmap-webmail</td></tr><tr><td>Branch</td><td><code>main</code></td></tr><tr><td>Commit</td><td><code>a3f9c21</code> "fix: sanitize CSS in email body"</td></tr></table><h4>Failed tests:</h4><ul><li>❌ <code>email-sanitization.test.ts</code> &gt; should strip javascript: URLs</li><li>❌ <code>email-sanitization.test.ts</code> &gt; should handle nested style tags</li></ul><p><strong>Passed: 247</strong> | <strong style="color:red">Failed: 2</strong> | Skipped: 0</p>' }, p2: { value: '<h3>❌ Build #1337 FAILED</h3><table><tr><td>Repository</td><td>bulwark-webmail</td></tr><tr><td>Branch</td><td><code>main</code></td></tr><tr><td>Commit</td><td><code>a3f9c21</code> "fix: sanitize CSS in email body"</td></tr></table><h4>Failed tests:</h4><ul><li>❌ <code>email-sanitization.test.ts</code> &gt; should strip javascript: URLs</li><li>❌ <code>email-sanitization.test.ts</code> &gt; should handle nested style tags</li></ul><p><strong>Passed: 247</strong> | <strong style="color:red">Failed: 2</strong> | Skipped: 0</p>' },
}, },
}, },
// ===================================================================== // =====================================================================
@@ -729,8 +729,8 @@ const IDENTITIES = [
email: 'dev@localhost', email: 'dev@localhost',
replyTo: null, replyTo: null,
bcc: null, bcc: null,
textSignature: '-- \nDev User\nJMAP Webmail Developer', textSignature: '-- \nDev User\nBulwark Webmail Developer',
htmlSignature: '<p>--<br>Dev User<br><em>JMAP Webmail Developer</em></p>', htmlSignature: '<p>--<br>Dev User<br><em>Bulwark Webmail Developer</em></p>',
mayDelete: false, mayDelete: false,
}, },
]; ];
+1 -1
View File
@@ -15,7 +15,7 @@ const geistMono = Geist_Mono({
}); });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "JMAP Webmail", title: "Bulwark Webmail",
description: "Minimalist webmail client using JMAP protocol", description: "Minimalist webmail client using JMAP protocol",
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
services: services:
webmail: webmail:
image: ghcr.io/rathlinus/jmap-webmail:latest image: ghcr.io/bulwarkmail/webmail:latest
ports: ports:
- "3000:3000" - "3000:3000"
env_file: env_file:
+3 -3
View File
@@ -1,7 +1,7 @@
import { readFileSync } from "fs"; import { readFileSync } from "fs";
const VERSION_CHECK_URL = const VERSION_CHECK_URL =
"https://raw.githubusercontent.com/root-fr/jmap-webmail/main/VERSION"; "https://raw.githubusercontent.com/bulwarkmail/webmail/main/VERSION";
const SEMVER_RE = /^\d+\.\d+\.\d+$/; const SEMVER_RE = /^\d+\.\d+\.\d+$/;
@@ -19,7 +19,7 @@ const pkg = JSON.parse(
readFileSync(`${process.cwd()}/package.json`, "utf-8") readFileSync(`${process.cwd()}/package.json`, "utf-8")
); );
const current: string = pkg.version ?? "0.0.0"; const current: string = pkg.version ?? "0.0.0";
console.info(`JMAP Webmail v${current}`); console.info(`Bulwark Webmail v${current}`);
if (process.env.NODE_ENV === "production") { if (process.env.NODE_ENV === "production") {
fetch(VERSION_CHECK_URL, { fetch(VERSION_CHECK_URL, {
@@ -36,7 +36,7 @@ if (process.env.NODE_ENV === "production") {
if (!SEMVER_RE.test(remote)) return; if (!SEMVER_RE.test(remote)) return;
if (compareVersions(current, remote) > 0) { if (compareVersions(current, remote) > 0) {
console.info( console.info(
`Update available: v${remote} — https://github.com/root-fr/jmap-webmail` `Update available: v${remote} — https://github.com/bulwarkmail/webmail`
); );
} }
}) })
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "jmap-webmail", "name": "bulwark-webmail",
"version": "1.1.2", "version": "1.1.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "jmap-webmail", "name": "bulwark-webmail",
"version": "1.1.2", "version": "1.1.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
+5 -5
View File
@@ -1,16 +1,16 @@
{ {
"name": "jmap-webmail", "name": "bulwark-webmail",
"version": "1.1.2", "version": "1.1.2",
"description": "A modern JMAP webmail client built for Stalwart Mail Server", "description": "Bulwark Webmail — a modern webmail client built for Stalwart Mail Server",
"author": "Matthieu MALVACHE <matthieu@root.cloud>", "author": "Matthieu MALVACHE <matthieu@root.cloud>",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/root-fr/jmap-webmail.git" "url": "git+https://github.com/bulwarkmail/webmail.git"
}, },
"homepage": "https://github.com/root-fr/jmap-webmail", "homepage": "https://github.com/bulwarkmail/webmail",
"bugs": { "bugs": {
"url": "https://github.com/root-fr/jmap-webmail/issues" "url": "https://github.com/bulwarkmail/webmail/issues"
}, },
"keywords": [ "keywords": [
"jmap", "jmap",
+16 -16
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ============================================================================= # =============================================================================
# JMAP Webmail - Interactive Setup Script # Bulwark Webmail - Interactive Setup Script
# ============================================================================= # =============================================================================
set -euo pipefail set -euo pipefail
@@ -51,7 +51,7 @@ set -u
ENV_FILE="${SCRIPT_DIR}/.env.local" ENV_FILE="${SCRIPT_DIR}/.env.local"
# Config values (defaults) # Config values (defaults)
CFG_APP_NAME="JMAP Webmail" CFG_APP_NAME="Bulwark Webmail"
CFG_JMAP_SERVER_URL="" CFG_JMAP_SERVER_URL=""
CFG_STALWART_FEATURES="true" CFG_STALWART_FEATURES="true"
CFG_OAUTH_ENABLED="false" CFG_OAUTH_ENABLED="false"
@@ -396,9 +396,9 @@ draw_header() {
echo "" echo ""
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
box "JMAP WEBMAIL SETUP -- DRY RUN" "$MAGENTA" box "BULWARK WEBMAIL SETUP -- DRY RUN" "$MAGENTA"
else else
box "JMAP WEBMAIL SETUP" "$CYAN" box "BULWARK WEBMAIL SETUP" "$CYAN"
fi fi
echo "" echo ""
@@ -444,7 +444,7 @@ screen_welcome() {
local version local version
version=$(cat "${SCRIPT_DIR}/VERSION" 2>/dev/null || echo "dev") version=$(cat "${SCRIPT_DIR}/VERSION" 2>/dev/null || echo "dev")
print_center "${BOLD}Welcome to JMAP Webmail${RESET}" print_center "${BOLD}Welcome to Bulwark Webmail${RESET}"
print_center "${DIM}v${version}${RESET}" print_center "${DIM}v${version}${RESET}"
echo "" echo ""
echo "" echo ""
@@ -542,7 +542,7 @@ screen_server_config() {
draw_header draw_header
section_header 1 "Server Configuration" \ section_header 1 "Server Configuration" \
"Point JMAP Webmail at your mail server." "Point Bulwark Webmail at your mail server."
echo -e " ${BOLD}General${RESET}" echo -e " ${BOLD}General${RESET}"
echo -e " ${DIM}This name appears in the browser tab and on the login page.${RESET}" echo -e " ${DIM}This name appears in the browser tab and on the login page.${RESET}"
@@ -719,7 +719,7 @@ screen_logging_config() {
draw_header draw_header
section_header 4 "Logging" \ section_header 4 "Logging" \
"Control how JMAP Webmail writes logs." "Control how Bulwark Webmail writes logs."
echo -e " ${BOLD}Log Format${RESET}" echo -e " ${BOLD}Log Format${RESET}"
echo "" echo ""
@@ -788,7 +788,7 @@ screen_deployment() {
draw_header draw_header
section_header 6 "Deployment Method" \ section_header 6 "Deployment Method" \
"Choose how you want to run JMAP Webmail." "Choose how you want to run Bulwark Webmail."
local docker_available=false local docker_available=false
command -v docker &>/dev/null && docker_available=true command -v docker &>/dev/null && docker_available=true
@@ -940,7 +940,7 @@ write_env_file() {
cat > "$ENV_FILE" << ENVEOF cat > "$ENV_FILE" << ENVEOF
# ============================================================================= # =============================================================================
# JMAP Webmail -- Configuration # Bulwark Webmail -- Configuration
# Generated by setup.sh on $(date '+%Y-%m-%d %H:%M:%S') # Generated by setup.sh on $(date '+%Y-%m-%d %H:%M:%S')
# ============================================================================= # =============================================================================
@@ -1026,7 +1026,7 @@ run_deployment() {
echo -e " ${DIM}[dry-run] Would start: npm start (port ${CFG_PORT})${RESET}" echo -e " ${DIM}[dry-run] Would start: npm start (port ${CFG_PORT})${RESET}"
;; ;;
"docker") "docker")
echo -e " ${DIM}[dry-run] Would run: docker pull ghcr.io/rathlinus/jmap-webmail:latest${RESET}" echo -e " ${DIM}[dry-run] Would run: docker pull ghcr.io/bulwarkmail/webmail:latest${RESET}"
echo -e " ${DIM}[dry-run] Would start: container on port ${CFG_PORT}${RESET}" echo -e " ${DIM}[dry-run] Would start: container on port ${CFG_PORT}${RESET}"
;; ;;
"compose") "compose")
@@ -1063,8 +1063,8 @@ run_deployment() {
"docker") "docker")
echo -e " ${BOLD}Pulling Docker image...${RESET}" echo -e " ${BOLD}Pulling Docker image...${RESET}"
echo "" echo ""
(docker pull ghcr.io/rathlinus/jmap-webmail:latest 2>&1) & (docker pull ghcr.io/bulwarkmail/webmail:latest 2>&1) &
spinner $! "Pulling ghcr.io/rathlinus/jmap-webmail:latest" spinner $! "Pulling ghcr.io/bulwarkmail/webmail:latest"
echo "" echo ""
echo -e " ${OK} Image pulled!" echo -e " ${OK} Image pulled!"
@@ -1072,11 +1072,11 @@ run_deployment() {
echo -e " ${BOLD}To run the container:${RESET}" echo -e " ${BOLD}To run the container:${RESET}"
echo "" echo ""
echo -e " ${CYAN}docker run -d \\${RESET}" echo -e " ${CYAN}docker run -d \\${RESET}"
echo -e " ${CYAN} --name jmap-webmail \\${RESET}" echo -e " ${CYAN} --name bulwark-webmail \\${RESET}"
echo -e " ${CYAN} -p ${CFG_PORT}:3000 \\${RESET}" echo -e " ${CYAN} -p ${CFG_PORT}:3000 \\${RESET}"
echo -e " ${CYAN} --env-file .env.local \\${RESET}" echo -e " ${CYAN} --env-file .env.local \\${RESET}"
echo -e " ${CYAN} --restart unless-stopped \\${RESET}" echo -e " ${CYAN} --restart unless-stopped \\${RESET}"
echo -e " ${CYAN} ghcr.io/rathlinus/jmap-webmail:latest${RESET}" echo -e " ${CYAN} ghcr.io/bulwarkmail/webmail:latest${RESET}"
;; ;;
"compose") "compose")
@@ -1136,7 +1136,7 @@ screen_complete() {
echo "" echo ""
hr hr
echo "" echo ""
print_center "${DIM}Thank you for using JMAP Webmail!${RESET}" print_center "${DIM}Thank you for using Bulwark Webmail!${RESET}"
echo "" echo ""
} }
@@ -1217,7 +1217,7 @@ elif [[ -r /dev/tty ]] 2>/dev/null && (echo < /dev/tty) 2>/dev/null; then
else else
echo "Error: No interactive terminal available." echo "Error: No interactive terminal available."
echo "Download and run the script directly instead:" echo "Download and run the script directly instead:"
echo " curl -fsSL https://raw.githubusercontent.com/rathlinus/jmap-webmail/main/setup.sh -o setup.sh" echo " curl -fsSL https://raw.githubusercontent.com/bulwarkmail/webmail/main/setup.sh -o setup.sh"
echo " bash setup.sh --dry-run" echo " bash setup.sh --dry-run"
exit 1 exit 1
fi fi
+6 -6
View File
@@ -24,7 +24,7 @@
## 1. Overview ## 1. Overview
This document describes a system that allows the JMAP Webmail application to be extended through **themes** (visual customization) and **plugins** (functional extensions). Together, these are called **addons**. This document describes a system that allows the Bulwark Webmail application to be extended through **themes** (visual customization) and **plugins** (functional extensions). Together, these are called **addons**.
### Design Goals ### Design Goals
@@ -240,7 +240,7 @@ A plugin exports a single `activate` function and optionally a `deactivate` func
```ts ```ts
// index.ts — Plugin entry point // index.ts — Plugin entry point
import type { PluginContext } from "@jmap-webmail/addon-api"; import type { PluginContext } from "@bulwarkmail/addon-api";
export function activate(ctx: PluginContext) { export function activate(ctx: PluginContext) {
// Register a sidebar section // Register a sidebar section
@@ -817,7 +817,7 @@ Some hooks allow plugins to transform data flowing through them. For example, `e
ctx.hooks.on("email:compose:before-send", (draft) => { ctx.hooks.on("email:compose:before-send", (draft) => {
return { return {
...draft, ...draft,
htmlBody: draft.htmlBody + "<p>Sent from JMAP Webmail</p>", htmlBody: draft.htmlBody + "<p>Sent from Bulwark Webmail</p>",
}; };
}); });
``` ```
@@ -866,8 +866,8 @@ useHostTheme(): { mode: "light" | "dark"; resolvedMode: "light" | "dark" };
### Phase 3: Developer Experience ### Phase 3: Developer Experience
- [ ] Create `@jmap-webmail/addon-api` — TypeScript type definitions package. - [ ] Create `@bulwarkmail/addon-api` — TypeScript type definitions package.
- [ ] Create `create-jmap-addon` CLI scaffolding tool. - [ ] Create `create-bulwark-addon` CLI scaffolding tool.
- [ ] Write addon developer documentation with examples. - [ ] Write addon developer documentation with examples.
- [ ] Build a sample plugin (e.g., email translation) as a reference. - [ ] Build a sample plugin (e.g., email translation) as a reference.
- [ ] Add dev mode: hot-reload addons from local filesystem. - [ ] Add dev mode: hot-reload addons from local filesystem.
@@ -896,7 +896,7 @@ nord-theme/
`addon.json`: `addon.json`:
```json ```json
{ {
"id": "org.nordtheme.jmap-webmail", "id": "org.nordtheme.bulwark-webmail",
"name": "Nord", "name": "Nord",
"version": "1.0.0", "version": "1.0.0",
"type": "theme", "type": "theme",
+4 -4
View File
@@ -1280,8 +1280,8 @@ export const useEmailStore = create<EmailStore>((set, get) => ({
receivedAt: new Date().toISOString(), receivedAt: new Date().toISOString(),
from: [{ name: "GitHub", email: "notifications@github.com" }], from: [{ name: "GitHub", email: "notifications@github.com" }],
to: [{ email: "you@example.com" }], to: [{ email: "you@example.com" }],
subject: "[jmap-webmail] New pull request #42: Add OAuth2 module", subject: "[bulwark-webmail] New pull request #42: Add OAuth2 module",
preview: "dependabot[bot] opened a pull request in root-fr/jmap-webmail. This PR adds a comprehensive authentication module with OAuth2 PKCE support...", preview: "dependabot[bot] opened a pull request in bulwarkmail/webmail. This PR adds a comprehensive authentication module with OAuth2 PKCE support...",
hasAttachment: false, hasAttachment: false,
}, },
{ {
@@ -1358,8 +1358,8 @@ export const useEmailStore = create<EmailStore>((set, get) => ({
receivedAt: new Date(Date.now() - 172800000).toISOString(), receivedAt: new Date(Date.now() - 172800000).toISOString(),
from: [{ name: "Vercel", email: "notifications@vercel.com" }], from: [{ name: "Vercel", email: "notifications@vercel.com" }],
to: [{ email: "you@example.com" }], to: [{ email: "you@example.com" }],
subject: "Deployment successful: jmap-webmail \u2192 Production", subject: "Deployment successful: bulwark-webmail \u2192 Production",
preview: "Your project jmap-webmail has been deployed to production. Build completed in 47s. All checks passed. Preview: https://jmap-webmail.vercel.app...", preview: "Your project bulwark-webmail has been deployed to production. Build completed in 47s. All checks passed. Preview: https://bulwark-webmail.vercel.app...",
hasAttachment: false, hasAttachment: false,
}, },
{ {