Environment Variables

MailPort is configured entirely through environment variables. On Vercel, go to Settings → Environment Variables; for local development, copy .env.example to .env.

Required

VariableDescription
ADMIN_PASSWORDDashboard login password. Use a long random string.
MAILPORT_SECRETMaster secret. Encrypts SMTP and API keys and signs admin sessions. At least 32 characters. Keep it safe; rotating it invalidates all encrypted credentials.

Without these, login returns 503 and writes fail.

Database (configure one group)

MailPort auto-detects the driver in this fixed order: PostgreSQL → MongoDB → MySQL → SQLite. Configure exactly one group.

PostgreSQL

Works with Supabase, Neon, Tembo, or self-hosted.

VariableRequiredDefaultDescription
PG_DByesDatabase name
PG_USERyesUsername
PG_PASSWORDyesPassword
PG_HOST127.0.0.1Host
PG_PORT5432Port
PG_SSLfalseForce SSL

Aliases also accepted: POSTGRES_DATABASE, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT, POSTGRES_SSL.

MongoDB

Works with MongoDB Atlas or self-hosted MongoDB.

VariableRequiredDefaultDescription
MONGO_DByesDatabase name
MONGO_USERUsername (usually required by self-hosted)
MONGO_PASSWORDPassword
MONGO_HOST127.0.0.1Host. For clusters, use a JSON array like ["h1","h2"]
MONGO_PORT27017Port. JSON array for clusters
MONGO_REPLICASETReplica set name. Required with multiple hosts
MONGO_AUTHSOURCEadmin (when user set)Auth source
MONGO_OPT_SSLfalseAtlas requires true

A full MONGODB_URI connection string is also accepted and takes precedence over the variables above.

MySQL / TiDB

Works with self-hosted MySQL, PlanetScale, FreeDB. TiDB is wire-compatible — use the MySQL variables.

VariableRequiredDefaultDescription
MYSQL_DByesDatabase name
MYSQL_USERyesUsername
MYSQL_PASSWORDyesPassword
MYSQL_HOST127.0.0.1Host
MYSQL_PORT3306Port
MYSQL_SSLfalseForce SSL

TiDB aliases also accepted: TIDB_DB, TIDB_USER, TIDB_PASSWORD, TIDB_HOST, TIDB_PORT, TIDB_SSL.

SQLite

Local development and VPS only. Not usable on Vercel Serverless (read-only filesystem).

VariableRequiredDefaultDescription
SQLITE_PATHyes./dataDirectory holding the database file
SQLITE_DBmailport.dbDatabase file name

Optional

VariableDefaultDescription
SITE_LOCALEenDefault UI locale. Values: en, zh-cn
SESSION_TTL604800 (7 days)Admin session lifetime, in seconds
TZUTCReserved. Does not affect the UI in this version (see note below)

Timezone (TZ)

In the current version, send logs and key usage times are formatted in the browser and follow each visitor's system timezone — the server-side TZ variable does not affect the UI. It is reserved for future server-side time formatting.

If you do set it, note that POSIX timezone signs are inverted:

ValueActual zone
Asia/ShanghaiUTC+8 (recommended; IANA name, handles DST)
UTC-8UTC+8
Etc/GMT-8UTC+8
UTC+8UTC-8 (inverted — a common trap)

UI language

Set SITE_LOCALE to choose the dashboard's default language:

ValueLanguage
enEnglish (default)
zh-cnSimplified Chinese

An invalid or missing value falls back to English.

Users can also switch language from the dropdown in the top-right corner of the dashboard. The choice is stored in a cookie that overrides the environment default for one year. To add another language, see the notes in src/i18n/.

Detection order

PG_DB / POSTGRES_DATABASE  →  PostgreSQL
MONGO_DB / MONGODB_URI     →  MongoDB
MYSQL_DB / TIDB_DB         →  MySQL
SQLITE_PATH / SQLITE_DB    →  SQLite

If none is set, /api/health reports status: "degraded" and all writes return 503.

Rotating MAILPORT_SECRET

Changing it makes previously encrypted SMTP passwords and API keys undecryptable. To rotate:

  1. Change MAILPORT_SECRET.
  2. Re-enter each sender's SMTP password in the dashboard.
  3. Delete old API keys and generate new ones; update callers.

Post-deploy check

GET /api/health:

{
  "status": "ok",
  "driver": "postgres",
  "adminConfigured": true,
  "secretConfigured": true
}

driver: null or status: "degraded" means no database was detected.