Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
028c9d8
feat: publish native wrappers
dcoffin88 May 18, 2026
6ac421e
fix: nested native app scripts under frontend/packages
dcoffin88 May 18, 2026
9bb958f
update appid to actual domain
dcoffin88 May 18, 2026
eda90de
replace capacitor default icons
dcoffin88 May 18, 2026
b5eb995
Add email for deb compliance
dcoffin88 May 18, 2026
d04bcaa
Add homepage for deb compliance
dcoffin88 May 18, 2026
c80f75d
app versioning tied to release
dcoffin88 May 18, 2026
4e2962a
define portable
dcoffin88 May 18, 2026
4553fca
expand package coverage
dcoffin88 May 18, 2026
56e7a3e
add snap support
dcoffin88 May 18, 2026
4feb553
implement arm64 builder for snap
dcoffin88 May 18, 2026
a8434c8
fix snapcraft dependency
dcoffin88 May 18, 2026
8ff640c
additional snapcraft dependencies
dcoffin88 May 18, 2026
73e4cbe
add app icon to electron packages
dcoffin88 May 18, 2026
b0a50f0
fix package naming scheme
dcoffin88 May 18, 2026
144d058
builder name scheme
dcoffin88 May 18, 2026
28135be
chore: fix CVE-2020-27348
dcoffin88 May 18, 2026
7e5b627
revert: removing snap as appImage/deb/rpm already working
dcoffin88 May 18, 2026
dd3cbaa
miscellaneous bug fix
dcoffin88 May 18, 2026
702431d
bug: build apk location
dcoffin88 May 18, 2026
addbc9f
debug android build
dcoffin88 May 18, 2026
97d52ad
removed system tray from mac and linux
dcoffin88 May 19, 2026
bed8e22
forward notification toast to system
dcoffin88 May 19, 2026
85ea06c
ensuring unreadoverlay doesn't disappear
dcoffin88 May 19, 2026
fbff233
remove tray
dcoffin88 May 19, 2026
15f84da
revert changes
dcoffin88 May 19, 2026
509f00b
electron wrapper update
dcoffin88 May 27, 2026
9402662
Menu update
dcoffin88 May 27, 2026
260db4b
Notification bridge
dcoffin88 May 27, 2026
54dc1ff
Notification forwarder
dcoffin88 May 27, 2026
000c2d0
Update checker testing
dcoffin88 May 27, 2026
8c38bd0
Adding native quick actions
dcoffin88 May 27, 2026
80d7584
fix native action bridge
dcoffin88 May 27, 2026
c8acf1d
build apps with github release number
dcoffin88 May 27, 2026
1b27456
fix double build
dcoffin88 May 27, 2026
0cbd78d
fix missing bracket
dcoffin88 May 27, 2026
2113995
Fix update install and message clip
dcoffin88 May 27, 2026
e32a6a0
fix message
dcoffin88 May 27, 2026
296c02b
fix native quick actions bridge
dcoffin88 May 27, 2026
50729d1
fix check for nativebridgeready
dcoffin88 May 27, 2026
74f7342
fix install update notification no longer times out.
dcoffin88 May 27, 2026
2e5eec6
feat silent startup update check
dcoffin88 May 27, 2026
30f0772
fix macos update bar
dcoffin88 May 27, 2026
b93b53e
enable wrap on notification toast for longer system messages
dcoffin88 May 27, 2026
46f31ff
fix bridge unread count badge to linux api
dcoffin88 May 27, 2026
cbde2ba
fix linux updater
dcoffin88 May 27, 2026
4062af7
correct linux update flow and metadata
dcoffin88 May 27, 2026
220d1d2
schema fix
dcoffin88 May 27, 2026
c8a36a4
fix linux packagename
dcoffin88 May 27, 2026
61a4954
remove appimage option
dcoffin88 May 27, 2026
b29fa7b
changing deb and rpm to update through shell
dcoffin88 May 27, 2026
9dfdaf4
to fix unread badge on rpm
dcoffin88 May 28, 2026
94dc083
add libunity dependency for counter badge
dcoffin88 May 28, 2026
1c44328
fix linux update flow
dcoffin88 May 28, 2026
f51ce0c
fix rpm build
dcoffin88 May 28, 2026
d5628be
Update README.md
dcoffin88 May 28, 2026
98bb853
feat to start forwarding inapp new mail notices to os
dcoffin88 May 28, 2026
266941c
fix to notify system os of new mail when minimized
dcoffin88 May 28, 2026
3db11d9
expand bridge to open new mail from os notification
dcoffin88 May 28, 2026
e96b308
feat add os default handlers
dcoffin88 May 28, 2026
e3c2ed7
fix windows default mail handler
dcoffin88 May 28, 2026
fd73722
rewrite host unavailable error page to branded page
dcoffin88 May 28, 2026
277ba0f
expand branded host unavailable page catcher
dcoffin88 May 28, 2026
3af2df8
implementing android
dcoffin88 May 28, 2026
9e1ad88
add android signing key
dcoffin88 May 28, 2026
a1f9e52
pre pull request cleanup
dcoffin88 May 28, 2026
df9f2de
Update .dockerignore
dcoffin88 May 28, 2026
ba187a0
fixed setup page flashing on every open
dcoffin88 May 28, 2026
ae2b927
enable android permission prompt
dcoffin88 May 28, 2026
9556632
update android mail handler intent
dcoffin88 May 28, 2026
2ae76cf
fixing android notification prompt
dcoffin88 May 28, 2026
023156e
updating android bridge
dcoffin88 May 28, 2026
8565cfc
fix android navigation integration
dcoffin88 May 28, 2026
138158f
integrate new mail notifications
dcoffin88 May 28, 2026
7bef75e
rename shortcuts
dcoffin88 May 28, 2026
058a596
implement background new mail checker
dcoffin88 May 28, 2026
ef8dbc1
sync quick action without displaying app
dcoffin88 May 29, 2026
8b80814
revert Commit d71d10e
dcoffin88 May 29, 2026
f161a8e
implement android updater
dcoffin88 May 29, 2026
53aeae4
enable AlertDialog for update flow
dcoffin88 May 30, 2026
e6ae870
update from notification install button
dcoffin88 May 30, 2026
97c7d55
android install button update flow
dcoffin88 May 30, 2026
441a002
fix in app install button
dcoffin88 May 30, 2026
ccdce8d
fix capacitor bridge
dcoffin88 May 30, 2026
e6bca3d
android notification quick actions
dcoffin88 May 30, 2026
d38db54
optimize android notification action flow
dcoffin88 May 30, 2026
d8299f6
implement notification quick actions for windows and macos
dcoffin88 May 30, 2026
e72da49
fix desktop notification reply to bridge
dcoffin88 May 30, 2026
16265e1
pre pull request cleanup
dcoffin88 May 30, 2026
4bdc2b7
cherrypick node_modules/tmp to 0.2.7
dcoffin88 May 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions .github/workflows/publish-apps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
name: Publish Apps

on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:

permissions:
contents: write

jobs:
desktop:
name: Electron (${{ matrix.os }})
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os:
- windows-latest
- macos-latest
- ubuntu-latest

steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: "22"
cache: "npm"
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
working-directory: frontend
run: npm ci

- name: Resolve app version
id: app-version
shell: bash
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
DISPATCH_VERSION: ${{ github.event.inputs.version }}
REF_NAME: ${{ github.ref_name }}
run: |
VERSION="${RELEASE_TAG:-${DISPATCH_VERSION:-$REF_NAME}}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Set app version
working-directory: frontend
run: npm run app:version -- "${{ steps.app-version.outputs.version }}" "${{ github.run_number }}"

- name: Build Electron package
if: matrix.os != 'ubuntu-latest'
working-directory: frontend
run: npm run electron:dist
env:
CSC_IDENTITY_AUTO_DISCOVERY: "false"

- name: Build Linux x64 Electron packages
if: matrix.os == 'ubuntu-latest'
working-directory: frontend
run: npm run electron:dist -- --linux deb rpm --x64
env:
CSC_IDENTITY_AUTO_DISCOVERY: "false"

- name: Build Linux arm64 Electron packages
if: matrix.os == 'ubuntu-latest'
working-directory: frontend
run: npm run electron:dist -- --linux deb rpm --arm64
env:
CSC_IDENTITY_AUTO_DISCOVERY: "false"

- name: Rename Linux artifacts
if: matrix.os == 'ubuntu-latest'
working-directory: frontend
run: node packages/scripts/rename-linux-artifacts.cjs

- name: Upload Electron artifacts
uses: actions/upload-artifact@v4
with:
name: mailflow-electron-${{ matrix.os }}
if-no-files-found: error
path: |
frontend/packages/release/*.deb
frontend/packages/release/*.dmg
frontend/packages/release/*.exe
frontend/packages/release/*.rpm

android:
name: Android
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: "22"
cache: "npm"
cache-dependency-path: frontend/package-lock.json

- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "21"

- uses: android-actions/setup-android@v3

- name: Install dependencies
working-directory: frontend
run: npm ci

- name: Resolve app version
id: app-version
shell: bash
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
DISPATCH_VERSION: ${{ github.event.inputs.version }}
REF_NAME: ${{ github.ref_name }}
run: |
VERSION="${RELEASE_TAG:-${DISPATCH_VERSION:-$REF_NAME}}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Set app version
working-directory: frontend
run: npm run app:version -- "${{ steps.app-version.outputs.version }}" "${{ github.run_number }}"

- name: Prepare Android release signing
shell: bash
env:
MAILFLOW_ANDROID_KEYSTORE_BASE64: ${{ secrets.MAILFLOW_ANDROID_KEYSTORE_BASE64 }}
run: |
if [ -n "$MAILFLOW_ANDROID_KEYSTORE_BASE64" ]; then
mkdir -p "$RUNNER_TEMP/mailflow-signing"
echo "$MAILFLOW_ANDROID_KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/mailflow-signing/release.keystore"
echo "MAILFLOW_ANDROID_STORE_FILE=$RUNNER_TEMP/mailflow-signing/release.keystore" >> "$GITHUB_ENV"
fi

- name: Build Android package
working-directory: frontend
run: npm run android:dist
env:
MAILFLOW_ANDROID_STORE_PASSWORD: ${{ secrets.MAILFLOW_ANDROID_STORE_PASSWORD }}
MAILFLOW_ANDROID_KEY_ALIAS: ${{ secrets.MAILFLOW_ANDROID_KEY_ALIAS }}
MAILFLOW_ANDROID_KEY_PASSWORD: ${{ secrets.MAILFLOW_ANDROID_KEY_PASSWORD }}

- name: List Android release artifacts
if: always()
working-directory: frontend
run: find packages/android/app/build -maxdepth 6 -type f | sort || true

- name: Upload Android artifact
uses: actions/upload-artifact@v4
with:
name: mailflow-android
if-no-files-found: error
path: frontend/packages/release/*.apk

release:
name: Attach to GitHub Release
needs:
- desktop
- android
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'release' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest

steps:
- name: Resolve app version
id: app-version
shell: bash
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
DISPATCH_VERSION: ${{ github.event.inputs.version }}
REF_NAME: ${{ github.ref_name }}
run: |
VERSION="${RELEASE_TAG:-${DISPATCH_VERSION:-$REF_NAME}}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Publish release files
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.app-version.outputs.version }}
files: |
artifacts/**/*.apk
artifacts/**/*.deb
artifacts/**/*.dmg
artifacts/**/*.exe
artifacts/**/*.rpm
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ node_modules/
# Build output
frontend/dist/
frontend/.vite/
frontend/packages/release/

# TLS certs (generated locally or via Let's Encrypt)
certs/
Expand Down
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,67 @@ nginx (frontend container — internal only)
└── backend, PostgreSQL, Redis (internal network, unchanged)
```

## Desktop and Android apps

MailFlow remains a self-hosted web app, but release builds also publish native wrappers for users who prefer an installed desktop or mobile application.

- Windows, macOS, and Linux use Electron-based packages.
- Android uses a Capacitor WebView wrapper.
- On first launch, the native wrapper prompts for the MailFlow server URL, such as `https://mail.your-domain.com`, stores it locally, and connects to that server.
- Native package sources live under `frontend/packages`.

Install release builds from the latest MailFlow release:

- **Windows**:
- Download the latest `.exe` installer and run it.
- **macOS**:
- Download the latest `Universal.dmg` release and install the app.
- On first launch, macOS may display:
- `"MailFlow" can't be opened because Apple cannot check it for malicious software`.
- Click OK, then open:
- Settings -> Privacy & Security.
- Click Open Anyway beside:
- `"MailFlow" was blocked from use because it is not from an identified developer`.
- Click Open on the second confirmation dialog.
- MailFlow will run normally afterward, including future updates.
- **Ubuntu / Debian**
- Download the latest `.deb` release and install it:

```bash
sudo dpkg -i MailFlow-<version>-amd64.deb
```
or
```bash
sudo dpkg -i MailFlow-<version>-arm64.deb
```
- If dependencies are missing:
```bash
sudo apt-get install -f
```
- **Fedora / Red Hat**
- Download the latest `.rpm` release and install it:

```bash
sudo dnf install MailFlow-<version>-x86_64.rpm
```
or
```bash
sudo dnf install MailFlow-<version>-aarch64.rpm
```

- **Android**
- Download the latest Android `.apk` release and install it manually.

Local Development Builds:

```bash
cd frontend
npm ci
npm run electron:dist
npm run android:dist
```
---

## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=maathimself/mailflow&type=Date)](https://star-history.com/#maathimself/mailflow&Date)
Expand Down
3 changes: 3 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ node_modules
dist
.git
*.local
packages/android
packages/release
packages/electron
Loading