InboxBridge is a self-hosted mail importer. It connects to one or more source mailboxes, reads their messages, and imports those messages into one destination mailbox so you can keep a "one inbox, many accounts" workflow without relying on email forwarding.
It is designed for people who want to keep mail from several accounts together in one place while still controlling where credentials, tokens, and imported-message history are stored.
Explore the public project page: https://tdferreira.github.io/inboxbridge/
It gives a quick tour of the product, the top-level architecture, the self-hosted security model, and the bootstrap .env helper for operators.
InboxBridge can:
- read mail from IMAP and POP3 source accounts
- import mail into Gmail through the Gmail API
- append mail into IMAP destination mailboxes such as Outlook and other providers
- manage source accounts either from
.envor through the web interface - store UI-managed secrets and OAuth tokens encrypted in PostgreSQL
- support multi-user or single-user deployments
- provide a browser-based admin UI plus a lightweight
/remotecontrol page for phones and quick access - show live polling progress with pause, resume, stop, retry, and queue reprioritization controls
- let IMAP sources opt into real-time IMAP IDLE watching with durable UID checkpoints and scheduler fallback if a watcher stays unhealthy
- keep durable POP3 UIDL checkpoints so scheduled polling can resume from newer POP mail instead of always re-reading only the latest tail window
InboxBridge is a good fit if you:
- want a self-hosted alternative to mailbox forwarding rules
- want to import mail from older or secondary accounts into one main mailbox
- need one deployment that can serve one person or several users
- are comfortable running Docker-based applications, even if you are not a developer
Source mailboxes:
- IMAP with password/app password
- POP3 with password/app password
- Microsoft OAuth2 for Outlook / Hotmail / Live source accounts
- Google OAuth for supported Google-based source flows
Destination mailboxes:
- Gmail through the Gmail API
- Outlook.com / Hotmail / Live through IMAP APPEND with Microsoft OAuth2
- Yahoo Mail through IMAP APPEND
- Proton Mail Bridge through IMAP APPEND
- Generic IMAP APPEND destinations
InboxBridge includes:
- a Quarkus backend
- a React admin UI
- PostgreSQL for durable storage
- Docker Compose services for the backend, frontend, database, and local TLS certificate bootstrap
By default, the local Docker setup serves the app over HTTPS with generated self-signed certificates.
- Unified source account list in the UI, including read-only
.envaccounts and user-managed accounts - Per-user destination mailbox configuration
- Import deduplication in PostgreSQL
- WebAuthn passkey support for sign-in
- User sessions with browser/device hints, Geo-IP, and optional browser-reported device location
- Per-user notification history that survives refreshes and sign-in cycles
- Optional post-poll actions for IMAP sources such as mark as read, mark as forwarded, delete, or move to folder
- Per-source IMAP fetch mode: scheduled polling or real-time IMAP IDLE across one or more configured folders
- Optional per-folder Gmail label mappings such as
INBOX=Imported/Inbox;Junk=SPAM - Two-tier admin configuration backups: redacted review snapshots and public-key-encrypted secret exports
- Live polling over authenticated SSE with bounded parallel workers
- A mobile-friendly
/remotepage for quick poll control without opening the full workspace
InboxBridge currently does not:
- encrypt secrets that you place directly in
.env - support every provider-specific OAuth flow
- include production-grade metrics, circuit breakers, or external secret-vault integration
If your goal is simply “read one source mailbox and import it into Gmail,” use this path first:
- Copy
.env.exampleto.env, generateSECURITY_TOKEN_ENCRYPTION_KEY, and start Docker Compose. - Open
https://localhost:3000and sign in asadmin/nimda. - Change the bootstrap password.
- Create a Google Cloud OAuth web client using the direct checklist in Google Cloud Setup For Gmail API.
- Paste the Google client ID and secret into
Administration -> OAuth Apps. - Open
My Destination Mailbox, connect Gmail, and complete Google consent. - Open
My Source Email Accounts, add your IMAP source, choose folders, and optionally add Gmail labels or per-folder label mappings. - Run a poll and confirm the imported mail appears in Gmail.
That route keeps .env small and stores UI-managed mailbox secrets encrypted.
If you prefer a config-file-only deployment, see
Config-file-only source setup.
Copy the example configuration file:
cp .env.example .envThe example file has the minimum local bootstrap values uncommented, so for a first run you usually only need to generate and fill the encryption key.
Generate an encryption key:
openssl rand -base64 32Put that generated value into:
SECURITY_TOKEN_ENCRYPTION_KEY=<base64-32-byte-key>For a normal first run, these minimum values are already present in
.env.example:
JDBC_URL=jdbc:postgresql://postgres:5432/inboxbridge
JDBC_USERNAME=inboxbridge
JDBC_PASSWORD=inboxbridge
PUBLIC_HOSTNAME=localhost
PUBLIC_PORT=3000
SECURITY_TOKEN_ENCRYPTION_KEY=<base64-32-byte-key>
SECURITY_TOKEN_ENCRYPTION_KEY_ID=v1InboxBridge now derives the browser-facing HTTPS URL as
https://${PUBLIC_HOSTNAME}:${PUBLIC_PORT} by default. If you need a custom
scheme or a more unusual public URL shape, you can still override it with
PUBLIC_BASE_URL.
docker compose up --buildServices:
- Admin UI:
https://localhost:3000 - Remote control page:
https://localhost:3000/remote - Backend HTTPS:
https://localhost:8443 - Backend and PostgreSQL stay on the internal Docker network and are not published to the host by default
The first startup generates certificates in ./certs.
Bootstrap credentials:
- username:
admin - password:
nimda
After signing in:
- Change the bootstrap password.
- Open
My Destination Mailboxand connect the mailbox that should receive imported mail. - Open
My Source Email Accountsand add at least one source mailbox. - Run a poll and confirm the messages arrive in the destination mailbox.
You do not need Google or Microsoft OAuth credentials just to start the stack, sign in, and explore the UI.
With only the minimum bootstrap values, you can:
- sign in to the admin UI
- change the bootstrap password
- create users in multi-user mode
- configure destination and source mailboxes in the browser
- review sessions and security settings
- use passkeys if your browser and hostname setup support them
To actually import messages, you need:
- the minimum bootstrap setup above
- one configured destination mailbox
- at least one configured source mailbox
- OAuth app credentials for any OAuth-based provider flow you choose to use
For example, if you want Gmail as the destination provider, you must first create a Google Cloud project and OAuth client for InboxBridge.
These are the settings most operators care about first:
PUBLIC_HOSTNAME: browser-facing hostname used for local TLS SAN generation and derived HTTPS defaultsPUBLIC_PORT: published HTTPS port for the admin UI and remote page; Docker Compose maps this host port to the frontend containerPUBLIC_BASE_URL: optional override for the canonical public HTTPS URL when it should differ fromhttps://${PUBLIC_HOSTNAME}:${PUBLIC_PORT}MULTI_USER_ENABLED: choose single-user or multi-user modeSECRET_PROVIDER_MODE: selects the deployment secret-provider mode;LOCAL,OPENBAO_TRANSIT,VAULT_TRANSIT, and the firstSPLIT_KEYimplementation are availableSECURITY_TOKEN_ENCRYPTION_KEY: required for encrypted UI-managed secrets and browser OAuth exchangeSECURITY_TOKEN_ENCRYPTION_KEY_ID: key label stored with encrypted dataSECURITY_TOKEN_ENCRYPTION_LEGACY_KEYS: optional comma-separatedkeyId:base64Keylist used to keep older encrypted records decryptable during key rotationSECURITY_PASSKEY_*: passkey/WebAuthn settingsMAIL_ACCOUNT_<n>__...: optional env-managed source mailbox definitionsMAIL_ACCOUNT_<n>__FOLDER_LABEL_MAPPINGS: optional IMAP-folder-to-Gmail-label overrides such asINBOX=Imported/Inbox;Junk=SPAMMAIL_ACCOUNT_<n>__SPAM_JUNK_STRATEGYandMAIL_ACCOUNT_<n>__SPAM_JUNK_SOURCE_FOLDERS: optional IMAP spam/junk import controls;IMPORT_AND_ROUTEpreserves messages from every configured source spam or junk folder in GmailSPAMor the destination spam/junk folder. The older singularMAIL_ACCOUNT_<n>__SPAM_JUNK_SOURCE_FOLDERstill works for one-folder configs.GOOGLE_*: shared Google OAuth app settings for Gmail destination flowsMICROSOFT_*: shared Microsoft OAuth app settings for Outlook flowsTLS_FRONTEND_CERT_HOSTNAMESandTLS_BACKEND_CERT_HOSTNAMES: extra hostnames to include in generated local certificatesTLS_POSTGRES_CERT_HOSTNAMES: extra hostnames to include in the generated PostgreSQL TLS certificate
Use these docs when you are ready to connect real providers:
Quick callback defaults:
- Google:
https://localhost:3000/api/google-oauth/callback - Microsoft:
https://localhost:3000/api/microsoft-oauth/callback
If you deploy on another hostname or port, set PUBLIC_HOSTNAME / PUBLIC_PORT
and use a certificate that matches that host. Keep PUBLIC_BASE_URL for cases
where you need to override the derived URL explicitly.
InboxBridge includes a smaller mobile-friendly interface at /remote.
It is useful when you want to:
- trigger a poll from a phone
- check live poll progress quickly
- pause, resume, stop, retry, or reprioritize a live run
- expose a simpler control surface behind your normal HTTPS access controls
The remote page uses its own scoped session model instead of reusing the main admin UI session.
InboxBridge's recommended day-to-day path is the web UI because it can encrypt
stored mailbox secrets. If you prefer a small, auditable deployment file for a
personal instance, you can still define source accounts in .env:
MAIL_ACCOUNT_0__ID=outlook-main
MAIL_ACCOUNT_0__ENABLED=true
MAIL_ACCOUNT_0__PROTOCOL=IMAP
MAIL_ACCOUNT_0__HOST=outlook.office365.com
MAIL_ACCOUNT_0__PORT=993
MAIL_ACCOUNT_0__TLS=true
MAIL_ACCOUNT_0__AUTH_METHOD=PASSWORD
MAIL_ACCOUNT_0__OAUTH_PROVIDER=NONE
MAIL_ACCOUNT_0__USERNAME=person@example.com
MAIL_ACCOUNT_0__PASSWORD=replace-me-app-password
MAIL_ACCOUNT_0__FOLDER=INBOX,Archive
MAIL_ACCOUNT_0__FETCH_MODE=IDLE
MAIL_ACCOUNT_0__CUSTOM_LABEL=Imported/Outlook
MAIL_ACCOUNT_0__FOLDER_LABEL_MAPPINGS=INBOX=Imported/Inbox;Archive=Imported/ArchiveUse .env accounts when you want file-based operation and accept that those
mailbox secrets are operator-managed plaintext configuration. Use UI-managed
accounts when you want encrypted secret storage, connection testing, folder
discovery, live diagnostics, and browser OAuth flows.
Projects such as Turbogmailify optimize for a very small Gmail-only tool configured by a file. That is a good fit when you want the smallest possible audit surface and do not need a web UI, PostgreSQL, multi-user operation, POP3, IMAP destinations, encrypted browser-managed setup, live controls, or operator diagnostics.
InboxBridge is intentionally broader. It is a better fit when you want the same self-hosted “one Gmail inbox, many source accounts” workflow plus:
- Gmail API or IMAP APPEND destinations
- IMAP and POP3 sources
- multi-folder IMAP polling and per-folder IMAP IDLE
- POP3 UIDL checkpoints
- encrypted UI-managed passwords and OAuth refresh tokens
- redacted and encrypted backup exports for operator-controlled recovery planning
- a full admin UI,
/remote, browser extensions, and live troubleshooting
The tradeoff is real: InboxBridge has more moving parts. The win is that those parts support safer setup, more providers, more control surfaces, and better visibility when imports fail.
- UI-managed OAuth tokens and mailbox secrets are intended to be stored encrypted in PostgreSQL.
- InboxBridge now supports stronger deployment-level secret custody through
LOCAL,OPENBAO_TRANSIT,VAULT_TRANSIT, and the firstSPLIT_KEYimplementation, with admin-side migration targets, provider diagnostics, rotation plans, and guided re-encryption underAdministration -> Authentication Security -> Secret management. - Browser-based Google and Microsoft OAuth exchange requires
SECURITY_TOKEN_ENCRYPTION_KEY. .envvalues are operator-managed configuration and are not encrypted by InboxBridge.- Passkeys work best on one stable hostname rather than a mix of unrelated hostnames or raw IP addresses.
If a Gmail account is unlinked locally but Google-side revocation fails, the remaining Google grant can be removed manually from myaccount.google.com under Security -> Manage third-party access -> InboxBridge.
The Docker Compose setup creates a local certificate authority and signs the frontend/backend certificates with it.
If your browser still shows a certificate warning, trust certs/ca.crt on the device that will open InboxBridge. This matters for:
- passkeys / WebAuthn
- secure browser APIs such as geolocation
- PWA installation for
/remote
If you want LAN or Tailscale access, prefer a real hostname covered by the certificate instead of a raw IP address.
InboxBridge is licensed under the Apache License 2.0. See LICENSE.
This project is provided on an AS IS basis, without warranties or conditions of any kind, express or implied, and is used at your own risk.
You are responsible for reviewing, testing, securing, and operating InboxBridge in your own environment, including how it handles credentials, imported mail, OAuth configuration, TLS, backups, and user access.
InboxBridge is not a managed service, legal/compliance product, or security guarantee.
This project was built with the help of AI-assisted tooling.
AI assistance was used to help design, implement, refactor, test, and document parts of the project, with human review and direction by the repository owner. Users and contributors should still review the code, configuration, and behavior carefully before relying on it in any environment.
- Java 25
- Quarkus 3.33.2
- React 19
- Vite 8
- PostgreSQL 16
- Flyway
- Docker Compose
- Main setup: docs/SETUP.md
- OAuth details: docs/OAUTH_SETUP.md
- Architecture: docs/ARCHITECTURE.md
- Local certificate trust: docs/TRUST_LOCAL_CA.md
- Admin UI notes: admin-ui/README.md
- Contributing guide: CONTRIBUTING.md
- Security policy: SECURITY.md
- Code of conduct: CODE_OF_CONDUCT.md
For the latest published InboxBridge version, see the GitHub Releases page.