Seraph for DirectAdmin
This guide is for administrators running DirectAdmin with Exim and Dovecot. Connect the server once, then use the Mail Filter plugin to activate domains and manage their settings. Resellers and domain owners can manage the domains they own.
On this page
"Seraph's operator" refers to the Servada team running the service. For an explanation of the filtering checks and data retention, see How Seraph works.
Beta service. Test with a small group of domains before a wider rollout. Contact support@seraphmail.eu if you need help.
Before you start
You need:
- DirectAdmin with Exim's custom configuration hooks. Run
da build exim_confto add the hooks if your existingexim.confpredates them. - Dovecot 2.3 or 2.4 with Pigeonhole, which provides Sieve filtering.
- PHP with JSON support and either the curl or openssl extension.
- The command-line tools
curl,sha256sumandsudo. The plugin installer installssudoif it is missing. - A valid, publicly trusted TLS certificate for the server's hostname. Seraph verifies this certificate when delivering mail.
- An installation command and enrolment code from Seraph, valid for 24 hours.
The installer checks software prerequisites before making changes. Certificate verification is reported at the end. You can check Pigeonhole and the certificate beforehand using the commands below.
Pigeonhole
Check whether CustomBuild manages Dovecot and enables Pigeonhole:
grep -E '^(dovecot|dovecot_conf|pigeonhole)=' /usr/local/directadmin/custombuild/options.conf
All three values should be yes. If only pigeonhole is no, enable it and rebuild Dovecot
during a maintenance window. The build takes several minutes and restarts Dovecot, requiring
IMAP and POP3 clients to reconnect:
da build set pigeonhole yes
da build dovecot
If dovecot or dovecot_conf is no, CustomBuild does not manage that part of the installation.
Install and configure Pigeonhole using the procedure for your Dovecot installation.
The certificate
Verify the certificate against the server hostname configured in DirectAdmin. A successful
check prints Verify return code: 0 (ok):
n=$(/usr/local/directadmin/directadmin c | sed -n 's/^servername=//p')
openssl s_client -starttls smtp -connect 127.0.0.1:25 -servername "$n" -verify_hostname "$n" -verify_return_error </dev/null 2>&1 | grep "Verify return code"
If verification fails, install a valid certificate for the hostname through DirectAdmin before activating domains. A Let's Encrypt certificate is suitable.
Connect the server
Run the installation command supplied by Seraph as root and enter the enrolment code when prompted. The command validates the code and server before making changes. Both the command's link and the code expire after 24 hours.
Each step reports ok, skip with a reason, or FAIL with corrective instructions. Installation
stops at the first failure. Fix the reported issue before continuing.
- preflight checks the server, before anything changes.
- enrol connects the server to Seraph, with your code.
- setup makes Exim and Dovecot ready for Seraph's verdicts.
- plugin installs Mail Filter in DirectAdmin.
- outbound sends the server's outgoing mail through Seraph, each domain once it is ready.
- report tells Seraph how the server is set up, and check shows it.
The tool is installed in /usr/local/seraph and is normally available as seraph-tool.sh.
With sudo on AlmaLinux, use /usr/local/seraph/seraph-tool.sh if the command is not in sudo's
search path. Running seraph-tool.sh install again updates only components that need changes;
it enrols again only if the server's token is no longer valid.
The supplied installation command runs every step. For later installations, --without plugin
or --without outbound omits that component. See the install reference.
What it changes
- Exim removes Seraph verdict headers from messages that did not arrive from Seraph, including locally submitted mail. This prevents senders from supplying their own filtering verdicts.
- A Dovecot Sieve rule files mail marked junk in top-level
Junkby default, or the folder chosen for that email address in Mail Filter, and stops there: users' own Sieve filters don't run on junk. DirectAdmin's forwarders and vacation messages run in Exim, before it, and still do. - Seraph's delivery hosts go on DirectAdmin's whitelist, so its own blocklist and spam checks skip mail Seraph has already checked.
- A system user,
seraph, without a login, can read the server's token; only root can change it. The plugin runs asseraph, and a small root helper carries out a fixed set of actions for it, through sudo. - Every 5 minutes the server fetches Seraph's delivery hosts, and the domains to lock and route.
- Exim gets a route to the relay, for outgoing mail from the domains Seraph routes.
- Configuration changes are backed up and rolled back if Exim or Dovecot rejects the new
configuration. Actions are recorded in
/usr/local/seraph/actions.log. - Nothing changes for a domain's incoming mail until its MX points at Seraph.
The plugin package is downloaded from Seraph and checked against the supplied SHA-256 checksum. Packages are not yet independently signed, so installation relies on trusting Seraph's download service. The configuration reference lists the affected files.
Spam folders
Seraph's default Junk destination is independent of DirectAdmin's own spam filtering, which may
use INBOX.spam or another folder. In Mail Filter → domain → Settings, choose an email address
and its Spam folder. An existing INBOX.spam is available there if you want both filters to
use it. Apart from the default Junk, only existing folders are offered. The choice changes future
Seraph delivery and enabled spam learning; it does not move old mail or change DirectAdmin's own
rules. An Inbox child such as INBOX.spam can add its unread count to Inbox in mail applications.
Consolidating old folders and DirectAdmin's defaults into Junk is optional. Ask Seraph's operator for the single PHP rollout script and its instructions if you want to do this. It changes server configuration and moves mail: review it and use it at your own risk, with a tested, restorable mailbox backup and a mail-client pilot before continuing across the server. Keep its receipts.
Add a domain
In DirectAdmin, open Mail Filter, pick the domain, and choose Turn on filtering. Administrators, resellers and users can each do this for the domains they own.
The steps
The domain page shows the activation steps and opens the next incomplete step:
- Confirm domain ownership. Publish the
_seraph-claimTXT record shown by the plugin. The plugin can write it when DNS is hosted on this server. For accounts without DNS Control, an administrator can use Update DNS, or enable Update DNS for accounts without DNS Control. For external DNS, copy the displayed record to the DNS provider. - Validate delivery. Seraph checks TLS delivery from each filter node, trusted verdict headers, recipient validation and conflicting domain registrations. A catch-all produces a warning but does not prevent approval.
- Approve the domain. With the TXT record published and required checks passing, Seraph approves the domain automatically within your plan's limit. Some domains require operator or administrator approval, or remain pending until capacity is available; see below.
- Route email through the filter. Update DNS writes the MX record, Seraph's SPF include and the outgoing provider's record in one go, once the filter is ready for the domain. If the domain has an MTA-STS policy, its owner adds Seraph's MX to it first: the plugin shows the new lines, and waits for them. At an outside DNS host, you copy the records.
- Filtering. The domain shows Filtered once every MX record points at Seraph and every filter node has the domain's route to your server in place. A day later, its port 25 locks (below).
Use Check again to request an immediate DNS check. Otherwise, checks run every few minutes.
Many domains at once
Administrators can select domains in the domain list, or use Select all that can be added, then choose Add selected to the filter. The plugin processes them in the background and publishes ownership records where DNS is hosted locally. Approval remains subject to your plan's limit.
To switch MX records automatically, enable Switch local MX records when ready in Server settings before approval. Otherwise, use Update DNS for each domain when ready. A request that expires after 14 days can be submitted again from the domain list.
Requests that wait for you
- Users' and resellers' requests. They're approved like yours while Approve requests from users and resellers automatically is on in Server settings, as it is unless you turn it off. With it off, each waits for you: the domain's Approval step says who asked, with Approve request; on the domain list, Approve selected requests approves several at once.
- Your plan's domain limit. Domains and aliases count. Once it's reached, new domains wait at Approval, and the administrator's page says how many are in use. They're approved by themselves once Seraph raises the limit and there is room; with their ownership record in place, they don't expire meanwhile.
Either way, the domain's owner reads "Waiting for your hosting provider". A domain still waiting after 14 days is dropped, and can be turned on again, unless its ownership record is in place and your plan's limit is reached.
What the checks mean
Users see the checks about their own domain, resellers see theirs too, and the administrator's Delivery check tab shows every one, with its detail and the fix.
| Check | It means | Fixed by |
|---|---|---|
| Domain is yours | The _seraph-claim TXT record is published, or an MX already points at this server |
the domain's owner |
| Domain belongs here | No other server or configuration at Seraph routes the domain | Seraph's operator |
| Domain on this server | DirectAdmin has the domain, with its mail on this server | the server's administrator |
| Your approval | A user's or reseller's request waits for the server's administrator | the server's administrator |
| Room in your plan | Your plan has room for another domain or alias | Seraph (raises the limit) |
| Mail reaches your server | Each of Seraph's filter nodes connects to the server and can deliver over verified TLS | the server's administrator |
| Server trusts the filter | Exim takes verdict headers from Seraph only (seraph-tool.sh setup) |
the server's administrator |
| Unknown addresses | The server refuses addresses that don't exist. A catch-all is a warning: Seraph then takes mail for any address | the domain's owner |
| Email goes through the filter | Every MX record points at Seraph | the domain's owner |
| Secure delivery policy | An MTA-STS policy, if there is one, lists Seraph's MX | the domain's owner |
| Outgoing records | SPF includes Seraph's, and the provider's record is published | the domain's owner |
| Outgoing mail provider | The delivery provider is ready for the domain | Seraph |
| Filter active | Every filter node has the domain's route to the server in place | Seraph |
| Direct delivery | Port 25 takes the domain's mail only from Seraph (and its provider's fallback hosts) | the server's administrator |
DNS records
Where the domain's DNS lives decides who writes the records:
- On this server, owner with DNS Control. The owner's Update DNS writes them.
- On this server, owner without DNS Control. The administrator writes them for the owner, with DirectAdmin's administrator API. Update DNS for accounts without DNS Control in Server settings (on by default) lets the plugin do that on the owner's behalf too. The owner reads that the hosting provider takes care of it.
- Somewhere else. The plugin lists the records, each with what Seraph found. Change the MX last, when the plugin says the domain is ready.
The plugin shows each record's value; these are the ones it asks for:
| Record | When | Why |
|---|---|---|
_seraph-claim.<domain> TXT |
before approval | proves the domain is on this server |
<domain> MX |
once the plugin says the domain is ready | sends incoming mail to Seraph |
<domain> TXT, the SPF include |
with the MX | lets Seraph send the domain's mail |
_mailchannels.<domain> CNAME, into Seraph's zone |
with the MX | lets the delivery provider send it |
| The MTA-STS policy, only if you publish one | before the MX | must list Seraph's MX |
The plugin writes only MX, TXT and CNAME records, only at the domain itself, _mailchannels and
_seraph-claim, and whatever a record points at lies in Seraph's own zones.
Moving from your current filter
- If you can, lower the MX record's TTL a day before: the change, and a change back, then reach other mail servers sooner.
- Your old filter may still deliver for a while: senders with the old MX in their cache, and its own queue. That's why a domain's port 25 locks only 24 hours after its MX moves.
- Locking the whole server at once with
seraph-tool.sh lockinstead? Add--transition "<old filter's addresses>"to take its mail meanwhile, and runlockagain without it some days later.
Server settings
Administrators manage these options in Mail Filter → Server settings. The plugin also uses the term "protection" for filtering.
| Setting | Effect | Default |
|---|---|---|
| Automatically add new domains | Registers new DirectAdmin domains with Seraph. | Off |
| Automatically add domain aliases | Adds new aliases of a filtered domain with its settings. | Off |
| Switch local MX records when ready | Switches locally hosted, authoritative MX records after an automatically or bulk-added domain is ready. | Off |
| Approve requests from users and resellers automatically | Allows requests to proceed without administrator approval. Other approval checks still apply. | On |
| Remove protection when a domain is deleted | Removes a deleted DirectAdmin domain from filtering. Its route remains for 48 hours; cleanup waits at least 96 hours. DNS is unchanged. | Off |
| Update DNS for accounts without DNS Control | Allows the plugin to write records using DirectAdmin's administrator API. | On |
Starting defaults for new domains sets the initial filtering preferences. A new domain uses its DirectAdmin account's language when that language is English or Dutch.
Filtering settings
Set filtering preferences for a domain, then override them for individual mailboxes where needed. New domains inherit the server's starting defaults.
| Setting | Purpose |
|---|---|
| Filter strength | Relaxed, normal or strict sensitivity. The standard default is normal. |
| Where spam goes | Deliver to the spam folder, hold in quarantine for 30 days, or deliver to Inbox. The standard default is the spam folder. |
| Learn from corrections | Enable a personal model trained on mailbox corrections. Off by default. |
| Primary language | English or Dutch for filtering reasons and optional warnings. |
| Sender authentication (DMARC) | Observe, reject, junk or disable enforcement for messages failing a DMARC reject policy. The standard default is observe. |
| Unsolicited sales emails / Newsletters | Choose whether to deliver these categories or send them to spam. Standard defaults are spam for sales emails and delivery for newsletters. |
| Expected mail | Identify expected categories, such as invoices, security alerts, orders or government mail. These categories alone do not make a message unwanted. |
| About the recipients | Describe the recipients in up to 255 characters to provide context for filtering. |
| Allowed and blocked senders | Maintain up to 1,000 entries in each list, using addresses or domains. |
Optional subject prefixes and visible message warnings are disabled by default and must be enabled explicitly. These can help identify unwanted mail when you choose delivery to Inbox. See spam folders for per-address filing choices.
What your users see
- Every message Seraph delivers carries its verdict in
X-Seraph-headers, among them a reason in plain words. How Seraph works explains them. - Junk is in the spam folder, or in the plugin's Quarantine tab when the domain or mailbox uses quarantine. Three days before a quarantined message is deleted, its recipient gets a notice.
- Malware and known scams never arrive: the sender is told they were refused.
Outgoing mail
install turns outgoing mail on for the server. A domain's mail goes through Seraph once its SPF
include and provider record are seen (step 4 above writes them); until then, it leaves as before.
- A domain's Outgoing tab shows the last 30 days' counts, mail held for review, mailboxes that can't send right now, and the bounces of the last week.
- Delete a held message, or ask Seraph to send it. Only Seraph's operator releases held mail, so a stolen password can't release its own spam.
- A mailbox that can't send went over its sending rate. If its user didn't send that much, change the mailbox's password.
seraph-tool.sh outbound statusshows how each sender leaves: through Seraph, or as before.- To stop: in Server settings, Outgoing mail, Turn off (administrators only); or
seraph-tool.sh outbound off. The server then sends as it did before.
Daily reports summarize your domains and senders, with items requiring attention listed first. Two CSV attachments provide the sender and domain statistics. To change recipients or stop reports, contact support@seraphmail.eu. See outbound in the reference.
The port-25 lock
A day after a domain's MX points at Seraph alone, your server's port 25 takes that domain's mail only from Seraph; How Seraph works says why and what stays open. The administrator's Delivery check tab shows each domain's lock: locked, locking, or open, and why.
seraph-tool.sh locklocks every domain on the server at once, without waiting a day. It refuses while any domain's MX points elsewhere, and names those domains. With--transition "<addresses>"it also takes mail from your old filter's addresses while DNS caches expire; some days later, runlockagain without it.unlocklifts the server-wide lock; the domains Seraph lists stay locked.seraph-tool.sh unlock --domain example.comopens one domain until the next refresh puts it back: for emergencies. While the whole server is locked, it opens nothing. Seraph's operator can keep a domain open for longer.- Stopping filtering in the plugin takes the domain off the list as it puts the old MX back.
See the port-25 lock in the reference.
Learning
Personal learning and shared sample collection are both disabled by default. They use message copies for different purposes; How Seraph works explains each feature.
Personal learning
In a domain's filtering settings, turn on Learn from corrections for the domain (the default for its mailboxes) or for one mailbox. The Learning tab shows progress. A model becomes active after 20 usable spam corrections and 20 usable non-spam corrections. Start over deletes the mailbox's corrections and model.
Samples for Seraph
Samples contain personal data. Collection can include private correspondence and attachments, including messages moved by mistake or automatically by a mail application. Root and the domain owner can read collected samples. They remain on your server until exported or deleted, with a maximum retention of 30 days for unexported samples. Enable collection only where your agreement with users permits it, and inform them first. Non-spam samples require a separate opt-in.
Keep a copy of mail users move into the spam folder, and with --ham yes, of mail they move out of
it:
seraph-tool.sh learn on example.com
seraph-tool.sh learn on example.com --ham yes
To submit samples for manual review, export them into an encrypted file that only Seraph can open. Export removes the collected originals from the server:
seraph-tool.sh learn export
The command prints the export's path under /usr/local/seraph. Email the encrypted file to
support@seraphmail.eu, then delete your copy. Exported files are not covered by the automatic
30-day sample cleanup.
learn off example.com stops it, and deletes the samples not yet sent. In the plugin, this is
"Help improve filtering for everyone" in the Learning tab. See learn
in the reference.
Troubleshooting and support
- The command says its link expired or was used. It works once, within 24 hours, and stops
after five wrong codes: ask support@seraphmail.eu for a new one. Already connected? Run
seraph-tool.sh install. - A step failed. Its
FAILline says what to do: fix that, then runseraph-tool.sh installagain. - "Mail reaches your server" fails. Check the server's certificate (see Before you start), that port 25 is open to Seraph, and the Delivery check tab for the detail.
- A sender gets "try again later" (451). Either the domain is locked and the sender used the old MX; or one mailbox got more than a burst of 200 messages, refilled at 60 a minute; or your server is down and Seraph couldn't check that the address exists. The sender tries again by itself.
- A new mailbox gets no mail yet. Seraph remembers "no such address" for 15 minutes.
- A message over 50 MB is refused.
- Good mail in spam. Read its
X-Seraph-Reason. Allow the sender, lower the filter strength, or move the message out of spam (with personal learning on, its mailbox learns from that). - Spam in the inbox. Move it into spam, or block the sender.
- A mailbox can't send. See Outgoing mail.
Still stuck? Write to support@seraphmail.eu, with the message's X-Seraph-ID where
there is one.
Updating
Seraph serves the current seraph-tool.sh and Mail Filter plugin; this site describes
seraph-tool.sh 12 and the plugin 0.2.18. To update both, as root:
seraph-tool.sh plugin update
seraph-tool.sh install
The first command downloads the current plugin and its receiver tool, verifying the supplied SHA-256 checksum. The second applies any required Exim, Dovecot and outgoing-mail configuration updates. Components that are already current are left unchanged.
Stop filtering a domain
In the plugin, the domain's Settings tab ends with Stop filtering this domain:
- Point your email back to its previous server. Restore previous MX records where the plugin changed the zone on this server itself; otherwise the records to copy, or to ask your hosting provider for.
- Wait for DNS caches. As long as the zone's MX TTL, where the plugin knows it, or about an hour.
- Stop filtering. Type the domain's name, and confirm the wait is over.
Seraph won't let a domain go while its MX still points at Seraph: its mail would have nowhere to go. Seraph's SPF include and provider record stay for seven days, for mail already on its way; then the plugin removes them where it wrote them, and at an outside DNS host you take them out.
Remove Seraph from the server
First stop filtering every domain in the plugin (Stop filtering a domain):
that points its MX back and, seven days later, removes Seraph's SPF include and provider record.
Do this before remove, which takes out the plugin's root helper. Then:
seraph-tool.sh remove
It takes out what install set up in Exim and Dovecot, outgoing mail, the lock, learning, the
plugin's root helper and the seraph user, and deletes the samples you haven't sent. The plugin's
pages stay in DirectAdmin until you remove Mail Filter in the Plugin Manager. Backups, the log and
earlier exports stay in /usr/local/seraph; remove --purge deletes those too, and the tool
itself. Then tell support@seraphmail.eu, so Seraph revokes the server's access. See
remove in the reference.