✉️ onifast-mail

Lightweight Go SMTP Mail Transfer Agent (MTA) with integrated DKIM signing and embedded Webmail explorer.

SMTP MTA DKIM Signing Embedded Webmail

onifast-mail is a custom lightweight Mail Transfer Agent (MTA) and Webmail backend written in Go. It integrates tightly with the Onifast panel ecosystem, using the same user database and SSO token mechanism.

Core Capabilities

Inbound/Outbound MTA
Dedicated SMTP handling with SPF validation, DKIM signing, and intelligent direct outbox resolution.
DKIM Signing
Outgoing mails are signed automatically with server DKIM selectors to boost email deliverability.
Embedded Webmail
Responsive HTML inbox/sent explorer panel, compose tool, and relay configs.

Process Architecture

The daemon runs three parallel concurrent routines under the hood:

  • SMTP Listener — Spawns incoming SMTP handlers listening on ports 25 and 587.
  • HTTP Server — Serves Webmail UI and secure JSON APIs on 127.0.0.1:4031.
  • Outbox Processor — A polling ticker running every 10 seconds to deliver queued messages.

Port Allocations

Port Protocol Description
25 TCP Inbound mail + authenticated outbox relay (standard SMTP)
587 TCP Authenticated SMTP submission port (recommended for clients)
4031 TCP Webmail UI + HTTP API (internal, proxied via panel as /mail)

Inbound Email Processing

1
SMTP Connection
SMTP connection received by the listener daemon on port 25 or 587.
2
Recipient Validation
MAIL FROM checks. RCPT TO validates: if local address (in mail_addresses table), it's accepted. If external and sender is authenticated, it's accepted in the queue. Unauthenticated relay is denied immediately (554).
3
Multipart Extraction
Email body parses, extracting header values and multipart items, preferring HTML content.
4
Storage & Indexing
Raw .eml payload gets stored in the system under /home/<owner>/.onifast/mail/ and indexed in the SQLite table.

Outbound Email Delivery

1
Queued Outbox
Authenticated client sends mail — queued in the SQLite outbox table as pending.
2
Sent Copy Storage
A copy is successfully stored in the sender's sent folder in the SQLite database.
3
Outbox Ticker Polling
The outbox ticker wakes up every 10 seconds, fetching up to 10 pending or failed (attempts < 3) records.
4
Upstream SMTP Relay
SMTP Relay Check: if a dedicated upstream SMTP relay is configured, delivers through it using auth + STARTTLS.
5
Direct MX Resolution
Direct Delivery: if no relay is defined, queries target MX records and resolves target port 25 (IPv4 only).
6
DKIM Header Signing
A cryptographic DKIM signature gets computed and added to the headers if the private keys exist.

SMTP Authentication

Authentication utilizes Onifast panel user credentials — the exact same username and password configurations parsed from /home/root/onifast/users/<username>.json.

Security Recommendation
AllowInsecureAuth is active in default configurations (meaning non-mandatory STARTTLS). For hardened environments, require active TLS handshake negotiations before allowing the AUTH block.

DKIM Signing Configuration

Emails are cryptographically signed if the corresponding private key resides at this location:

Path
/home/root/onifast/certs/<domain>/dkim_private.pem

By default, the DKIM selector is mapped as mail. Add this TXT record to your authoritative DNS zone to verify signatures:

dns txt
mail._domainkey.example.com.  TXT  "v=DKIM1; k=rsa; p=<base64-public-key>"

HTTP JSON API Endpoints

Endpoint Description
GET /api/mail/list Get list of emails within specific folder tags (inbox/sent/trash)
GET /api/mail/addresses List mail addresses associated with the system user session
GET /api/mail/read?id=<n> Fetch single email item details by ID
POST /api/mail/move Move email target items to inbox/sent/trash folders
POST /api/mail/send Send new outbound email payload (queues inside outbox table)
GET /api/mail/config Get or set global outbound SMTP relay properties
GET /api/mail/outbox Examine current delivery states in the queue
GET /api/mail/counts Get count metrics for unread inbox messages
GET /api/mail/dkim Manage and query server-side DKIM key configurations
GET /sso-login?token=<t> Single Sign-On login using a one-time token issued by the panel

SQLite Database Schema

The local database sits inside /home/root/onifast/config/onifast-mail.db:

schema
-- Email Index
emails (id, sender, recipient, subject, body, raw_content, received_at, is_read, folder, file_path)

-- Outbound Queue
outbox (id, sender, recipient, subject, body, status, attempts, last_error, created_at)

-- Domain Link List
mail_addresses (address, domain, local_part, owner, created_at)

-- Outbound SMTP Relay Settings
mail_config (key, value)

PHP Option A: msmtp MTA Wrapper

The simplest setup is mapping the system's sendmail path to msmtp routing on localhost port 25:

bash
# 1. Install packages
sudo apt install msmtp msmtp-mta

# 2. Configure /etc/msmtprc
defaults
auth     off
tls      off
logfile  /var/log/msmtp.log

account  onifast
host     127.0.0.1
port     25
from     webmaster@localhost

account default : onifast

# 3. Add sendmail path to php.ini
sendmail_path = "/usr/bin/msmtp -t"

# 4. Restart PHP-FPM
sudo systemctl restart php8.2-fpm

PHP Option B: PHPMailer via SMTP

For more robust applications, leverage PHPMailer with authentication over port 587:

php
<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';

$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host     = '127.0.0.1';
$mail->SMTPAuth = true;
$mail->Username = 'your_onifast_user';
$mail->Password = 'your_panel_password';
$mail->Port     = 587;

$mail->setFrom('you@yourdomain.com', 'Your App');
$mail->addAddress('recipient@example.com');
$mail->isHTML(true);
$mail->Subject = 'Test Email';
$mail->Body    = '<p>Hello from Onifast!</p>';
$mail->send();

Systemd Service Configuration

systemd
[Unit]
Description=Onifast Mail Server
After=network.target

[Service]
ExecStart=/home/root/go/cmd/onifast-mail/onifast-mail
WorkingDirectory=/home/root/go/cmd/onifast-mail
Restart=always

[Install]
WantedBy=multi-user.target
Copied snippet to clipboard!