mirror of
https://github.com/ghostersk/gowebmail.git
synced 2026-04-17 08:36:01 +01:00
150 lines
5.5 KiB
Markdown
150 lines
5.5 KiB
Markdown
# GoMail
|
|
|
|
A self-hosted, encrypted web email client written entirely in Go. Supports Gmail and Outlook via OAuth2, plus any standard IMAP/SMTP provider.
|
|
|
|
# Notes:
|
|
- work still in progress
|
|
- AI is involved in making this work, as I do not have the skill and time to do it on my own
|
|
- looking for any advice and suggestions to improve it!
|
|
|
|
## Features
|
|
|
|
- **Unified inbox** — view emails from all connected accounts in one stream
|
|
- **Gmail & Outlook OAuth2** — modern, token-based auth (no storing raw passwords for these providers)
|
|
- **IMAP/SMTP** — connect any provider (ProtonMail Bridge, Fastmail, iCloud, etc.)
|
|
- **AES-256-GCM encryption** — all email content encrypted at rest in SQLite
|
|
- **bcrypt password hashing** — GoMail account passwords hashed with cost=12
|
|
- **Send / Reply / Forward** — full compose workflow
|
|
- **Folder navigation** — per-account folder/label browsing
|
|
- **Full-text search** — across all accounts locally
|
|
- **Dark-themed web UI** — clean, keyboard-shortcut-friendly interface
|
|
|
|
## Architecture
|
|
|
|
```
|
|
cmd/server/main.go Entry point, HTTP server setup
|
|
config/config.go Environment-based config
|
|
internal/
|
|
auth/oauth.go OAuth2 flows (Google + Microsoft)
|
|
crypto/crypto.go AES-256-GCM encryption + bcrypt
|
|
db/db.go SQLite database with field-level encryption
|
|
email/imap.go IMAP fetch + SMTP send via XOAUTH2
|
|
handlers/ HTTP handlers (auth, app, api)
|
|
middleware/middleware.go Logger, auth guard, security headers
|
|
models/models.go Data models
|
|
web/static/
|
|
login.html Sign-in page
|
|
register.html Registration page
|
|
app.html Single-page app (email client UI)
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### Option 1: Docker Compose (recommended)
|
|
|
|
```bash
|
|
# 1. Clone / copy the project
|
|
git clone https://github.com/yourname/gomail && cd gomail
|
|
|
|
# 2. Generate secrets
|
|
export ENCRYPTION_KEY=$(openssl rand -hex 32)
|
|
export SESSION_SECRET=$(openssl rand -hex 32)
|
|
echo "ENCRYPTION_KEY=$ENCRYPTION_KEY" # SAVE THIS — losing it means losing your email cache
|
|
|
|
# 3. Add your OAuth2 credentials to docker-compose.yml (see below)
|
|
# 4. Run
|
|
ENCRYPTION_KEY=$ENCRYPTION_KEY SESSION_SECRET=$SESSION_SECRET docker compose up
|
|
```
|
|
|
|
Visit http://localhost:8080, register an account, then connect your email.
|
|
|
|
### Option 2: Run directly
|
|
|
|
```bash
|
|
go build -o gomail ./cmd/server
|
|
export ENCRYPTION_KEY=$(openssl rand -hex 32)
|
|
export SESSION_SECRET=$(openssl rand -hex 32)
|
|
./gomail
|
|
```
|
|
|
|
## Setting up OAuth2
|
|
|
|
### Gmail
|
|
|
|
1. Go to [Google Cloud Console](https://console.cloud.google.com/) → New project
|
|
2. Enable **Gmail API**
|
|
3. Create **OAuth 2.0 Client ID** (Web application)
|
|
4. Add Authorized redirect URI: `http://localhost:8080/auth/gmail/callback`
|
|
5. Set env vars: `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`
|
|
|
|
> **Important:** In the Google Cloud Console, add the scope `https://mail.google.com/` to allow IMAP access. You'll also need to add test users while in "Testing" mode.
|
|
|
|
### Outlook / Microsoft 365
|
|
|
|
1. Go to [Azure portal](https://portal.azure.com/) → App registrations → New registration
|
|
2. Set redirect URI: `http://localhost:8080/auth/outlook/callback`
|
|
3. Under API permissions, add:
|
|
- `https://outlook.office.com/IMAP.AccessAsUser.All`
|
|
- `https://outlook.office.com/SMTP.Send`
|
|
- `offline_access`, `openid`, `profile`, `email`
|
|
4. Create a Client secret
|
|
5. Set env vars: `MICROSOFT_CLIENT_ID`, `MICROSOFT_CLIENT_SECRET`, `MICROSOFT_TENANT_ID`
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Required | Description |
|
|
|---|---|---|
|
|
| `ENCRYPTION_KEY` | **Yes** | 64-char hex string (32 bytes). Auto-generated on first run but must be persisted. |
|
|
| `SESSION_SECRET` | **Yes** | Random string for session signing. |
|
|
| `LISTEN_ADDR` | No | Default `:8080` |
|
|
| `DB_PATH` | No | Default `./data/gomail.db` |
|
|
| `BASE_URL` | No | Default `http://localhost:8080` |
|
|
| `GOOGLE_CLIENT_ID` | For Gmail | Google OAuth2 client ID |
|
|
| `GOOGLE_CLIENT_SECRET` | For Gmail | Google OAuth2 client secret |
|
|
| `GOOGLE_REDIRECT_URL` | No | Default `{BASE_URL}/auth/gmail/callback` |
|
|
| `MICROSOFT_CLIENT_ID` | For Outlook | Azure AD app client ID |
|
|
| `MICROSOFT_CLIENT_SECRET` | For Outlook | Azure AD app client secret |
|
|
| `MICROSOFT_TENANT_ID` | No | Default `common` (multi-tenant) |
|
|
| `SECURE_COOKIE` | No | Set `true` in production (HTTPS only) |
|
|
|
|
## Security Notes
|
|
|
|
- **ENCRYPTION_KEY** is critical — back it up. Without it, the encrypted SQLite database is unreadable.
|
|
- Email content (subject, from, to, body) is encrypted at rest using AES-256-GCM.
|
|
- OAuth2 tokens are stored encrypted in the database.
|
|
- Passwords for GoMail accounts are bcrypt hashed (cost=12).
|
|
- All HTTP responses include security headers (CSP, X-Frame-Options, etc.).
|
|
- In production, run behind HTTPS (nginx/Caddy) and set `SECURE_COOKIE=true`.
|
|
|
|
## Keyboard Shortcuts
|
|
|
|
| Shortcut | Action |
|
|
|---|---|
|
|
| `Ctrl/Cmd + N` | Compose new message |
|
|
| `Ctrl/Cmd + K` | Focus search |
|
|
| `Escape` | Close compose / modal |
|
|
|
|
## Dependencies
|
|
|
|
```
|
|
github.com/emersion/go-imap IMAP client
|
|
github.com/emersion/go-smtp SMTP client
|
|
github.com/emersion/go-message MIME parsing
|
|
github.com/gorilla/mux HTTP routing
|
|
github.com/mattn/go-sqlite3 SQLite driver (CGO)
|
|
golang.org/x/crypto bcrypt
|
|
golang.org/x/oauth2 OAuth2 + Google/Microsoft endpoints
|
|
```
|
|
|
|
## Building for Production
|
|
|
|
```bash
|
|
CGO_ENABLED=1 GOOS=linux go build -ldflags="-s -w" -o gomail ./cmd/server
|
|
```
|
|
|
|
CGO is required by `go-sqlite3`. Cross-compilation requires a C cross-compiler.
|
|
|
|
## License
|
|
|
|
MIT
|