How to Configure the Email Notification System with SMTP Settings in INFINI Console

To configure email notifications in INFINI Console, create an EmailServer record via the REST API with SMTP host, port, TLS settings, and authentication; when enabled, the system auto-generates a pipeline configuration that routes alert messages through the specified SMTP server.

INFINI Console delivers email alerts through a pipeline-based SMTP processor that decouples alert generation from message delivery. This guide explains how to configure the email notification system using the REST API, manage TLS encryption settings, and verify connectivity before production deployment.

Understanding the EmailServer Data Model

The foundation of email notifications in INFINI Console is the EmailServer struct defined in model/email_server.go. This model encapsulates all SMTP connection parameters, authentication credentials, and TLS security settings.

Core SMTP Configuration Fields

The EmailServer struct includes the following key fields:

type EmailServer struct {
    Name          string           `json:"name"`
    Host          string           `json:"host"`
    Port          int              `json:"port"`
    TLS           bool             `json:"tls"`               // use STARTTLS / SSL
    Auth          *model.BasicAuth `json:"auth"`              // username/password
    Enabled       bool             `json:"enabled"`           // auto-load into pipeline
    CredentialID  string           `json:"credential_id"`     // optional credential reference
    TLSMinVersion string           `json:"tls_min_version"`   // TLS10-TLS13 (default TLS12)
}

TLS Version Support

INFINI Console supports TLS versions 1.0 through 1.3 via the TLSMinVersion field. The system defines constants in model/email_server.go:

const (
    TLSVersion10 = "TLS10"
    TLSVersion11 = "TLS11"
    TLSVersion12 = "TLS12"
    TLSVersion13 = "TLS13"
)

func GetTLSVersion(version string) (uint16, error) { … }

If tls_min_version is omitted, the system defaults to TLS 1.2.

Creating and Enabling an SMTP Server via REST API

The REST API for email server management is implemented in plugin/api/email/server.go, providing endpoints for creating, updating, and testing SMTP configurations.

API Endpoint and Payload Structure

To create a new SMTP server, send a POST request to /api/email/server:

curl -X POST http://localhost:8080/api/email/server \
  -H "Content-Type: application/json" \
  -d '{
        "name":"prod-smtp",
        "host":"smtp.example.com",
        "port":587,
        "tls":true,
        "auth":{
          "username":"alert@example.com",
          "password":"s3cr3t"
        },
        "tls_min_version":"TLS12",
        "enabled":true
      }'

The createEmailServer and updateEmailServer methods handle these requests, validating the payload and storing the record in the Elasticsearch-backed email-server index.

Authentication Options

You can provide credentials in two ways:

  • Inline authentication: Include the auth object with username and password directly in the JSON payload.
  • Credential reference: Provide a credential_id instead of the raw auth block. The system retrieves the stored BasicAuth credential using GetBasicAuth and stores the password securely in the keystore.

When enabled:true is set, the handler automatically triggers common.RefreshEmailServer() to regenerate the pipeline configuration.

How the Pipeline Configuration Works

INFINI Console uses an internal queue-and-pipeline architecture to process email notifications asynchronously. The pipeline generation logic resides in plugin/api/email/common/pipeline.go.

Automatic Pipeline Generation

The RefreshEmailServer() function performs the following steps:

  1. Query enabled servers from the email-server index.
  2. Validate each entry using the Validate method.
  3. Resolve credentials via GetBasicAuth (or the credential_id).
  4. Store passwords securely using keystore.SetValue.
  5. Generate a YAML pipeline via GeneratePipelineConfig.
  6. Write the configuration to send_email.yml in the console's config directory (global.Env().GetConfigDir()).

The send_email.yml Structure

The generated pipeline configuration maps server IDs to SMTP processors:

pipeline:
  - name: send_email_service
    auto_start: true
    processor:
      - consumer:
          queue_selector:
            keys: ["email_messages"]
          processor:
            - smtp:
                idle_timeout_in_seconds: 1
                servers:
                  "server-id-123":
                    server:
                      host: smtp.example.com
                      port: 587
                      tls: true
                      refresh_timestamp: 1709280000000
                    min_tls_version: TLS12
                    auth:
                      username: alert@example.com
                      password: $[[keystore.server-id-123_password]]
                templates:
                  raw:
                    content_type: "text/plain"
                    subject: "$[[subject]]"
                    body: "$[[body]]"

The password is referenced via a keystore placeholder ($[[keystore.<id>_password]]), ensuring credentials are not exposed in plain text.

Message Flow from Alert to SMTP

When an alert rule triggers an email action, the EmailAction.Execute() method in service/alerting/action/email.go constructs a message and pushes it to the queue:

func (act *EmailAction) Execute() ([]byte, error) {
    queueCfg := queue.GetOrInitConfig(EmailQueueName) // "email_messages"
    emailMsg := util.MapStr{
        "server_id": act.Data.ServerID,
        "email":     act.Data.Recipients.To,
        "template":  "raw",
        "variables": util.MapStr{
            "subject": act.Subject,
            "body":    act.Body,
        },
    }
    return nil, queue.Push(queueCfg, util.MustToJSONBytes(emailMsg))
}

The pipeline's consumer reads from the email_messages queue and forwards the message to the SMTP server specified in the server_id field, using the TLS version configured for that server.

Testing Your SMTP Configuration

Before relying on email alerts in production, verify your SMTP settings using the built-in test endpoint implemented in plugin/api/email/server.go.

Using the Test Endpoint

Send a POST request to /api/email/server/_test:

curl -X POST http://localhost:8080/api/email/server/_test \
  -H "Content-Type: application/json" \
  -d '{
        "send_to":["admin@example.com"],
        "host":"smtp.example.com",
        "port":587,
        "tls":true,
        "auth":{
          "username":"alert@example.com",
          "password":"s3cr3t"
        },
        "tls_min_version":"TLS13"
      }'

TLS Version Defaults in Testing

The testEmailServer method follows the same defaults as the main configuration. If tls_min_version is omitted, the code explicitly defaults to TLS 1.2:

if reqBody.TLSMinVersion == "" {
    reqBody.TLSMinVersion = model.TLSVersion12
}
tlsMinVersion, err := model.GetTLSVersion(reqBody.TLSMinVersion)

A successful test returns HTTP 200 with a JSON acknowledgement, confirming that the console can establish the SMTP connection and authenticate using the specified TLS version.

Complete Configuration Workflow

Follow these steps to fully configure email notifications in INFINI Console:

  1. Define the EmailServer record via POST /api/email/server with your SMTP host, port, TLS settings, and authentication credentials.
  2. Enable the server by setting "enabled": true in the payload; this triggers automatic pipeline generation.
  3. Verify the pipeline by checking that send_email.yml exists in the console's config directory (global.Env().GetConfigDir()).
  4. Test connectivity using the /api/email/server/_test endpoint before creating alert rules.
  5. Create alert rules that reference the email server ID as a destination (defined in model/alerting/destination.go).
  6. Monitor the queue; when alerts trigger, EmailAction.Execute() pushes messages to email_messages, which the pipeline consumes and forwards via SMTP.

Summary

Frequently Asked Questions

What TLS versions does INFINI Console support for SMTP?

INFINI Console supports TLS 1.0, 1.1, 1.2, and 1.3 through the tls_min_version field in the EmailServer model. The system uses the GetTLSVersion function in model/email_server.go to map string constants like "TLS12" to Go's TLS version constants. If no version is specified, the system defaults to TLS 1.2 for secure connections.

Can I use stored credentials instead of plaintext passwords?

Yes. Instead of including an auth object with plaintext credentials in your API request, you can provide a credential_id field referencing a pre-stored BasicAuth credential. The system retrieves the credential using GetBasicAuth and stores the password securely in the internal keystore via keystore.SetValue. The generated pipeline configuration references the password using the placeholder $[[keystore.<server_id>_password]], ensuring credentials never appear in plain text on disk.

Where is the SMTP pipeline configuration stored?

The SMTP pipeline configuration is stored in a YAML file named send_email.yml located in the console's configuration directory, accessible via global.Env().GetConfigDir(). This file is automatically generated or updated by the RefreshEmailServer() function in plugin/api/email/common/pipeline.go whenever you create, update, or toggle the enabled status of an email server through the REST API.

How do I troubleshoot email delivery failures?

Start by using the /api/email/server/_test endpoint to verify SMTP connectivity and authentication without waiting for an alert to trigger. Check that the send_email.yml pipeline file exists in the config directory and contains your server ID in the servers map with the correct keystore password reference. Verify that the email server record has "enabled": true and that your alert rule references the correct server_id. Monitor the email_messages queue to confirm that EmailAction.Execute() in service/alerting/action/email.go is successfully pushing messages when alerts trigger.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →