feat: rename project to InboxConverge with configurable contact details

Agent-Logs-Url: https://github.com/christianlouis/pop_puller_to_gmail/sessions/82f2f361-3513-44e6-991b-db1a19902772

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-26 18:06:46 +00:00
parent eba086fff0
commit 92d67369e9
46 changed files with 226 additions and 192 deletions
+6 -1
View File
@@ -14,7 +14,7 @@ POP3_ACCOUNT_1_USE_SSL=true
# POP3_ACCOUNT_2_USE_SSL=true
# ── Bootstrap Settings (always from env, never from database) ──────
# DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/pop3_forwarder
# DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/inbox_converge
# SECRET_KEY=<generate with: python -c 'import secrets; print(secrets.token_urlsafe(32))'>
# ENCRYPTION_KEY=<generate with: python -c 'import secrets; print(secrets.token_urlsafe(32))'>
@@ -41,5 +41,10 @@ MAX_EMAILS_PER_RUN=50
# Throttling (emails per minute)
THROTTLE_EMAILS_PER_MINUTE=10
# Application identity (used by frontend server components at runtime)
APP_NAME=InboxConverge
APP_URL=https://inboxconverge.com
CONTACT_EMAIL=christian@inboxconverge.com
# Logging
LOG_LEVEL=INFO
+1 -1
View File
@@ -21,7 +21,7 @@ assignees: ''
<!-- What actually happened -->
## Environment
- **Component**: [e.g., Backend API, Worker, Docker, pop3_forwarder.py]
- **Component**: [e.g., Backend API, Worker, Docker, inbox_converge.py]
- **Version**: [e.g., v1.0.0, main branch]
- **Deployment**: [e.g., Docker, Kubernetes, local]
- **OS**: [e.g., Ubuntu 22.04, macOS, Windows]
+4 -4
View File
@@ -77,7 +77,7 @@ jobs:
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: pop3_forwarder_test
POSTGRES_DB: inbox_converge_test
options: >-
--health-cmd pg_isready
--health-interval 10s
@@ -113,7 +113,7 @@ jobs:
- name: Run tests with coverage
env:
DATABASE_URL: postgresql+asyncpg://postgres:postgres@localhost:5432/pop3_forwarder_test
DATABASE_URL: postgresql+asyncpg://postgres:postgres@localhost:5432/inbox_converge_test
REDIS_URL: redis://localhost:6379/0
SECRET_KEY: test-secret-key-for-ci-cd-at-least-32-chars
ENCRYPTION_KEY: test-encryption-key-for-ci-cd-at-least-32-chars
@@ -173,9 +173,9 @@ jobs:
matrix:
include:
- context: ./backend
image_name: gmail-puller/backend
image_name: inboxconverge/backend
- context: ./frontend
image_name: gmail-puller/frontend
image_name: inboxconverge/frontend
steps:
- name: Checkout repository
+2 -2
View File
@@ -33,7 +33,7 @@ repos:
- id: black
language_version: python3.11
args: [--line-length=100]
files: ^(backend/|pop3_forwarder\.py)
files: ^(backend/|inboxconverge\.py)
# Python linting with Ruff (replaces flake8, isort, etc.)
- repo: https://github.com/astral-sh/ruff-pre-commit
@@ -41,7 +41,7 @@ repos:
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
files: ^(backend/|pop3_forwarder\.py)
files: ^(backend/|inboxconverge\.py)
# Type checking with mypy
- repo: https://github.com/pre-commit/mirrors-mypy
+16 -5
View File
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- **Project renamed to InboxConverge**: All user-visible strings, Docker container names, database defaults, Docker image paths, monitoring job names, Grafana dashboard titles, and documentation updated from the legacy names (`POP3 to Gmail Forwarder`, `InboxRescue`, `gmail-puller`, `pop3_forwarder`, etc.) to **InboxConverge** / `inboxconverge`.
- **Domain updated to `inboxconverge.com`**: All contact and administrative email addresses now default to `@inboxconverge.com` (e.g. `christian@inboxconverge.com`).
- **Configurable contact details**: Two new environment variables make contact information overridable at deployment time:
- `CONTACT_EMAIL` (default: `christian@inboxconverge.com`) — used by the frontend legal pages (Impressum, Datenschutz) and surfaced in the backend `Settings`.
- `APP_URL` (default: `https://inboxconverge.com`) — the canonical public URL of the deployment.
- `NEXT_PUBLIC_APP_NAME` (default: `InboxConverge`) — the application name shown in frontend legal-page titles; readable by Next.js server components at runtime.
- **Legacy script renamed**: `pop3_forwarder.py``inboxconverge.py`; root `Dockerfile` and `Makefile` updated accordingly.
- **Grafana dashboard file renamed**: `monitoring/grafana/dashboards/inboxrescue.json``inboxconverge.json`.
- **Note on encryption salt**: The internal PBKDF2 salt `b"pop3_forwarder_0"` in `backend/app/core/security.py` is intentionally **not** renamed — changing it would invalidate all existing encrypted credentials stored in the database.
### Added
- **Prometheus metrics** (`/metrics` endpoint on the FastAPI backend, scraped every 15 s):
- **HTTP layer** — `http_requests_total` (counter, labelled `method`/`endpoint`/`status_code`) and `http_request_duration_seconds` (histogram). Path segments that are numeric IDs are normalised to `{id}` to avoid label-set explosion.
@@ -17,14 +28,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **All metrics** defined as module-level singletons in `backend/app/core/metrics.py` (imported by HTTP middleware, task workers, GmailService, and auth endpoints).
- **Prometheus service** added to `docker-compose.new.yml` (port 9090, 30-day retention, config from `monitoring/prometheus.yml`).
- **Grafana service** added to `docker-compose.new.yml` (port 3001, auto-provisioned datasource + pre-built dashboard). Default credentials: `admin` / `admin`.
- **Pre-built Grafana dashboard** (`monitoring/grafana/dashboards/inboxrescue.json`) with five sections: Mail Processing, Gmail API, Authentication & OAuth, HTTP API, and Celery Workers. Dashboard auto-refreshes every 30 s.
- **Pre-built Grafana dashboard** (`monitoring/grafana/dashboards/inboxconverge.json`) with five sections: Mail Processing, Gmail API, Authentication & OAuth, HTTP API, and Celery Workers. Dashboard auto-refreshes every 30 s.
- **Admin interface**: Superusers now have access to a dedicated Admin section in the sidebar with three pages:
- **Admin Overview** (`/admin`): System-wide stats (total users, mail accounts, processing runs).
- **Manage Users** (`/admin/users`): Table of all registered users with their subscription tier, status, mail account count, and last login. Admins can edit any user's name, email, plan, active status, and promote/demote admin (superuser) privileges. Users can be deleted (with confirmation).
- **Manage Plans** (`/admin/plans`): Full CRUD for subscription plans—create, edit, and delete plans with fields for tier, name, pricing, max mailboxes, max emails/day, check interval, and support level.
- **Auto-promotion of admin email**: When the user whose email matches the `ADMIN_EMAIL` environment variable logs in or registers (via email/password or Google OAuth), they are automatically promoted to superuser. Default value is `christianlouis@gmail.com` (configurable via the `ADMIN_EMAIL` env var).
- **Auto-promotion of admin email**: When the user whose email matches the `ADMIN_EMAIL` environment variable logs in or registers (via email/password or Google OAuth), they are automatically promoted to superuser. Default value is `christian@inboxconverge.com` (configurable via the `ADMIN_EMAIL` env var).
- **`is_superuser` field in API responses**: `GET /users/me` and all admin user endpoints now include `is_superuser` so the frontend can conditionally show admin UI.
- **New admin API endpoints** (all require superuser role):
- `GET /admin/users` List all users with mail account counts.
@@ -39,7 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **`DEFAULT_USER_TIER` env var**: Controls the subscription tier assigned to every new user on registration. Defaults to `free`. Set to `enterprise` (or any other tier) for B2B / Google Workspace installations where all employees should start on a zero-rate plan.
- **`ALLOWED_DOMAINS` env var**: Comma-separated list of permitted email domains (e.g. `company.com,subsidiary.com`). When set, only addresses from those domains may register or log in. Superusers always bypass this check. Empty (default) = no restriction (normal B2C mode).
- **Dynamic pricing section on landing page**: The home page now fetches `GET /subscriptions/plans` and renders a pricing section only when paid plans exist. In enterprise / all-zero-rate deployments the pricing section is silently hidden — the page just shows features and a "Get started free" CTA.
- **B2C copy and branding**: App renamed to **InboxRescue** throughout (was "POP3 Forwarder SaaS"). Landing page hero, feature cards, how-it-works, and footer rewritten in a personal, consumer-friendly tone. Pricing updated to €0.99 / €1.99 / €2.99 per month for Good / Better / Best plans.
- **B2C copy and branding**: App renamed to **InboxConverge** throughout (was "InboxConverge"). Landing page hero, feature cards, how-it-works, and footer rewritten in a personal, consumer-friendly tone. Pricing updated to €0.99 / €1.99 / €2.99 per month for Good / Better / Best plans.
### Fixed
- Test email sender name corrected from "Christian Loris" to "Christian Krakau-Louis".
@@ -52,7 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed `TypeError: can't subtract offset-naive and offset-aware datetimes` in `process_mail_account` task when computing `duration_seconds`. After a database refresh, `started_at` may be returned as a naive datetime; it is now normalized to UTC before subtraction.
- **Admin user not seeing admin dashboard**: Added startup auto-promotion in `main.py` lifespan handler — on every application start, if the user matching `ADMIN_EMAIL` exists in the database but does not yet have `is_superuser=True`, they are promoted immediately. This fixes accounts created before the auto-promotion-on-login code was deployed (e.g. `christianlouis@gmail.com` was logged in but saw no admin section).
- **Admin user not seeing admin dashboard**: Added startup auto-promotion in `main.py` lifespan handler — on every application start, if the user matching `ADMIN_EMAIL` exists in the database but does not yet have `is_superuser=True`, they are promoted immediately. This fixes accounts created before the auto-promotion-on-login code was deployed (e.g. `christian@inboxconverge.com` was logged in but saw no admin section).
- **Blank page on direct navigation to `/admin`, `/admin/users`, `/admin/plans`**: All three admin pages had `if (!user?.is_superuser) return null` before the `<AuthGuard>` was ever rendered. On a direct page load or refresh the Zustand store initialises with `user = null`, so the guard fired immediately and returned an empty render — `AuthGuard` was never mounted, its `checkAuth` effect never ran, and the user data was never fetched. Fixed by removing the early return and moving the superuser guard inside the `<AuthGuard>/<DashboardLayout>` tree, so authentication always runs first.
### Security
@@ -212,7 +223,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.1.0] - 2025-12-15 (Legacy Version)
### Added
- Initial release of single-user pop3_forwarder.py script
- Initial release of single-user inbox_converge.py script
- Docker support with docker-compose
- Multiple POP3 account support
- Gmail forwarding via SMTP
+5 -5
View File
@@ -1,4 +1,4 @@
# Contributing to POP3 to Gmail Forwarder
# Contributing to InboxConverge
Thank you for your interest in contributing! This document provides guidelines for contributing to the project.
@@ -10,7 +10,7 @@ Be respectful and inclusive. We welcome contributions from everyone.
### Reporting Bugs
1. Check if the bug has already been reported in [Issues](https://github.com/christianlouis/pop_puller_to_gmail/issues)
1. Check if the bug has already been reported in [Issues](https://github.com/christianlouis/inboxconverge/issues)
2. If not, create a new issue with:
- Clear title and description
- Steps to reproduce
@@ -77,8 +77,8 @@ Be respectful and inclusive. We welcome contributions from everyone.
```bash
# Clone your fork
git clone https://github.com/YOUR-USERNAME/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/YOUR-USERNAME/inboxconverge.git
cd inboxconverge
# Install all development dependencies
make install-dev
@@ -88,7 +88,7 @@ cp .env.example .env
# Edit .env with test credentials
# Run the legacy forwarder script directly
python pop3_forwarder.py
python inbox_converge.py
# Or start the SaaS backend in dev mode
make run-dev
+5 -5
View File
@@ -8,13 +8,13 @@ COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY pop3_forwarder.py .
COPY inboxconverge.py .
# Create non-root user for security
RUN useradd -m -u 1000 forwarder && \
chown -R forwarder:forwarder /app
RUN useradd -m -u 1000 inboxconverge && \
chown -R inboxconverge:inboxconverge /app
USER forwarder
USER inboxconverge
# Run the application
CMD ["python", "-u", "pop3_forwarder.py"]
CMD ["python", "-u", "inboxconverge.py"]
+3 -3
View File
@@ -120,12 +120,12 @@ run-beat: ## Run Celery beat scheduler
run-flower: ## Run Flower (Celery monitoring)
cd backend && celery -A app.core.celery_app flower --port=5555
run-legacy: ## Run legacy pop3_forwarder script
python pop3_forwarder.py
run-legacy: ## Run legacy inboxconverge script
python inboxconverge.py
# Database Shell
shell: ## Open database shell
docker-compose exec db psql -U postgres -d pop3_forwarder
docker-compose exec db psql -U postgres -d inbox_converge
shell-python: ## Open Python shell with app context
cd backend && python -c "from app.core.database import SessionLocal; db = SessionLocal(); print('Database session available as db')"
+11 -11
View File
@@ -1,9 +1,9 @@
# POP3 to Gmail Forwarder
# InboxConverge
[![CI Tests](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/test.yml/badge.svg)](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/test.yml)
[![Lint](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/lint.yml/badge.svg)](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/lint.yml)
[![Security Scan](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/security.yml/badge.svg)](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/security.yml)
[![Docker Build](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/docker-build.yml/badge.svg)](https://github.com/christianlouis/pop_puller_to_gmail/actions/workflows/docker-build.yml)
[![CI Tests](https://github.com/christianlouis/inboxconverge/actions/workflows/test.yml/badge.svg)](https://github.com/christianlouis/inboxconverge/actions/workflows/test.yml)
[![Lint](https://github.com/christianlouis/inboxconverge/actions/workflows/lint.yml/badge.svg)](https://github.com/christianlouis/inboxconverge/actions/workflows/lint.yml)
[![Security Scan](https://github.com/christianlouis/inboxconverge/actions/workflows/security.yml/badge.svg)](https://github.com/christianlouis/inboxconverge/actions/workflows/security.yml)
[![Docker Build](https://github.com/christianlouis/inboxconverge/actions/workflows/docker-build.yml/badge.svg)](https://github.com/christianlouis/inboxconverge/actions/workflows/docker-build.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](https://www.docker.com/)
@@ -31,8 +31,8 @@ The repository also includes a multi-tenant SaaS backend built with FastAPI, Pos
```bash
# Pull and configure
curl -O https://raw.githubusercontent.com/christianlouis/pop_puller_to_gmail/main/docker-compose.yml
curl -o .env https://raw.githubusercontent.com/christianlouis/pop_puller_to_gmail/main/.env.example
curl -O https://raw.githubusercontent.com/christianlouis/inboxconverge/main/docker-compose.yml
curl -o .env https://raw.githubusercontent.com/christianlouis/inboxconverge/main/.env.example
# Edit .env with your credentials
nano .env
@@ -44,8 +44,8 @@ docker-compose up -d
### Building from Source
```bash
git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
cp .env.example .env # then edit .env
docker-compose up -d
```
@@ -257,5 +257,5 @@ This project is licensed under the MIT License — see [LICENSE](LICENSE) for de
## Support
- [Issue Tracker](https://github.com/christianlouis/pop_puller_to_gmail/issues)
- [Discussions](https://github.com/christianlouis/pop_puller_to_gmail/discussions)
- [Issue Tracker](https://github.com/christianlouis/inboxconverge/issues)
- [Discussions](https://github.com/christianlouis/inboxconverge/discussions)
+1 -1
View File
@@ -15,7 +15,7 @@
If you discover a security vulnerability, please report it responsibly:
1. **Email**: Send details to the repository maintainer via the email listed on the [GitHub profile](https://github.com/christianlouis).
2. **GitHub Private Vulnerability Reporting**: Use [GitHub's security advisory feature](https://github.com/christianlouis/pop_puller_to_gmail/security/advisories/new) to report privately.
2. **GitHub Private Vulnerability Reporting**: Use [GitHub's security advisory feature](https://github.com/christianlouis/inboxconverge/security/advisories/new) to report privately.
### What to Include
+5 -3
View File
@@ -1,5 +1,5 @@
# Database Configuration
DATABASE_URL=postgresql+asyncpg://postgres:password@localhost:5432/pop3_forwarder
DATABASE_URL=postgresql+asyncpg://postgres:password@localhost:5432/inbox_converge
# Security
SECRET_KEY=change-this-to-a-secure-random-secret-key-minimum-32-characters
@@ -41,12 +41,14 @@ CELERY_RESULT_BACKEND=redis://localhost:6379/0
LOG_LEVEL=INFO
# Admin Account (created on first startup)
ADMIN_EMAIL=admin@example.com
ADMIN_EMAIL=christian@inboxconverge.com
ADMIN_PASSWORD=change-this-secure-password
# Application
APP_NAME=POP3 Forwarder SaaS
APP_NAME=InboxConverge
APP_VERSION=2.0.0
APP_URL=https://inboxconverge.com
CONTACT_EMAIL=christian@inboxconverge.com
DEBUG=false
HOST=0.0.0.0
PORT=8000
+5 -3
View File
@@ -27,8 +27,10 @@ class Settings(BaseSettings):
)
# Application
APP_NAME: str = "InboxRescue"
APP_NAME: str = "InboxConverge"
APP_VERSION: str = "2.0.0"
APP_URL: str = "https://inboxconverge.com"
CONTACT_EMAIL: str = "christian@inboxconverge.com"
DEBUG: bool = False
API_V1_PREFIX: str = "/api/v1"
@@ -38,7 +40,7 @@ class Settings(BaseSettings):
# Database
DATABASE_URL: str = (
"postgresql+asyncpg://user:password@localhost:5432/pop3_forwarder"
"postgresql+asyncpg://user:password@localhost:5432/inbox_converge"
)
DATABASE_POOL_SIZE: int = 20
DATABASE_MAX_OVERFLOW: int = 10
@@ -94,7 +96,7 @@ class Settings(BaseSettings):
LOG_LEVEL: str = "INFO"
# Admin
ADMIN_EMAIL: Optional[str] = "christianlouis@gmail.com"
ADMIN_EMAIL: Optional[str] = "christian@inboxconverge.com"
ADMIN_PASSWORD: Optional[str] = None
# User defaults & access control
+1 -1
View File
@@ -1,5 +1,5 @@
"""
Prometheus metrics definitions for InboxRescue.
Prometheus metrics definitions for InboxConverge.
All application metrics are defined here as module-level singletons so that
every subsystem (HTTP layer, Celery workers, Gmail service, auth) imports
+1 -1
View File
@@ -148,7 +148,7 @@ def create_application() -> FastAPI:
async def root():
"""Root endpoint"""
return {
"message": "InboxRescue API",
"message": "InboxConverge API",
"version": settings.APP_VERSION,
"docs": "/api/docs",
}
+1 -1
View File
@@ -12,7 +12,7 @@ logger = logging.getLogger(__name__)
# Create Celery app
celery_app = Celery(
"pop3_forwarder",
"inboxconverge",
broker=settings.CELERY_BROKER_URL,
backend=settings.CELERY_RESULT_BACKEND,
include=["app.workers.tasks"],
+1 -1
View File
@@ -16,7 +16,7 @@ from app.core.security import get_password_hash, create_access_token
# Test database URL (use different database for tests)
TEST_DATABASE_URL = settings.DATABASE_URL.replace(
"/pop3_forwarder", "/pop3_forwarder_test"
"/inbox_converge", "/inbox_converge_test"
)
+1 -1
View File
@@ -89,7 +89,7 @@ class TestApplicationFactory:
async def test_app_title(self, app):
"""Test that app has correct title"""
assert app.title == "InboxRescue"
assert app.title == "InboxConverge"
async def test_app_version(self, app):
"""Test that app has a version"""
+12 -9
View File
@@ -4,11 +4,11 @@ services:
# PostgreSQL Database
postgres:
image: postgres:15-alpine
container_name: pop3-postgres
container_name: inboxconverge-postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: pop3_forwarder
POSTGRES_DB: inbox_converge
ports:
- "5432:5432"
volumes:
@@ -22,7 +22,7 @@ services:
# Redis for caching and Celery
redis:
image: redis:7-alpine
container_name: pop3-redis
container_name: inboxconverge-redis
ports:
- "6379:6379"
volumes:
@@ -38,7 +38,7 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pop3-backend
container_name: inboxconverge-backend
ports:
- "8000:8000"
env_file:
@@ -58,7 +58,7 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pop3-celery-worker
container_name: inboxconverge-celery-worker
env_file:
- ./backend/.env
depends_on:
@@ -75,7 +75,7 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pop3-celery-beat
container_name: inboxconverge-celery-beat
env_file:
- ./backend/.env
depends_on:
@@ -92,11 +92,14 @@ services:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: pop3-frontend
container_name: inboxconverge-frontend
ports:
- "3000:3000"
environment:
- BACKEND_URL=http://backend:8000
- CONTACT_EMAIL=christian@inboxconverge.com
- APP_URL=https://inboxconverge.com
- APP_NAME=InboxConverge
depends_on:
- backend
restart: unless-stopped
@@ -104,7 +107,7 @@ services:
# Prometheus metrics collection
prometheus:
image: prom/prometheus:v2.51.2
container_name: pop3-prometheus
container_name: inboxconverge-prometheus
ports:
- "9090:9090"
volumes:
@@ -122,7 +125,7 @@ services:
# Grafana dashboards
grafana:
image: grafana/grafana:10.4.3
container_name: pop3-grafana
container_name: inboxconverge-grafana
ports:
- "3001:3000"
environment:
+3 -3
View File
@@ -1,13 +1,13 @@
version: '3.8'
services:
pop3-forwarder:
inboxconverge:
# Option 1: Build from source (default)
build: .
# Option 2: Use pre-built image from GitHub Container Registry
# Uncomment the line below and comment out 'build: .' to use pre-built image
# image: ghcr.io/christianlouis/pop_puller_to_gmail:latest
container_name: pop3-gmail-forwarder
# image: ghcr.io/christianlouis/inboxconverge:latest
container_name: inboxconverge
restart: unless-stopped
env_file:
- .env
+8 -8
View File
@@ -1,4 +1,4 @@
# POP3 Forwarder SaaS - Multi-Tenant Architecture
# InboxConverge - Multi-Tenant Architecture
This document describes the new multi-tenant SaaS architecture for the POP3/IMAP email forwarder.
@@ -20,7 +20,7 @@ The project has been transformed from a single-user Docker application into a fu
## 📁 Project Structure
```
pop_puller_to_gmail/
inboxconverge/
├── backend/ # FastAPI backend application
│ ├── app/
│ │ ├── api/ # API endpoints
@@ -50,7 +50,7 @@ pop_puller_to_gmail/
│ └── .env.example # Environment template
├── frontend/ # React/Next.js frontend (to be implemented)
├── docker-compose.new.yml # Docker Compose for all services
├── pop3_forwarder.py # Legacy single-user script
├── inbox_converge.py # Legacy single-user script
└── README.md # This file
```
@@ -68,8 +68,8 @@ pop_puller_to_gmail/
1. **Clone and navigate to repository**
```bash
git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
```
2. **Configure backend environment**
@@ -329,7 +329,7 @@ Coming soon: Kubernetes manifests and Helm charts.
## 🔄 Migration from Legacy Version
To migrate from the single-user `pop3_forwarder.py`:
To migrate from the single-user `inbox_converge.py`:
1. **Export existing configuration** from `.env` file
2. **Create user account** via API or admin panel
@@ -404,8 +404,8 @@ MIT License - See [LICENSE](../LICENSE) file
## 🆘 Support
- **Issues**: https://github.com/christianlouis/pop_puller_to_gmail/issues
- **Discussions**: https://github.com/christianlouis/pop_puller_to_gmail/discussions
- **Issues**: https://github.com/christianlouis/inboxconverge/issues
- **Discussions**: https://github.com/christianlouis/inboxconverge/discussions
- **Email**: support@example.com
## 🙏 Acknowledgments
+1 -1
View File
@@ -1,6 +1,6 @@
# Coding Patterns and Best Practices
This document outlines the coding patterns, conventions, and best practices for the POP3 to Gmail Forwarder project.
This document outlines the coding patterns, conventions, and best practices for the InboxConverge project.
## Table of Contents
- [General Principles](#general-principles)
+7 -7
View File
@@ -1,6 +1,6 @@
# Deployment Checklist and Next Steps
This document provides a checklist for deploying the multi-tenant POP3 Forwarder with web interface.
This document provides a checklist for deploying the multi-tenant InboxConverge with web interface.
## 🚀 Pre-Deployment Checklist
@@ -48,7 +48,7 @@ This document provides a checklist for deploying the multi-tenant POP3 Forwarder
#### Database
- [ ] PostgreSQL 15+ instance running
- [ ] Database created: `pop3_forwarder`
- [ ] Database created: `inbox_converge`
- [ ] Connection details configured in backend/.env
- [ ] Backups configured
@@ -89,8 +89,8 @@ sudo certbot --nginx -d yourdomain.com -d api.yourdomain.com
```bash
# On production server
cd /opt
sudo git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
sudo git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
```
### Step 2: Configure Environment
@@ -195,9 +195,9 @@ curl -X POST https://api.yourdomain.com/api/v1/auth/register \
# Automated daily backup script
cat > /usr/local/bin/backup-pop3-db.sh << 'EOF'
#!/bin/bash
BACKUP_DIR=/var/backups/pop3_forwarder
BACKUP_DIR=/var/backups/inbox_converge
DATE=$(date +%Y%m%d_%H%M%S)
docker exec pop3-postgres pg_dump -U postgres pop3_forwarder | gzip > $BACKUP_DIR/backup_$DATE.sql.gz
docker exec inboxconverge-postgres pg_dump -U postgres inbox_converge | gzip > $BACKUP_DIR/backup_$DATE.sql.gz
find $BACKUP_DIR -type f -mtime +30 -delete
EOF
@@ -394,4 +394,4 @@ Use this checklist after deployment:
## 🎉 Congratulations!
If all checkboxes above are complete, your multi-tenant POP3 Forwarder with web interface is successfully deployed and ready to serve users!
If all checkboxes above are complete, your multi-tenant InboxConverge with web interface is successfully deployed and ready to serve users!
+50 -50
View File
@@ -1,6 +1,6 @@
# Deployment Guide
This guide walks you through deploying **POP3 to Gmail Forwarder** from scratch — whether you just want a single container pulling emails, a full multi-service SaaS stack with Docker Compose, or a production-grade Kubernetes setup.
This guide walks you through deploying **InboxConverge** from scratch — whether you just want a single container pulling emails, a full multi-service SaaS stack with Docker Compose, or a production-grade Kubernetes setup.
---
@@ -52,13 +52,13 @@ You will also need:
## Option 1 — Legacy Single-Container Deployment
The legacy mode runs a single Python script (`pop3_forwarder.py`) that polls POP3 mailboxes and forwards email via SMTP. No database, no web UI — just a container and an `.env` file.
The legacy mode runs a single Python script (`inbox_converge.py`) that polls POP3 mailboxes and forwards email via SMTP. No database, no web UI — just a container and an `.env` file.
### 1. Create the environment file
```bash
git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
cp .env.example .env
```
@@ -97,12 +97,12 @@ The repository ships `docker-compose.yml` for this mode. Here is the content for
version: "3.8"
services:
pop3-forwarder:
inbox-converge:
# Build from source
build: .
# Or use the pre-built image:
# image: ghcr.io/christianlouis/pop_puller_to_gmail:latest
container_name: pop3-gmail-forwarder
# image: ghcr.io/christianlouis/inboxconverge:latest
container_name: inboxconverge
restart: unless-stopped
env_file:
- .env
@@ -149,7 +149,7 @@ Save both values — you will need them below.
### 2. Create the backend environment file
```bash
cd pop_puller_to_gmail
cd inboxconverge
cp backend/.env.example backend/.env
```
@@ -157,7 +157,7 @@ Edit `backend/.env`:
```ini
# ── Database ──────────────────────────────────────────────
DATABASE_URL=postgresql+asyncpg://postgres:change-me@postgres:5432/pop3_forwarder
DATABASE_URL=postgresql+asyncpg://postgres:change-me@postgres:5432/inbox_converge
# ── Security (paste the values you generated above) ──────
SECRET_KEY=<your-64-char-hex-secret>
@@ -198,12 +198,12 @@ services:
# ── PostgreSQL ───────────────────────────────────────────
postgres:
image: postgres:15-alpine
container_name: pop3-postgres
container_name: inboxconverge-postgres
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: change-me # must match DATABASE_URL
POSTGRES_DB: pop3_forwarder
POSTGRES_DB: inbox_converge
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
@@ -219,7 +219,7 @@ services:
# ── Redis ────────────────────────────────────────────────
redis:
image: redis:7-alpine
container_name: pop3-redis
container_name: inboxconverge-redis
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
@@ -235,7 +235,7 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pop3-backend
container_name: inboxconverge-backend
restart: unless-stopped
ports:
- "8000:8000"
@@ -260,7 +260,7 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pop3-celery-worker
container_name: inboxconverge-celery-worker
restart: unless-stopped
env_file:
- ./backend/.env
@@ -278,7 +278,7 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pop3-celery-beat
container_name: inboxconverge-celery-beat
restart: unless-stopped
env_file:
- ./backend/.env
@@ -296,7 +296,7 @@ services:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: pop3-frontend
container_name: inboxconverge-frontend
restart: unless-stopped
ports:
- "3000:3000"
@@ -358,7 +358,7 @@ Below is a set of example Kubernetes manifests to get you started. Adapt namespa
apiVersion: v1
kind: Namespace
metadata:
name: pop3-forwarder
name: inbox-converge
```
### Secrets
@@ -369,13 +369,13 @@ Store sensitive values in a Kubernetes Secret. In production, consider using an
apiVersion: v1
kind: Secret
metadata:
name: pop3-forwarder-secrets
namespace: pop3-forwarder
name: inbox-converge-secrets
namespace: inbox-converge
type: Opaque
stringData:
SECRET_KEY: "<your-64-char-hex-secret>"
ENCRYPTION_KEY: "<your-64-char-hex-encryption-key>"
DATABASE_URL: "postgresql+asyncpg://postgres:change-me@postgres:5432/pop3_forwarder"
DATABASE_URL: "postgresql+asyncpg://postgres:change-me@postgres:5432/inbox_converge"
REDIS_URL: "redis://redis:6379/0"
CELERY_BROKER_URL: "redis://redis:6379/0"
CELERY_RESULT_BACKEND: "redis://redis:6379/0"
@@ -396,7 +396,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: pop3-forwarder
namespace: inbox-converge
spec:
replicas: 1
selector:
@@ -416,11 +416,11 @@ spec:
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_DB
value: pop3_forwarder
value: inbox_converge
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: pop3-forwarder-secrets
name: inbox-converge-secrets
key: POSTGRES_PASSWORD
volumeMounts:
- name: pgdata
@@ -439,7 +439,7 @@ apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: pop3-forwarder
namespace: inbox-converge
spec:
selector:
app: postgres
@@ -451,7 +451,7 @@ apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: pop3-forwarder
namespace: inbox-converge
spec:
accessModes: [ReadWriteOnce]
resources:
@@ -466,7 +466,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: pop3-forwarder
namespace: inbox-converge
spec:
replicas: 1
selector:
@@ -493,7 +493,7 @@ apiVersion: v1
kind: Service
metadata:
name: redis
namespace: pop3-forwarder
namespace: inbox-converge
spec:
selector:
app: redis
@@ -509,7 +509,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: pop3-forwarder
namespace: inbox-converge
spec:
replicas: 2
selector:
@@ -522,22 +522,22 @@ spec:
spec:
initContainers:
- name: run-migrations
image: ghcr.io/christianlouis/pop_puller_to_gmail-backend:latest
image: ghcr.io/christianlouis/inboxconverge-backend:latest
command: ["alembic", "upgrade", "head"]
envFrom:
- secretRef:
name: pop3-forwarder-secrets
name: inbox-converge-secrets
env:
- name: DEBUG
value: "false"
containers:
- name: backend
image: ghcr.io/christianlouis/pop_puller_to_gmail-backend:latest
image: ghcr.io/christianlouis/inboxconverge-backend:latest
ports:
- containerPort: 8000
envFrom:
- secretRef:
name: pop3-forwarder-secrets
name: inbox-converge-secrets
env:
- name: HOST
value: "0.0.0.0"
@@ -567,7 +567,7 @@ apiVersion: v1
kind: Service
metadata:
name: backend
namespace: pop3-forwarder
namespace: inbox-converge
spec:
selector:
app: backend
@@ -583,7 +583,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: celery-worker
namespace: pop3-forwarder
namespace: inbox-converge
spec:
replicas: 2
selector:
@@ -596,7 +596,7 @@ spec:
spec:
containers:
- name: worker
image: ghcr.io/christianlouis/pop_puller_to_gmail-backend:latest
image: ghcr.io/christianlouis/inboxconverge-backend:latest
command:
- celery
- -A
@@ -606,7 +606,7 @@ spec:
- --concurrency=2
envFrom:
- secretRef:
name: pop3-forwarder-secrets
name: inbox-converge-secrets
resources:
requests:
cpu: 250m
@@ -625,7 +625,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: celery-beat
namespace: pop3-forwarder
namespace: inbox-converge
spec:
replicas: 1 # Must be exactly 1
strategy:
@@ -640,7 +640,7 @@ spec:
spec:
containers:
- name: beat
image: ghcr.io/christianlouis/pop_puller_to_gmail-backend:latest
image: ghcr.io/christianlouis/inboxconverge-backend:latest
command:
- celery
- -A
@@ -649,7 +649,7 @@ spec:
- --loglevel=info
envFrom:
- secretRef:
name: pop3-forwarder-secrets
name: inbox-converge-secrets
resources:
requests:
cpu: 100m
@@ -666,7 +666,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: pop3-forwarder
namespace: inbox-converge
spec:
replicas: 2
selector:
@@ -679,7 +679,7 @@ spec:
spec:
containers:
- name: frontend
image: ghcr.io/christianlouis/pop_puller_to_gmail-frontend:latest
image: ghcr.io/christianlouis/inboxconverge-frontend:latest
ports:
- containerPort: 3000
env:
@@ -697,7 +697,7 @@ apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: pop3-forwarder
namespace: inbox-converge
spec:
selector:
app: frontend
@@ -714,8 +714,8 @@ The Ingress below assumes you have an Ingress controller installed (e.g., [ingre
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pop3-forwarder-ingress
namespace: pop3-forwarder
name: inbox-converge-ingress
namespace: inbox-converge
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
@@ -725,7 +725,7 @@ spec:
- hosts:
- your-domain.com
- api.your-domain.com
secretName: pop3-forwarder-tls
secretName: inbox-converge-tls
rules:
- host: your-domain.com
http:
@@ -754,7 +754,7 @@ spec:
If you manage many environments (staging, production, etc.) consider wrapping the manifests above into a Helm chart:
```text
helm/pop3-forwarder/
helm/inbox-converge/
├── Chart.yaml
├── values.yaml # defaults for all environments
├── values-staging.yaml
@@ -782,8 +782,8 @@ replicaCount:
frontend: 2
image:
backend: ghcr.io/christianlouis/pop_puller_to_gmail-backend
frontend: ghcr.io/christianlouis/pop_puller_to_gmail-frontend
backend: ghcr.io/christianlouis/inboxconverge-backend
frontend: ghcr.io/christianlouis/inboxconverge-frontend
tag: latest
ingress:
@@ -862,7 +862,7 @@ In production you should place a reverse proxy in front of the backend and front
### Example: nginx
```nginx
# /etc/nginx/sites-available/pop3-forwarder
# /etc/nginx/sites-available/inbox-converge
# Frontend
server {
@@ -969,7 +969,7 @@ If you prefer Traefik, add it as a service in your Compose file and use labels o
## Upgrading
```bash
cd pop_puller_to_gmail
cd inboxconverge
# Pull latest code
git pull origin main
+1 -1
View File
@@ -1,6 +1,6 @@
# Error Codes and Messages
This document catalogs all error codes used in the POP3 to Gmail Forwarder application.
This document catalogs all error codes used in the InboxConverge application.
## Error Code Format
+3 -3
View File
@@ -2,7 +2,7 @@
## 🎯 Mission Accomplished
This document summarizes the completion of the web interface and multitenancy features for the POP3 to Gmail Forwarder project.
This document summarizes the completion of the web interface and multitenancy features for the InboxConverge project.
## 📦 What Was Delivered
@@ -320,7 +320,7 @@ These are potential future improvements outside the current task:
### What Was Accomplished
**Complete implementation of web interface and multitenancy features**
The POP3 to Gmail Forwarder now has:
The InboxConverge now has:
- A modern, responsive web interface
- Complete user authentication system
- Full mail account management capabilities
@@ -356,7 +356,7 @@ The implementation is **complete and ready for**:
## 👏 Thank You
This implementation represents a significant milestone in transforming the POP3 Forwarder from a simple script into a production-ready multi-tenant SaaS application. The web interface makes the service accessible to users of all technical levels, while maintaining the robust backend infrastructure.
This implementation represents a significant milestone in transforming the InboxConverge from a simple script into a production-ready multi-tenant SaaS application. The web interface makes the service accessible to users of all technical levels, while maintaining the robust backend infrastructure.
**The multitenancy and web interface implementation is now complete and ready for deployment!** 🎉
+11 -11
View File
@@ -1,6 +1,6 @@
# Implementation Guide
This guide provides step-by-step instructions for setting up and deploying the multi-tenant POP3 Forwarder SaaS application.
This guide provides step-by-step instructions for setting up and deploying the multi-tenant InboxConverge application.
## Table of Contents
@@ -36,8 +36,8 @@ This guide provides step-by-step instructions for setting up and deploying the m
```bash
# Clone repository
git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
# Create backend environment file
cp backend/.env.example backend/.env
@@ -49,7 +49,7 @@ Edit `backend/.env` with your settings:
```bash
# Minimum required for development
DATABASE_URL=postgresql+asyncpg://postgres:password@postgres:5432/pop3_forwarder
DATABASE_URL=postgresql+asyncpg://postgres:password@postgres:5432/inbox_converge
SECRET_KEY=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
GOOGLE_CLIENT_ID=your-client-id
@@ -176,7 +176,7 @@ ADMIN_EMAIL=admin@yourdomain.com
Use nginx or Traefik as reverse proxy:
```nginx
# /etc/nginx/sites-available/pop3-forwarder
# /etc/nginx/sites-available/inbox-converge
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
@@ -202,7 +202,7 @@ cat > /etc/cron.daily/backup-postgres << 'EOF'
#!/bin/bash
BACKUP_DIR=/var/backups/postgres
DATE=$(date +%Y%m%d_%H%M%S)
docker exec pop3-postgres pg_dump -U postgres pop3_forwarder | gzip > $BACKUP_DIR/backup_$DATE.sql.gz
docker exec inboxconverge-postgres pg_dump -U postgres inbox_converge | gzip > $BACKUP_DIR/backup_$DATE.sql.gz
find $BACKUP_DIR -type f -mtime +7 -delete # Keep 7 days
EOF
@@ -348,10 +348,10 @@ docker-compose -f docker-compose.new.yml exec celery-worker celery -A app.worker
```bash
# Check connections
docker exec pop3-postgres psql -U postgres -d pop3_forwarder -c "SELECT count(*) FROM pg_stat_activity;"
docker exec inboxconverge-postgres psql -U postgres -d inbox_converge -c "SELECT count(*) FROM pg_stat_activity;"
# Check table sizes
docker exec pop3-postgres psql -U postgres -d pop3_forwarder -c "
docker exec inboxconverge-postgres psql -U postgres -d inbox_converge -c "
SELECT
schemaname,
tablename,
@@ -376,7 +376,7 @@ docker-compose -f docker-compose.new.yml ps postgres
docker-compose -f docker-compose.new.yml logs postgres
# Test connection
docker exec pop3-postgres psql -U postgres -c "SELECT version();"
docker exec inboxconverge-postgres psql -U postgres -c "SELECT version();"
```
#### Celery Worker Not Processing
@@ -480,8 +480,8 @@ redis:
For additional help:
- **Documentation**: See [ARCHITECTURE.md](ARCHITECTURE.md)
- **Issues**: https://github.com/christianlouis/pop_puller_to_gmail/issues
- **Discussions**: https://github.com/christianlouis/pop_puller_to_gmail/discussions
- **Issues**: https://github.com/christianlouis/inboxconverge/issues
- **Discussions**: https://github.com/christianlouis/inboxconverge/discussions
---
+2 -2
View File
@@ -1,6 +1,6 @@
# Migration Guide: Single-User to Multi-Tenant SaaS
This guide helps you migrate from the legacy single-user `pop3_forwarder.py` script to the new multi-tenant SaaS application.
This guide helps you migrate from the legacy single-user `inbox_converge.py` script to the new multi-tenant SaaS application.
## Overview
@@ -230,7 +230,7 @@ docker-compose -f docker-compose.yml down
# Archive old configuration
mkdir -p archive
mv pop3_forwarder.py archive/
mv inbox_converge.py archive/
mv .env.legacy.backup archive/
mv docker-compose.yml archive/docker-compose.legacy.yml
+10 -10
View File
@@ -1,6 +1,6 @@
# Quick Start Guide
Get your POP3 to Gmail forwarder running in under 10 minutes!
Get your InboxConverge instance running in under 10 minutes!
## Prerequisites
@@ -13,8 +13,8 @@ Get your POP3 to Gmail forwarder running in under 10 minutes!
### 1. Clone the Repository
```bash
git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
```
### 2. Generate Gmail App Password
@@ -23,7 +23,7 @@ cd pop_puller_to_gmail
2. Sign in to your Google Account
3. Select "App passwords" under Security
4. Choose "Mail" and "Other (Custom name)"
5. Enter "POP3 Forwarder" as the name
5. Enter "InboxConverge" as the name
6. Click "Generate"
7. **Copy the 16-character password** (you'll need this in step 3)
@@ -66,10 +66,10 @@ docker-compose logs -f
You should see:
```
pop3-gmail-forwarder | INFO - POP3 to Gmail Forwarder starting...
pop3-gmail-forwarder | INFO - Loaded POP3 account: ...
pop3-gmail-forwarder | INFO - Configuration validated successfully
pop3-gmail-forwarder | INFO - Starting email processing cycle
inboxconverge | INFO - InboxConverge starting...
inboxconverge | INFO - Loaded POP3 account: ...
inboxconverge | INFO - Configuration validated successfully
inboxconverge | INFO - Starting email processing cycle
```
### 6. Test the Forwarder
@@ -192,13 +192,13 @@ Restart after changes: `docker-compose restart`
## Need Help?
- Open an issue: https://github.com/christianlouis/pop_puller_to_gmail/issues
- Open an issue: https://github.com/christianlouis/inboxconverge/issues
- Check existing discussions
- Review troubleshooting section in README.md
## Success! 🎉
Your POP3 to Gmail forwarder is now running. Emails will be automatically forwarded every 5 minutes (or your configured interval).
Your InboxConverge instance is now running. Emails will be automatically forwarded every 5 minutes (or your configured interval).
**Remember**:
- The forwarder deletes emails from POP3 after successful forwarding
+4 -4
View File
@@ -39,8 +39,8 @@ This project has been **completely transformed** from a single-user Docker scrip
```bash
# Clone repository
git clone https://github.com/christianlouis/pop_puller_to_gmail.git
cd pop_puller_to_gmail
git clone https://github.com/christianlouis/inboxconverge.git
cd inboxconverge
# Configure environment
cp backend/.env.example backend/.env
@@ -330,8 +330,8 @@ MIT License - See [LICENSE](../LICENSE) file for details.
## 🆘 Support
- **Documentation**: See docs in repository
- **Issues**: https://github.com/christianlouis/pop_puller_to_gmail/issues
- **Discussions**: https://github.com/christianlouis/pop_puller_to_gmail/discussions
- **Issues**: https://github.com/christianlouis/inboxconverge/issues
- **Discussions**: https://github.com/christianlouis/inboxconverge/discussions
- **Email**: support@example.com (for Enterprise customers)
## 🎉 Acknowledgments
+1 -1
View File
@@ -1,7 +1,7 @@
# Roadmap
## Vision
Create a robust, scalable, and user-friendly POP3 to Gmail forwarding solution that serves as a complete replacement for Gmail's discontinued POP3 import feature.
Create a robust, scalable, and user-friendly InboxConverge email-forwarding solution that serves as a complete replacement for Gmail's discontinued POP3 import feature.
---
+1 -1
View File
@@ -2,7 +2,7 @@
## Overview
Security analysis completed on February 1, 2026 for the Multi-Tenant POP3 Forwarder SaaS application.
Security analysis completed on February 1, 2026 for the Multi-Tenant InboxConverge application.
## CodeQL Security Scan
+1 -1
View File
@@ -25,7 +25,7 @@ This guide will help you test the complete multi-tenant web interface with the b
3. Edit the `.env` file and update the following critical values:
```bash
# Database - should point to Docker service
DATABASE_URL=postgresql+asyncpg://postgres:password@postgres:5432/pop3_forwarder
DATABASE_URL=postgresql+asyncpg://postgres:password@postgres:5432/inbox_converge
# Redis - should point to Docker service
REDIS_URL=redis://redis:6379/0
+7 -1
View File
@@ -2,6 +2,12 @@
Comprehensive task breakdown for repository improvements and production readiness.
## ✅ Recently Completed
- [x] Rename entire project to **InboxConverge**: all user-visible strings, Docker container/image names, DB defaults, monitoring, and docs updated.
- [x] Domain updated to `inboxconverge.com`; contact email defaults to `christian@inboxconverge.com`.
- [x] New configurable env vars: `CONTACT_EMAIL`, `APP_URL`, `NEXT_PUBLIC_APP_NAME`.
## 🔴 Critical - Security (In Progress)
### Completed ✅
@@ -245,7 +251,7 @@ because the API client layer is missing.
- [x] Admin overview page (`/admin`) with system-wide stats
- [x] User management page (`/admin/users`) — list, edit, delete users; assign plans; promote/demote admin
- [x] Plan management page (`/admin/plans`) — full CRUD for subscription plans (mailboxes, emails/day, interval, pricing)
- [x] `ADMIN_EMAIL` env var with default `christianlouis@gmail.com`; admin auto-promoted on login and on every application startup (fixes pre-existing accounts)
- [x] `ADMIN_EMAIL` env var with default `christian@inboxconverge.com`; admin auto-promoted on login and on every application startup (fixes pre-existing accounts)
- [x] `is_superuser` exposed in `/users/me` response
- [x] Admin badge (purple shield) shown in top bar for superusers
- [x] Fix blank page on direct navigation to `/admin*`: moved superuser guard inside `<AuthGuard>` so auth check always runs on fresh load
+2 -2
View File
@@ -1,6 +1,6 @@
# Web Interface Quick Start Guide
The POP3 to Gmail Forwarder now includes a modern web interface built with Next.js, making it easy to manage your email forwarding without API calls.
The InboxConverge now includes a modern web interface built with Next.js, making it easy to manage your email forwarding without API calls.
## 🌐 Accessing the Web Interface
@@ -104,7 +104,7 @@ frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: pop3-frontend
container_name: inboxconverge-frontend
ports:
- "3000:3000"
environment:
+1 -1
View File
@@ -126,7 +126,7 @@ elif version == 'v2':
def get_or_create_user_salt(user_id: int) -> bytes:
# Use deterministic salt based on user_id + global salt
# OR store random salt in database per user
return hashlib.sha256(f'pop3_forwarder_user_{user_id}'.encode()).digest()
return hashlib.sha256(f'inbox_converge_user_{user_id}'.encode()).digest()
```
## Security Best Practices
+1 -1
View File
@@ -64,7 +64,7 @@ async def lifespan(app: FastAPI):
# Shutdown: cleanup
app = FastAPI(
title="POP3 Forwarder API",
title="InboxConverge API",
lifespan=lifespan,
openapi_url="/api/openapi.json",
docs_url="/api/docs",
+5 -3
View File
@@ -1,12 +1,14 @@
import Link from 'next/link';
import type { Metadata } from 'next';
const APP_NAME = process.env.APP_NAME ?? 'InboxConverge';
export const metadata: Metadata = {
title: 'Datenschutz POP3 Forwarder',
title: `Datenschutz ${APP_NAME}`,
};
const LAST_UPDATED = 'March 26, 2026';
const CONTACT_EMAIL = 'christianlouis@gmail.com';
const CONTACT_EMAIL = process.env.CONTACT_EMAIL ?? 'christian@inboxconverge.com';
export default function DatenschutzPage() {
return (
@@ -82,7 +84,7 @@ export default function DatenschutzPage() {
2. Geltungsbereich dieser Datenschutzerklärung
</h2>
<p className="text-gray-700">
Dieser Hinweis gilt für die POP3 Forwarder-Webanwendung. Er gilt
Dieser Hinweis gilt für die {APP_NAME}-Webanwendung. Er gilt
für alle Nutzer weltweit, einschließlich derjenigen in der
Europäischen Union (EU), dem Europäischen Wirtschaftsraum (EWR),
Deutschland, dem Vereinigten Königreich (UK), der Schweiz, der
+6 -3
View File
@@ -1,8 +1,11 @@
import Link from 'next/link';
import type { Metadata } from 'next';
const APP_NAME = process.env.APP_NAME ?? 'InboxConverge';
const CONTACT_EMAIL = process.env.CONTACT_EMAIL ?? 'christian@inboxconverge.com';
export const metadata: Metadata = {
title: 'Impressum POP3 Forwarder',
title: `Impressum ${APP_NAME}`,
};
export default function ImpressumPage() {
@@ -36,10 +39,10 @@ export default function ImpressumPage() {
Fax: +49 40 97074609<br />
E-Mail:{' '}
<a
href="mailto:christianlouis@gmail.com"
href={`mailto:${CONTACT_EMAIL}`}
className="text-blue-600 hover:text-blue-500"
>
christianlouis@gmail.com
{CONTACT_EMAIL}
</a>
</p>
</section>
+1 -1
View File
@@ -14,7 +14,7 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
title: "InboxRescue — your old inboxes, delivered to Gmail",
title: "InboxConverge — your old inboxes, delivered to Gmail",
description: "Poll your legacy POP3 and IMAP mailboxes and have everything land quietly in Gmail. Set it once, forget it exists.",
};
+1 -1
View File
@@ -46,7 +46,7 @@ export default function LoginPage() {
<div className="max-w-md w-full space-y-8">
<div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
POP3 to Gmail Forwarder
InboxConverge
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Sign in to your account
+6 -6
View File
@@ -106,7 +106,7 @@ export default function Home() {
<div className="flex justify-between items-center py-4">
<div className="flex items-center">
<Mail className="h-8 w-8 text-blue-600 mr-2" />
<h1 className="text-2xl font-bold text-gray-900">InboxRescue</h1>
<h1 className="text-2xl font-bold text-gray-900">InboxConverge</h1>
</div>
<div className="flex items-center gap-4">
<Link
@@ -136,7 +136,7 @@ export default function Home() {
</h2>
<p className="text-xl text-gray-600 mb-4 max-w-2xl mx-auto">
You know the ones that GMX account from 2009, the old ISP address your
bank still sends to, the Hotmail you gave out in school. InboxRescue
bank still sends to, the Hotmail you gave out in school. InboxConverge
quietly polls them all and drops everything into your Gmail. Set it once,
forget it exists.
</p>
@@ -171,7 +171,7 @@ export default function Home() {
Auto-detects everything
</h3>
<p className="text-gray-600">
Type your old email address and InboxRescue figures out the server
Type your old email address and InboxConverge figures out the server
settings. No Googling port numbers required.
</p>
</div>
@@ -215,7 +215,7 @@ export default function Home() {
</div>
<h4 className="text-xl font-semibold text-gray-900 mb-2">Add your old inbox</h4>
<p className="text-gray-600">
Paste the email address InboxRescue auto-detects the POP3/IMAP
Paste the email address InboxConverge auto-detects the POP3/IMAP
settings in seconds.
</p>
</div>
@@ -225,7 +225,7 @@ export default function Home() {
</div>
<h4 className="text-xl font-semibold text-gray-900 mb-2">Connect Gmail</h4>
<p className="text-gray-600">
Sign in with Google once. InboxRescue delivers mail directly into
Sign in with Google once. InboxConverge delivers mail directly into
your inbox using the Gmail API no SMTP relay needed.
</p>
</div>
@@ -270,7 +270,7 @@ export default function Home() {
<footer className="mt-20 border-t border-gray-200 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<p className="text-center text-gray-600 text-sm">
© {new Date().getFullYear()} InboxRescue made for people, not enterprises.
© {new Date().getFullYear()} InboxConverge made for people, not enterprises.
</p>
</div>
</footer>
+2 -2
View File
@@ -54,7 +54,7 @@ export function DashboardLayout({ children }: DashboardLayoutProps) {
<div className="hidden lg:fixed lg:inset-y-0 lg:flex lg:w-64 lg:flex-col">
<div className="flex flex-col flex-grow bg-white border-r border-gray-200">
<div className="flex items-center h-16 flex-shrink-0 px-4 border-b border-gray-200">
<h1 className="text-xl font-bold text-gray-900">InboxRescue</h1>
<h1 className="text-xl font-bold text-gray-900">InboxConverge</h1>
</div>
<nav className="flex-1 px-2 py-4 space-y-1">
{navigation.map((item) => {
@@ -117,7 +117,7 @@ export function DashboardLayout({ children }: DashboardLayoutProps) {
<div className="fixed inset-0 bg-gray-600/75" onClick={() => setSidebarOpen(false)} />
<div className="fixed inset-y-0 left-0 flex w-64 flex-col bg-white">
<div className="flex items-center justify-between h-16 px-4 border-b border-gray-200">
<h1 className="text-xl font-bold text-gray-900">InboxRescue</h1>
<h1 className="text-xl font-bold text-gray-900">InboxConverge</h1>
<button onClick={() => setSidebarOpen(false)} className="text-gray-500 hover:text-gray-700">
<X className="h-6 w-6" />
</button>
+4 -4
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
POP3 to Gmail Forwarder
InboxConverge
Fetches emails from POP3 mailboxes and forwards them to Gmail
"""
@@ -80,7 +80,7 @@ class POP3Account:
class EmailForwarder:
"""Main class for forwarding emails from POP3 to Gmail"""
"""Main class for forwarding emails from POP3 to Gmail via InboxConverge"""
def __init__(self):
self.smtp_host = os.getenv('SMTP_HOST', 'smtp.gmail.com')
@@ -241,7 +241,7 @@ class EmailForwarder:
payload = json.dumps({
"From": self.postmark_from,
"To": self.postmark_to,
"Subject": f"[POP3 Forwarder Alert] {subject}",
"Subject": f"[InboxConverge Alert] {subject}",
"TextBody": f"Error occurred at {datetime.now().isoformat()}\n\n{error_message}",
"MessageStream": "outbound"
})
@@ -312,7 +312,7 @@ class EmailForwarder:
def main():
"""Main entry point"""
logger.info("POP3 to Gmail Forwarder starting...")
logger.info("InboxConverge starting...")
forwarder = EmailForwarder()
@@ -51,7 +51,7 @@
}
]
},
"description": "InboxRescue system health: mail processing, Gmail API, auth, and HTTP metrics",
"description": "InboxConverge system health: mail processing, Gmail API, auth, and HTTP metrics",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
@@ -1111,7 +1111,7 @@
],
"refresh": "30s",
"schemaVersion": 38,
"tags": ["inboxrescue", "monitoring", "email"],
"tags": ["inboxconverge", "monitoring", "email"],
"templating": {
"list": []
},
@@ -1121,8 +1121,8 @@
},
"timepicker": {},
"timezone": "browser",
"title": "InboxRescue - System Health",
"uid": "inboxrescue-health",
"title": "InboxConverge - System Health",
"uid": "inboxconverge-health",
"version": 1,
"weekStart": ""
}
@@ -1,7 +1,7 @@
apiVersion: 1
providers:
- name: InboxRescue
- name: InboxConverge
orgId: 1
type: file
disableDeletion: false
+1 -1
View File
@@ -3,7 +3,7 @@ global:
evaluation_interval: 15s
scrape_configs:
- job_name: "inboxrescue-backend"
- job_name: "inboxconverge-backend"
static_configs:
- targets: ["backend:8000"]
metrics_path: /metrics