diff --git a/.env.example b/.env.example index 231d3789..c1c35b60 100644 --- a/.env.example +++ b/.env.example @@ -17,6 +17,7 @@ SMTP_USER= SMTP_PASSWORD= EMAIL_FROM= # e.g. "Kan " SMTP_SECURE= # set to "false" to use port 587 +SMTP_REJECT_UNAUTHORIZED= # set to "false" to accept invalid certs # Switch email features off entirely (optional) NEXT_PUBLIC_DISABLE_EMAIL= diff --git a/README.md b/README.md index 91fe3c5a..55e48c40 100644 --- a/README.md +++ b/README.md @@ -138,42 +138,43 @@ pnpm dev ## Environment Variables 🔐 -| Variable | Description | Required | Example | -| ----------------------------------------- | -------------------------------------------------------- | ------------------------ | ----------------------------------------------------------- | -| `POSTGRES_URL` | PostgreSQL connection URL | To use external database | `postgres://user:pass@localhost:5432/db` | -| `EMAIL_FROM` | Sender email address | For Email | `"Kan "` | -| `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` | -| `SMTP_PORT` | SMTP server port | For Email | `465` | -| `SMTP_USER` | SMTP username/email | No | `resend` | -| `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` | -| `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` | -| `NEXT_PUBLIC_DISABLE_EMAIL` | To disable all email features | For Email | `true` | -| `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` | -| `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string | -| `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` | -| `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` | -| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` | -| `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` | -| `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` | -| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` | -| `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` | -| `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` | -| `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` | -| `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` | -| `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` | -| `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` | -| `S3_REGION` | S3 storage region | For file uploads | `WEUR` | -| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` | -| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` | -| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` | -| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` | -| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` | -| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` | -| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` | -| `NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME` | S3 bucket name for attatchments | For file uploads | `attatchments` | -| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` | -| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` | -| `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` | +| Variable | Description | Required | Example | +| ----------------------------------------- | --------------------------------------------------------- | ------------------------ | ----------------------------------------------------------- | +| `POSTGRES_URL` | PostgreSQL connection URL | To use external database | `postgres://user:pass@localhost:5432/db` | +| `EMAIL_FROM` | Sender email address | For Email | `"Kan "` | +| `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` | +| `SMTP_PORT` | SMTP server port | For Email | `465` | +| `SMTP_USER` | SMTP username/email | No | `resend` | +| `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` | +| `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` | +| `SMTP_REJECT_UNAUTHORIZED` | Reject invalid certificates (defaults to true if not set) | For Email | `false` | +| `NEXT_PUBLIC_DISABLE_EMAIL` | To disable all email features | For Email | `true` | +| `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` | +| `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string | +| `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` | +| `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` | +| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` | +| `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` | +| `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` | +| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` | +| `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` | +| `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` | +| `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` | +| `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` | +| `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` | +| `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` | +| `S3_REGION` | S3 storage region | For file uploads | `WEUR` | +| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` | +| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` | +| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` | +| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` | +| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` | +| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` | +| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` | +| `NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME` | S3 bucket name for attachments | For file uploads | `attachments` | +| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` | +| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` | +| `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` | See `.env.example` for a complete list of supported environment variables. diff --git a/cloud/docker-compose.yml b/cloud/docker-compose.yml index d13205ea..d3bb4418 100644 --- a/cloud/docker-compose.yml +++ b/cloud/docker-compose.yml @@ -35,6 +35,7 @@ services: - SMTP_PASSWORD=${SMTP_PASSWORD} - SMTP_SECURE=${SMTP_SECURE} - EMAIL_FROM=${EMAIL_FROM} + - SMTP_REJECT_UNAUTHORIZED=${SMTP_REJECT_UNAUTHORIZED} # Notifications - NOVU_API_KEY=${NOVU_API_KEY} diff --git a/docker-compose.yml b/docker-compose.yml index fca7330d..0ccd9b5e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,7 @@ services: - SMTP_USER=${SMTP_USER} - SMTP_PASSWORD=${SMTP_PASSWORD} - EMAIL_FROM=${EMAIL_FROM} + - SMTP_REJECT_UNAUTHORIZED=${SMTP_REJECT_UNAUTHORIZED} # Disable email features entirely (optional) - NEXT_PUBLIC_DISABLE_EMAIL=${NEXT_PUBLIC_DISABLE_EMAIL} diff --git a/packages/email/src/sendEmail.tsx b/packages/email/src/sendEmail.tsx index 41ed1d23..a087606c 100644 --- a/packages/email/src/sendEmail.tsx +++ b/packages/email/src/sendEmail.tsx @@ -16,7 +16,17 @@ const emailTemplates: Record = { const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT), - secure: process.env.SMTP_SECURE !== "false", + secure: + process.env.SMTP_SECURE === undefined + ? true + : process.env.SMTP_SECURE?.toLowerCase() === "true", + tls: { + // do not fail on invalid certs + rejectUnauthorized: + process.env.SMTP_REJECT_UNAUTHORIZED === undefined + ? true + : process.env.SMTP_REJECT_UNAUTHORIZED?.toLowerCase() === "true", + }, ...(process.env.SMTP_USER && process.env.SMTP_PASSWORD && { auth: { diff --git a/turbo.json b/turbo.json index e0a56510..eb3c1fdc 100644 --- a/turbo.json +++ b/turbo.json @@ -96,6 +96,7 @@ "SMTP_USER", "SMTP_PASSWORD", "SMTP_SECURE", + "SMTP_REJECT_UNAUTHORIZED", "NEXT_PUBLIC_KAN_ENV", "NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY", "STRIPE_SECRET_KEY",