Skip to content

SMTP Configuration

Self-Hosted Deployments Only

This guide is for Self-Hosted deployments. Managed customers do not configure SMTP — Qualytics operates the email transport on your behalf.

This guide explains how to configure outbound email delivery for a Self-Hosted Qualytics deployment. The controlplane uses SMTP to send user invitations, password resets, scheduled report deliveries, and operational notifications. Without SMTP configured, those email-driven flows are disabled but the rest of the platform continues to function.

How it works

Two Helm value groups configure SMTP:

Group Purpose Where it lives in values.yaml
controlplane.smtp Connection settings (server, port, sender, enable toggle) Controlplane block
secrets.smtp Credentials (username, password) — optional for relays that allow anonymous auth Secrets block, injected as a Kubernetes secret

When controlplane.smtp.enabled is true, the chart injects SMTP_SERVER, SMTP_PORT, and SMTP_SENDER_EMAIL into the controlplane API and worker pods. If both secrets.smtp.smtp_sender_user and secrets.smtp.smtp_sender_password are non-empty, SMTP_SENDER_USER and SMTP_SENDER_PASSWORD are also injected from a Kubernetes secret. If either credential is empty, the controlplane connects without authentication — useful for trusted internal relays.

Required configuration

Add the following to your values.yaml (or your chart overrides):

controlplane:
  smtp:
    enabled: true
    server: "smtp.example.com"
    port: "465"
    sender: "no-reply@your-company.com"

secrets:
  smtp:
    smtp_sender_user: "your-smtp-username"
    smtp_sender_password: "your-smtp-password"
Field Description
controlplane.smtp.enabled Master toggle. Set to false to disable SMTP entirely.
controlplane.smtp.server SMTP host. Examples: email-smtp.us-east-1.amazonaws.com (AWS SES), smtp.gmail.com, smtp.office365.com, or your internal relay.
controlplane.smtp.port SMTP port as a string. Use 465 for implicit TLS (SMTPS), 587 for STARTTLS, or 25 for unencrypted internal relays.
controlplane.smtp.sender The From address shown on outgoing emails. Must be a sender your SMTP provider has authorized.
secrets.smtp.smtp_sender_user SMTP username. Leave empty for anonymous (no-auth) relays.
secrets.smtp.smtp_sender_password SMTP password or provider-specific access token. Leave empty for anonymous relays.

Sender address must be authorized

Most SMTP providers (AWS SES, Gmail, Office 365) reject mail when the From address is not a verified or authorized sender on the account. Verify your sender value with your provider before deploying.

Common providers

controlplane:
  smtp:
    enabled: true
    server: "email-smtp.us-east-1.amazonaws.com"
    port: "465"
    sender: "no-reply@your-verified-domain.com"

secrets:
  smtp:
    smtp_sender_user: "<SES_SMTP_USERNAME>"
    smtp_sender_password: "<SES_SMTP_PASSWORD>"

SES SMTP credentials are not the same as your AWS access keys — generate them from the SES console under SMTP settings → Create SMTP credentials. The sender domain or address must be verified in SES, and your account must be moved out of the SES sandbox to email arbitrary recipients.

controlplane:
  smtp:
    enabled: true
    server: "smtp.gmail.com"
    port: "465"
    sender: "no-reply@your-workspace-domain.com"

secrets:
  smtp:
    smtp_sender_user: "no-reply@your-workspace-domain.com"
    smtp_sender_password: "<APP_PASSWORD>"

Use a Google App Password — regular account passwords will not work. The account must have 2-Step Verification enabled.

controlplane:
  smtp:
    enabled: true
    server: "smtp.office365.com"
    port: "587"
    sender: "no-reply@your-tenant.onmicrosoft.com"

secrets:
  smtp:
    smtp_sender_user: "no-reply@your-tenant.onmicrosoft.com"
    smtp_sender_password: "<APP_PASSWORD>"

Office 365 requires STARTTLS on port 587. SMTP AUTH must be enabled on the mailbox, which Microsoft disables by default for tenants created after 2020 — your administrator may need to re-enable it via PowerShell.

controlplane:
  smtp:
    enabled: true
    server: "internal-relay.your-company.local"
    port: "25"
    sender: "no-reply@your-company.com"

secrets:
  smtp:
    smtp_sender_user: ""
    smtp_sender_password: ""

Leaving both credential fields empty causes the chart to skip injecting SMTP_SENDER_USER / SMTP_SENDER_PASSWORD, and the controlplane connects without authentication. Use this for internal MTAs that authorize the controlplane pods by source IP or network position.

TLS certificate validation

The controlplane validates TLS certificates on outbound SMTP SSL sessions by default. If your relay uses a private CA or self-signed certificate (common in air-gapped environments), disable validation globally:

controlplane:
  egress:
    verifyTLSCertificates: false

This setting also disables validation for HTTP egress and other outbound TLS sessions, so prefer importing your private CA into the controlplane image when possible.

Apply and verify

Apply your changes with helm upgrade:

helm upgrade qualytics qualytics/qualytics \
    --namespace qualytics --reuse-values \
    -f values.yaml

Restart the controlplane pods to pick up the new env vars:

kubectl rollout restart deployment -n qualytics qualytics-api qualytics-cmd

Verify the env vars landed in the controlplane:

kubectl exec -n qualytics deploy/qualytics-api -- env | grep SMTP_

Expected output (the password is intentionally not echoed by the controlplane image but the env var should be set):

SMTP_SERVER=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=465
SMTP_SENDER_EMAIL=no-reply@your-domain.com
SMTP_SENDER_USER=AKIA...
SMTP_SENDER_PASSWORD=********

To exercise the live SMTP path, invite a test user from the Settings → Users screen and confirm the invitation email arrives.

Troubleshooting

Symptom Likely cause Fix
No emails sent, no errors in logs controlplane.smtp.enabled is false, or env vars are missing because the deployment was not restarted Confirm enabled: true, run kubectl rollout restart, and re-check env vars.
SMTPAuthenticationError Wrong username/password, or the provider requires an app-specific password / SES SMTP credential Regenerate credentials with the provider and update secrets.smtp.
SMTPSenderRefused sender is not a verified address on the provider account Verify the sender address with your provider; for SES, check the SES sandbox status.
SSLError / CertificateVerifyFailed Relay uses a private CA the controlplane does not trust Either import the CA into the controlplane image or set controlplane.egress.verifyTLSCertificates: false.
Connection timeout NetworkPolicy or egress firewall blocks outbound SMTP Allow egress from the controlplane namespace to the SMTP host on the configured port.
Connection unexpectedly closed on port 587 Relay requires STARTTLS but is being approached as implicit TLS Confirm port matches the provider's auth mode — 465 for SMTPS, 587 for STARTTLS.