echo6-docs/runbooks/mailcow-create-mailbox.md
Matt Johnson e9231ac24a Migration: consolidate Echo6 docs to cortex with full infrastructure cleanup sync
- Documents recent infrastructure cleanup (8 CTs destroyed, 35 DNS records removed, Headscale cleanup)
- Adds 24 new runbooks covering Authentik, PeerTube, Meshtastic, RECON, Proxmox, Mailcow, Internet Archive, GPU routing
- Adds project documentation for headscale, vaultwarden, peertube, matrix, mmud, advbbs, arr stack
- Updates services.md, environment.md, caddy.md, authentik.md to match live infrastructure
- Removes 4 deprecated runbook duplicates (canonical versions live in projects/)
- Adds .gitignore for binary archives and editor temp files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 06:02:16 +00:00

259 lines
8.1 KiB
Markdown

# Mailcow: Create Mailbox
Create a new mailbox in Mailcow on the Contabo VPS. Covers both interactive (UI) and API-driven creation, with the critical authsource fix for service accounts.
---
## When to Use This
Any time a new mailbox is created in Mailcow, but **especially** for service/system accounts that authenticate via SMTP to send mail programmatically (e.g., `no-reply@echo6.co` used by Authentik, `recon@echo6.co` used by the RECON pipeline). These accounts don't log in through the Mailcow web UI or SSO — they pass credentials directly to Postfix over SMTP, so they **must** use local password authentication.
---
## Prerequisites
- SSH access to Contabo (`ssh root@100.64.0.1`)
- Mailcow API key (stored in Mailcow admin UI under System → Configuration → API)
- Mailcow DB password: source from `/opt/mailcow-dockerized/.env` (`DBPASS`)
---
## Inputs
```
LOCAL_PART=no-reply # Left side of the @ sign
DOMAIN=echo6.co # Must already exist in Mailcow
DISPLAY_NAME="Echo6 No Reply" # Friendly name
PASSWORD=<strong-password> # Generate with: openssl rand -base64 24 | tr -d '/+='
QUOTA_MB=256 # Mailbox quota in MB
IS_SERVICE_ACCOUNT=true # true = SMTP sender, false = regular user
MAILCOW_API_KEY=<api-key> # From Mailcow admin UI
```
---
## Step 1: Create the Mailbox
### Option A: Via Mailcow API
```bash
ssh root@100.64.0.1
curl -sk -X POST "https://127.0.0.1:8443/api/v1/add/mailbox" \
-H "X-API-Key: ${MAILCOW_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"local_part": "'${LOCAL_PART}'",
"domain": "'${DOMAIN}'",
"name": "'${DISPLAY_NAME}'",
"password": "'${PASSWORD}'",
"password2": "'${PASSWORD}'",
"quota": '${QUOTA_MB}',
"active": 1,
"force_pw_update": 0,
"tls_enforce_in": 1,
"tls_enforce_out": 1
}'
```
Expected response:
```json
[{"type":"success","msg":["mailbox_added","no-reply@echo6.co"]}]
```
### Option B: Via Mailcow Admin UI
1. Open https://mail.echo6.co (log in as admin)
2. Navigate to **Email → Mailboxes → Add mailbox**
3. Fill in local part, domain, display name, password, quota
4. Click **Add**
### Access Flags
For service accounts (send-only), disable unnecessary access after creation:
```bash
curl -sk -X POST "https://127.0.0.1:8443/api/v1/edit/mailbox" \
-H "X-API-Key: ${MAILCOW_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"items": ["'${LOCAL_PART}@${DOMAIN}'"],
"attr": {
"sogo_access": "0",
"imap_access": "0",
"pop3_access": "0",
"smtp_access": "1"
}
}'
```
Regular user accounts can leave all access flags at their defaults (all enabled).
---
## Step 2: Fix authsource (CRITICAL for Service Accounts)
### The Problem
Mailcow domains configured with OIDC authentication (like `echo6.co` with Authentik SSO) set `authsource=generic-oidc` on **every new mailbox by default**. This tells Dovecot to authenticate the account through the OIDC provider instead of the local password hash.
For service accounts that log in via SMTP with a username and password, this means:
1. Postfix receives the SMTP AUTH credentials
2. Postfix hands them to Dovecot for verification
3. Dovecot's Lua passdb sees `authsource=generic-oidc`
4. Dovecot tries to authenticate via Authentik SSO
5. The service account doesn't exist in Authentik → **auth fails silently**
6. SMTP returns `535 5.7.8 Error: authentication failed: (reason unavailable)`
The failure message gives no indication that OIDC is the cause. The password is correct, the mailbox exists, and the Mailcow API reports success on password changes — but SMTP auth never works.
### The Fix
Change the authsource from `generic-oidc` to `mailcow` in the database:
```bash
ssh root@100.64.0.1
# Source the DB password
DBPASS=$(grep ^DBPASS /opt/mailcow-dockerized/.env | cut -d= -f2)
# Check current authsource
docker exec mailcowdockerized-mysql-mailcow-1 \
mysql -u mailcow -p${DBPASS} mailcow -N \
-e "SELECT username, authsource FROM mailbox WHERE username='${LOCAL_PART}@${DOMAIN}'"
# Fix: set authsource to local password auth
docker exec mailcowdockerized-mysql-mailcow-1 \
mysql -u mailcow -p${DBPASS} mailcow \
-e "UPDATE mailbox SET authsource='mailcow' WHERE username='${LOCAL_PART}@${DOMAIN}'"
```
**When to apply:**
| Account Type | authsource | Reason |
|-------------|-----------|--------|
| Service account (SMTP sender) | `mailcow` | Authenticates with local password via SMTP |
| Regular user (SSO login) | `generic-oidc` | Authenticates through Authentik web SSO |
| Regular user (IMAP/SMTP client) | `mailcow` | Authenticates with local password from mail client |
Rule of thumb: if the account will ever authenticate with a username + password (SMTP, IMAP, POP3), set `authsource=mailcow`. Only leave `generic-oidc` for accounts that exclusively use SSO web login.
---
## Step 3: Verify SMTP Authentication
Wait a few seconds after the authsource fix, then test:
```bash
# From the Contabo host
python3 -c "
import smtplib
s = smtplib.SMTP('mail.echo6.co', 587, timeout=10)
s.starttls()
s.login('${LOCAL_PART}@${DOMAIN}', '${PASSWORD}')
print('SMTP auth: OK')
s.quit()
"
```
If SMTP auth is being used from inside a Docker container (like Authentik), also test from there:
```bash
docker exec authentik-worker python3 -c "
import smtplib
s = smtplib.SMTP('mail.echo6.co', 587, timeout=10)
s.starttls()
s.login('${LOCAL_PART}@${DOMAIN}', '${PASSWORD}')
print('Container SMTP auth: OK')
s.quit()
"
```
Both should print `OK`. If either fails with `535 5.7.8 Error: authentication failed`, re-check the authsource (Step 2).
---
## Step 4: Store Credentials
Add the new mailbox credentials to `/home/zvx/projects/.ref/credentials`:
```
# Mailcow: ${LOCAL_PART}@${DOMAIN}
MAILCOW_${LOCAL_PART^^}_USER=${LOCAL_PART}@${DOMAIN}
MAILCOW_${LOCAL_PART^^}_PASS=${PASSWORD}
```
---
## Troubleshooting
### SMTP auth fails immediately after mailbox creation
**Cause:** `authsource=generic-oidc` (see Step 2).
### SMTP auth fails after it was previously working
**Cause 1:** Mailcow may have reset the authsource during a stack restart or update. Re-apply Step 2.
**Cause 2:** The password hash may have been corrupted by a failed API password reset. Mailcow's password edit API (`/api/v1/edit/mailbox`) sometimes reports success but doesn't actually update the hash. **Workaround:** Delete the mailbox and recreate it from scratch (Step 1), then re-apply the authsource fix (Step 2). Do not attempt to reset the password via API.
### "Unknown user" in Dovecot logs
Check that the mailbox exists and is active:
```bash
curl -sk "https://127.0.0.1:8443/api/v1/get/mailbox/${LOCAL_PART}@${DOMAIN}" \
-H "X-API-Key: ${MAILCOW_API_KEY}" | python3 -m json.tool
```
### Checking Dovecot auth logs
```bash
docker logs mailcowdockerized-dovecot-mailcow-1 --since 5m 2>&1 | grep -i auth
```
### Checking netfilter/fail2ban
Too many failed SMTP login attempts can trigger Mailcow's brute-force protection:
```bash
docker logs mailcowdockerized-netfilter-mailcow-1 --since 10m 2>&1 | grep -i ban
```
If the Contabo IP (5.189.158.149) is banned, restart the netfilter container:
```bash
cd /opt/mailcow-dockerized && docker compose restart netfilter-mailcow
```
---
## Checklist
```
[ ] Mailbox created (API or UI)
[ ] Access flags set appropriately for account type
[ ] authsource checked — set to 'mailcow' if service account
[ ] SMTP auth verified from host
[ ] SMTP auth verified from consuming container (if applicable)
[ ] Credentials stored in /home/zvx/projects/.ref/credentials
```
---
## Reference: Current Service Accounts
| Mailbox | Used By | authsource | Purpose |
|---------|---------|-----------|---------|
| no-reply@echo6.co | Authentik | mailcow | SSO invitation emails, notifications |
| cipher@echo6.co | CIPHER | generic-oidc | Daily intelligence briefs |
| recon@echo6.co | RECON | generic-oidc | Pipeline notifications |
| fulcrum@echo6.co | Fulcrum | generic-oidc | Hub notifications |
**Note:** cipher, recon, and fulcrum currently use `generic-oidc`. If any of these need to send mail via SMTP (not through the SSO web UI), their authsource must be changed to `mailcow` per Step 2.
---
*Created: 2026-02-16*