How to Configure SMTP for Notifications in OpenCTI: Complete Setup Guide
Configure SMTP in OpenCTI by setting environment variables such as SMTP__HOSTNAME, SMTP__PORT, and SMTP__USERNAME in your Docker Compose or .env file, which the platform uses to initialize a nodemailer transport in src/database/smtp.js for sending password resets and ingestion alerts.
OpenCTI relies on a centralized SMTP transport layer to deliver critical email notifications, including user password resets and automated ingestion alerts. The platform implements this functionality using nodemailer within the src/database/smtp.js module, reading configuration parameters from environment variables during the initialization process defined in src/initialization.js.
Understanding the SMTP Architecture in OpenCTI
Core SMTP Transport Layer (src/database/smtp.js)
The core SMTP logic resides in src/database/smtp.js, where the smtpOptions object is assembled from environment variables (lines 15-25). This configuration object is passed to nodemailer's createTransport method to establish the connection. The module exports sendMail(), which wraps the native nodemailer method and records metrics via MeterManager (lines 59-65).
Startup Health Verification (src/initialization.js)
During platform startup, src/initialization.js invokes smtpIsAlive() (lines 53-55) to verify SMTP connectivity before marking the service as ready. If the check fails, the logs display "SMTP seems down, e-mail notification may not work" (lines 48-55 in smtp.js), alerting administrators to configuration errors.
Environment Variables for SMTP Configuration
OpenCTI uses double-underscore notation to map environment variables to nested configuration keys. The following variables control the SMTP transport:
SMTP__HOSTNAME– SMTP server hostname (default:localhost)SMTP__PORT– Server port (default:25)SMTP__USE_SSL– Enable TLS/SSL (default:false)SMTP__REJECT_UNAUTHORIZED– Reject unauthorized certificates (default:true)SMTP__USERNAME– Authentication usernameSMTP__PASSWORD– Authentication passwordSMTP__ENABLED– Master toggle for SMTP functionality (default:true)SMTP__FORCED_SENDER_EMAIL– Override all sender addresses (optional)
Step-by-Step SMTP Configuration Guide
Configure Basic SMTP Connectivity
Set the required environment variables in your Docker Compose file or .env file. For a typical TLS configuration on port 587:
SMTP__HOSTNAME=smtp.mailgun.org
SMTP__PORT=587
SMTP__USE_SSL=false
SMTP__REJECT_UNAUTHORIZED=true
SMTP__USERNAME=postmaster@mydomain.com
SMTP__PASSWORD=your_secure_password
SMTP__ENABLED=true
Set a Forced Sender Email Address
To ensure all notifications originate from a single address regardless of UI settings, configure the forced sender option. In src/database/smtp.js (lines 9-12, 36-38), setting SMTP__FORCED_SENDER_EMAIL disables the ALLOW_EMAIL_REWRITE flag and forces smtpConfiguredEmail() to return the specified value.
SMTP__FORCED_SENDER_EMAIL=security-alerts@myorg.com
Configure Platform Email in the UI
When not using a forced sender, administrators can set the default sender address via the web interface. Navigate to Settings → Platform → Platform email to define the address used by smtpComputeFrom() (lines 40-46 in src/database/smtp.js) when constructing the From: header.
Verify SMTP Connectivity
After restarting the platform, monitor the startup logs for the "SMTP alive" message generated by smtpIsAlive() in src/initialization.js (lines 53-55). Alternatively, use the test functionality in Settings → Platform by entering an address in the "Test e-mail address" field and clicking the test button, which invokes the GraphQL settingsTestMail mutation.
Sending Custom Notifications Programmatically
Developers building connectors or custom scripts can leverage the sendMail function exported from src/database/smtp.js. The function accepts a nodemailer-compatible mail object and an optional metrics context.
import { sendMail, smtpComputeFrom } from '../../src/database/smtp.js';
// Build the email payload
const buildMail = async (to, subject, html) => ({
from: await smtpComputeFrom('OpenCTI Connector'),
to,
subject,
html,
});
// Example usage inside a connector
const notifyUser = async (userEmail, indicatorName) => {
const mail = await buildMail(
userEmail,
'New Indicator Ingestion',
`<p>The indicator <strong>${indicatorName}</strong> has been ingested.</p>`
);
await sendMail(mail, { name: 'custom_ingestion_alert' });
};
Troubleshooting Common SMTP Issues
- Connection timeouts: Verify that
SMTP__HOSTNAMEandSMTP__PORTmatch your provider's settings. For port 587, setSMTP__USE_SSL=falseto allow STARTTLS negotiation. - Authentication failures: Ensure
SMTP__USERNAMEandSMTP__PASSWORDare correctly encoded without quotes in the environment file. - Certificate errors: Set
SMTP__REJECT_UNAUTHORIZED=falseonly in development environments to bypass self-signed certificate validation. - Forced email not applied: Check that
SMTP__FORCED_SENDER_EMAILis set as an environment variable; the configuration fileconfig/default.jsonentrysmtp:forced_sender_emailis also valid but environment variables take precedence in containerized deployments.
Summary
- OpenCTI uses nodemailer in
src/database/smtp.jsto manage SMTP connections and send notifications. - Configuration is driven by environment variables using double-underscore notation (e.g.,
SMTP__HOSTNAME,SMTP__PORT). - The forced sender email (
SMTP__FORCED_SENDER_EMAIL) overrides all UI settings and ensures consistent sender addresses. - Health checks occur during startup in
src/initialization.jsviasmtpIsAlive(). - Developers can import
sendMailandsmtpComputeFromfromsrc/database/smtp.jsto send custom notifications from connectors.
Frequently Asked Questions
What environment variables are required to configure SMTP in OpenCTI?
At minimum, you must set SMTP__HOSTNAME and SMTP__PORT to define the server endpoint. If authentication is required, provide SMTP__USERNAME and SMTP__PASSWORD. For TLS configurations, set SMTP__USE_SSL=true (port 465) or false with SMTP__REJECT_UNAUTHORIZED for STARTTLS on port 587.
How do I set a fixed sender email address for all OpenCTI notifications?
Set the SMTP__FORCED_SENDER_EMAIL environment variable (or smtp:forced_sender_email in config/default.json). According to the source code in src/database/smtp.js (lines 9-12, 36-38), this disables the ALLOW_EMAIL_REWRITE flag and forces every notification to use the specified address, overriding any UI-configured platform email.
Where does OpenCTI verify SMTP connectivity during startup?
The platform calls smtpIsAlive() from src/database/smtp.js during the initialization sequence defined in src/initialization.js (lines 53-55). This health check verifies that the nodemailer transport can reach the configured SMTP server before the platform finishes booting, logging "SMTP alive" on success or a warning if the server is unreachable.
Can I send custom email notifications from an OpenCTI connector?
Yes. Import sendMail and smtpComputeFrom from src/database/smtp.js in your connector code. Build a nodemailer-compatible mail object with from, to, subject, and html fields, then call await sendMail(mail, { name: 'metric_name' }). The function handles the transport connection and records metrics automatically, as implemented in lines 59-65 of src/database/smtp.js.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →