1. How Shield works
The domain's MX points to Lua. Messages go through antispam and antivirus and are delivered to your server. The mailboxes, users and data stay with you.
- Inbound. The message reaches Lua's MX (
mx.secure.edgium-dns.net). - Analysis. Sender reputation, SPF, DKIM, DMARC, blocklists, content, links and attachments. Each message gets a score.
- Delivery. The message goes on to your server over SMTP, with the result recorded in the headers.
What happens to each message
| Score | What Lua does |
|---|---|
| Below 6 | Normal delivery. |
| From 6 to 24.9 | Delivered with the header X-Edgium-Spam: Yes. A rule on your server moves the message to the spam folder (chapter 4). |
| 25 or more | Rejected at the door. The sender gets a bounce with the reason, so nothing disappears without notice. |
Headers that Lua adds and that help with diagnosis:
X-Edgium-Spam: Yes: the message was classified as spam.X-Spamd-Bar: the score as bars (+++++++). The more bars, the more suspicious.Authentication-ResultsandARC-Authentication-Resultsfrommx.secure.edgium-dns.net: the SPF, DKIM and DMARC result seen at the door.
2. Before you start
- The name or IP of the server that receives the email (port 25), reachable from the internet. Lua registers this destination for the domain.
- The server accepts TLS on port 25 (recommended).
- The server rejects nonexistent recipients right at send time (
550onRCPT TO), instead of accepting and bouncing later. This avoids bounces to forged senders. (With a split domain, Lua is the one that rejects: see chapter 5.) - Access to the domain's DNS and administrator access to the server.
Recommended order
- Ask Lua to register the domain with your server as the destination.
- Allow Lua's IPs in the server's firewall and antispam (chapter 3).
- Create the rule that moves tagged spam (chapter 4).
- If the domain has accounts outside your server, adjust the server (chapter 5).
- Change the MX (chapter 6) and run the tests (chapter 8).
3. Allowing Lua's IPs
All messages start reaching your server from the same few Lua IPs. A server that limits connections per IP sees this as abnormal volume and may block delivery.
The official list of IPs is at resources.edgium.net/ips_mx.txt. Always use this list, which is updated when an IP changes.
- Firewall: allow port 25 for these IPs.
- fail2ban, per-IP limits and greylisting: add these IPs as an exception.
- Server antispam: treat these IPs as a trusted gateway, so it does not re-evaluate SPF and blocklists against Lua's IP. In SpamAssassin (Zimbra, cPanel), use
trusted_networks. In Exchange, Lua's receive connector.
Never add Lua's IPs as a network authorized to send (mynetworks in Postfix and Zimbra, anonymous relay in Exchange). That turns the server into an open relay for anyone who passes through Lua. Trusted for spam analysis, yes. Authorized to use the server for sending, no.
After activation: accept only from Lua
Even with the MX changed, spammers keep trying to deliver directly to the server's old IP. Once activation is stable, accept connections on port 25 only from Lua's IPs. That way all outside email goes through the filter. Users keep sending normally through the authenticated submission ports (587 and 465).
4. Moving tagged spam
Lua's filter scores each message. Between 6 and 24.9 points it is not rejected: it goes on to your server with the header X-Edgium-Spam: Yes, and your server decides what to do with it. Your server has to recognize this header and treat the message as spam: if X-Edgium-Spam is Yes, it goes to the spam folder (Junk). On Zimbra and Amavis, the way is to add spam points to the message; on other servers, a filter rule.
To see the header on a real message, open the message in the email client and use View source (in Outlook, Properties; in Zimbra, Show original). The line X-Edgium-Spam: Yes appears next to the Received headers. Unmarked messages do not have the line, or have No.
The rule applies to all mailboxes on the server, and the header can be forged by anyone sending directly to your IP. That is why it is worth following the section After activation: accept only from Lua: with port 25 open only to Lua's IPs, nobody outside can put X-Edgium-Spam: Yes on a message to disrupt a mailbox or remove the tag from another.
To trigger the tag and confirm the rule works, follow chapter 8, Activation tests.
Zimbra 8.5 or later
In Zimbra, Amavis calls SpamAssassin, which adds up the points from all rules. It then compares the total with two cutoffs: above the tagging cutoff (tag) the message goes to Junk; above the discard cutoff (kill) it is discarded. The rule below adds points when Lua's header comes as Yes.
- Sign in as the
zimbrauser:su - zimbra. - Edit
/opt/zimbra/conf/salocal.cf.inand add this at the top of the file:
# EDGIUM ANTI SPAM RULES
header EDGIUM_ANTISPAM X-Edgium-Spam =~ /^Yes$/
describe EDGIUM_ANTISPAM Anti Spam Service Score reported as SPAM
score EDGIUM_ANTISPAM 7
- Restart Amavis:
zmamavisdctl restart. - Check that the rule made it into
/opt/zimbra/data/spamassassin/localrules/salocal.cf.
The score matters because of the cutoffs. Zimbra stores both as percentages, with 20 SpamAssassin points equal to 100%. To see yours, as the zimbra user:
zmprov gacf zimbraSpamTagPercent zimbraSpamKillPercent
With the factory values, zimbraSpamTagPercent is 33% (6.6 points) and zimbraSpamKillPercent is 75% (15 points). The rule's score must be greater than or equal to the tagging cutoff so that Lua's message alone already goes to Junk. That is why the example uses 7: with 6 points, the rule alone does not reach 6.6 and the message would only go to Junk if some other SpamAssassin rule also scored. If your cutoff is different, adjust the score to a value above it. On a tagged message, Zimbra's X-Spam-Status shows the rule in the list of tests, something like EDGIUM_ANTISPAM=7.
Careful with discarding. In Zimbra, a message above the discard cutoff (15 points, by default) is not delivered and does not go to Junk. Lua's rule adds 7 to the points SpamAssassin already gave: if the message already had 8 or more, it goes over 15 and is discarded instead of going to Junk. For it to go to Junk instead of vanishing, change the final destination of spam to delivery (zmprov mcf zimbraAmavisFinalSpamDestiny D_PASS; the default is D_DISCARD) or raise zimbraSpamKillPercent. Decide carefully, because the same change applies to all of the server's spam, not just what comes from Lua.
Amavis with SpamAssassin on your own server *
If your Postfix calls Amavis and SpamAssassin without Zimbra, the rule is the same, in SpamAssassin's local.cf (usually /etc/mail/spamassassin/local.cf; confirm the path on your distribution):
header EDGIUM_ANTISPAM X-Edgium-Spam =~ /^Yes$/
describe EDGIUM_ANTISPAM Anti Spam Service Score reported as SPAM
score EDGIUM_ANTISPAM 7
- Validate the syntax:
spamassassin --lint. No output means it is correct. - Check Amavis's cutoffs in
amavisd.conf(or in your distribution'sconf.dfiles):$sa_tag2_level_defltis the score from which the message getsX-Spam-Flag: YESandX-Spam-Status: Yes;$sa_kill_level_defltis the score from which it is blocked, and$final_spam_destinysets the destination (by default,D_DISCARD). - The rule's score (7 in the example) should be above
$sa_tag2_level_defltand below$sa_kill_level_deflt. - Restart Amavis (
systemctl restart amavisdoramavis, depending on the distribution).
Amavis only tags the message. For it to go to the Junk folder, the mailbox server has to act on X-Spam-Flag, for example with the Sieve in the next section.
Exchange Server (on-premises) *
- In the Exchange admin center, open Mail flow → Rules and create a new rule.
- Condition: a message header includes: header
X-Edgium-Spam, valueYes. - Action: modify the message properties → set the spam confidence level (SCL) to
6or more. Messages go to Outlook's Junk Email folder.
Postfix with Dovecot (Sieve)
Dovecot delivers the message through LMTP (or LDA) and runs Sieve on delivery. A global script, run before each user's script, moves the tagged message to the spam folder. The examples below are for Dovecot 2.3 with Pigeonhole.
- Create the global scripts folder and the script:
require ["fileinto", "mailbox"];
# Lua Shield: the front-door filter tagged the message as spam.
if header :is "X-Edgium-Spam" "Yes" {
fileinto :create "Junk";
stop;
}
:create creates the folder if it does not exist yet in the user's mailbox. The name Junk is what the IMAP client sees: if your spam folder has another name (Spam, INBOX.Junk with a namespace prefix), use that name.
- Turn on the Sieve plugin at delivery and point it to the script (usually in
conf.d/20-lmtp.conf,15-lda.confand90-sieve.conf):
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
protocol lda {
mail_plugins = $mail_plugins sieve
}
plugin {
sieve_before = /etc/dovecot/sieve-before
}
If sieve_before points to a folder, all .sieve files in it run, in name order. If it points to a file, only that file runs. If you already use mail_plugins with other plugins in the sections, just add sieve to the list.
- Make the folder and the script readable by the Dovecot user (
chmod 755on the folder,chmod 644on the script), compile and reload:
sievec /etc/dovecot/sieve-before/10-edgium-spam.sieve
doveadm reload
- Test the script without delivering anything, with a message saved to a file that has the line
X-Edgium-Spam: Yes:
sieve-test /etc/dovecot/sieve-before/10-edgium-spam.sieve mensagem-marcada.eml
The expected output is store message in folder: Junk. With a message without the tag, the output is store message in folder: INBOX.
The sieve_before applies to all accounts on the server, not just one. Before turning it on, confirm that all the server's mailboxes go through Lua, or create the rule in the script of a single account (in the user's sieve). Because the script uses stop, the user's personal script does not run for the tagged message. If a sieve_before already exists on the server (for example, for antivirus), add the rule with a name that sorts after it, instead of replacing the path.
In Dovecot 2.4 the configuration format changed. The same rule looks like this:
protocol lmtp {
mail_plugins {
sieve = yes
}
}
sieve_script edgium-spam {
type = before
path = /etc/dovecot/sieve-before/10-edgium-spam.sieve
}
The Sieve script and sievec are the same.
Postfix without Dovecot (header_checks) *
Postfix's header_checks acts on the header, but does not move the message to a folder: the mailbox server does that. It is useful for rejecting, discarding, holding or redirecting the tagged message. In main.cf:
header_checks = regexp:/etc/postfix/header_checks
/^X-Edgium-Spam:[[:space:]]*Yes[[:space:]]*$/ REDIRECT quarentena@yourcompany.com
Test the pattern without touching the server: postmap -fq "X-Edgium-Spam: Yes" regexp:/etc/postfix/header_checks shows the action when it matches and shows nothing when it does not. After editing, run postfix reload. The actions that make sense here, according to the Postfix manual:
| Action | What it does | When to use |
|---|---|---|
REDIRECT usuario@dominio | Delivers the message to another address, in place of the recipients. | The safest: the spam stays in a quarantine mailbox, and someone reviews it. Nothing is lost. |
HOLD | Puts the message in Postfix's hold queue until someone releases or deletes it. | Review with postsuper. The queue grows, so keep an eye on it. |
PREPEND text | Adds a header line and continues the analysis. | For another program to decide later, for example a mailbox filter. |
DISCARD | Tells the sender it was delivered and deletes the message silently. | Only if you accept losing messages, including legitimate ones that Lua tagged by mistake. |
REJECT | Rejects the message during the SMTP conversation. | Avoid: the one talking to your server is Lua's MX, which has already accepted the message. Lua then has to generate a bounce to the sender, which with spam is usually a forged address (backscatter). Talk to our team before using it. |
If you need the message in the spam folder, use the Sieve from the previous section or the filter of the mailbox server you use. header_checks does not replace that.
Exim without cPanel: use the filter of the mailbox server itself or of the panel you use to file messages into a folder. Exim's documentation on the system filter was not checked for this case, so we do not give an example.
cPanel / WHM *
- In Global Email Filters (in cPanel, per account or for all accounts), create a filter.
- Rule: Any Header contains
X-Edgium-Spam: Yes. - Action: Deliver to Folder, folder
Junk(orspam, depending on the server).
After saving, cPanel itself has Test Filter to check with a sample message.
Other servers
Any server that filters by header works. The condition is X-Edgium-Spam equal to Yes, and the action is to move to the spam folder. If your server has its own filter, use it.
* Example configuration. Validate it with your provider. If it does not work, talk to the provider's support or to our team.
5. Domain shared with other accounts
This only applies when not all of the domain's accounts are on your server: part of the team on lua.email, Microsoft 365 or another provider. If all mailboxes are on your server, skip this chapter.
In that case, your server cannot treat as nonexistent an address that is simply not on it. In the domain configuration, accounts that do not exist on your server must go to the external MX (mx.secure.edgium-dns.net), instead of being bounced. Lua delivers each one to the right place and rejects what exists nowhere.
Lua's MX always receives first. The source of the account list is Lua's panel: it knows which addresses are on your server, which are on lua.email and which are on another provider. For cPanel, Email Routing → Remote Mail Exchanger plays this role; see option B in cPanel on Bridge.
Exchange Server (on-premises)
- In Mail flow → Accepted domains, change the domain from Authoritative to Internal relay.
- In Mail flow → Send connectors, create a connector for the address space
yourcompany.com, delivering through the smart hostmx.secure.edgium-dns.net.
Zimbra
Zimbra calls this a split domain. As the zimbra user:
zmprov md yourcompany.com zimbraMailCatchAllAddress @yourcompany.com
zmprov md yourcompany.com zimbraMailCatchAllForwardingAddress @yourcompany.com
zmprov md yourcompany.com zimbraMailTransport smtp:mx.secure.edgium-dns.net:25
Other servers
Look for shared domain, internal relay or split delivery: an address that does not exist locally is passed on to mx.secure.edgium-dns.net. If in doubt, talk to Lua before changing anything.
With a split domain, your server stops rejecting nonexistent addresses on its own, because it now passes them on. Lua is the one that rejects, since it knows all of the domain's accounts. So register with Lua all the accounts that are outside your server before making this change. Setting up accounts on other providers follows the lua Bridge documentation.
6. MX, SPF, DKIM and DMARC
MX
Testing period (first 30 days): publish Lua's MX with the same priority and the same TTL as the current MX, or with a better priority than it (lower number) and the same TTL. If something goes wrong, the old MX keeps receiving.
After the testing period: leave only Lua's MX.
yourcompany.com. 3600 IN MX 5 mx.secure.edgium-dns.net.
While the old MX is published, some messages arrive without going through the filter. That is why the testing period has a deadline, and after it you should accept only from Lua.
SPF
SPF lists who sends email for the domain. With Shield, the one sending is still your server, because Shield handles inbound. So:
- Keep in SPF the IP (or the
include) of your server and of the other systems that send for the domain. - Add
include:spf.edgium-dns.net. It is required if the domain also has accounts on lua.email or sends through Lua's servers, and recommended in other cases, to cover messages from the domain itself that Lua passes on to your server.
yourcompany.com. IN TXT "v=spf1 ip4:IP-DO-SEU-SERVIDOR include:spf.edgium-dns.net -all"
Remember the limit of 10 DNS lookups counting all includes, and keep a single SPF record.
DKIM
Set up DKIM signing on your server (OpenDKIM on Postfix, native DKIM on Zimbra, signing by Exchange or by an outbound gateway) and publish the key in DNS. DKIM is what keeps DMARC passing when a company message is forwarded.
DMARC
Recommended. It protects the domain against anyone trying to send using the company's name. Start by observing and tighten after SPF and DKIM have been checked:
_dmarc.yourcompany.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourcompany.com"
_dmarc.yourcompany.com. IN TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc@yourcompany.com"
For the rua address, create a dedicated mailbox (for example, dmarc@ or abuse@) and forward it to whoever administers the environment. If you do not want to receive reports, remove the rua.
7. Training the filter
You teach the filter yourself, in the panel, without opening a ticket. When a message is classified wrongly, send it as an example: the filter learns from it and makes better decisions on similar messages later. Our team stays by your side whenever you need it.
How to submit a message
- In the panel, open the domain and go to Delivery → Train the filter.
- Under This message is, choose SPAM (scam, unwanted advertising) or TRUSTED (a legitimate message that was flagged).
- Under How to submit, choose .eml file and select the file, or Paste the message and paste the full message, with headers and body.
- If the message has no recipient from the domain, enter in Address that received the message which mailbox received it.
- Click Send to the filter and confirm in the window that opens.
The result
The screen tells you what happened:
- Done: the filter learned this message as SPAM (or as TRUSTED): trained.
- All good: the filter had already learned or already classifies messages like this: this is also a success. The message was already taught, so there is no need to send it again.
- Could not train right now. Try again later: the filter is unavailable at the moment. Try again shortly; if it continues, contact support.
- The other notices say what to fix: an empty message or one that does not look like an email, a recipient outside the domain, hourly limit reached, or a repeated submission.
What was trained
The What was trained button, next to Send to the filter, lists each submission: date, who sent it, domain, type, sender and subject of the message, size, and result. You can filter by date, user, type, result, and domain. The message content does not appear: only the sender and the subject are kept, truncated.
How to get the .eml
- Google account (Workspace or personal): open the message, then ⋮ → Show original → Download original message.
- Outlook on the web and new Outlook: open the message and use the ⋯ menu to download or save it as an .eml file.
- Outlook for Windows (classic): dragging the message to a folder creates an .msg file, which the panel does not accept. Open the message in Outlook on the web and download the .eml from there.
- Thunderbird: File → Save As → File saves the .eml.
- Apple Mail: File → Save As, in the Raw Message Source format.
- lua.email webmail: in the message's More menu, download the .eml file or open the source and copy everything.
Prefer the .eml: it carries the whole message, with the headers the filter uses. If you paste, copy everything, from the first header (From:, Received:) to the end of the body.
Good to know
- The filter learns per destination address, not for the whole domain. The message teaches the filter of the mailbox that received it: the address that appears in the headers (
To,Cc,Delivered-To) or the one you enter in the field. To teach more than one mailbox, send the message once for each address. - Only addresses from the domain itself (and its alias domains) are accepted.
- One message at a time, up to 10 MB. A file with several messages (mbox) is rejected.
- There is a limit on submissions per hour, per person and per domain. The same message sent again right after is rejected, because it does not need to be repeated.
- The Read-only and Helpdesk profiles cannot train: they see the screen and the history, without the form.
- The screen exists for domains with an active Shield or Bridge license.
- The message goes through the filter and is not stored in the panel. Only the record that the submission was made remains.
If your account does not have the screen (read-only or helpdesk profile, or a domain without Shield or Bridge), ask whoever administers the domain, or send the original message as an .eml through support.
Training teaches the filter to decide on the next similar messages. For a sender that must always get through, add it to the allowed list, under Delivery → Access lists.
8. Activation tests
| Test | What to check |
|---|---|
| Send from an external account to an account on the domain | It arrived. The header has a Received from mx.secure.edgium-dns.net and Lua's Authentication-Results. |
| Send to an address that does not exist on the domain | The bounce arrives quickly, with 550 from your server. |
Tagged message (X-Edgium-Spam: Yes) | It went to the spam folder. If there is not a real one yet, ask Lua for a tagged test message. |
| Send from the domain to the outside | spf=pass, dkim=pass and dmarc=pass in the recipient's header. |
9. Common problems
Messages do not arrive or arrive late
The server's firewall, fail2ban, greylisting or a per-IP limit is holding back Lua's connections. Allow the IPs from the official list in those places.
Tagged spam shows up in the inbox
The rule from chapter 4 is not active or uses a different header name. Check in the full header whether the message has X-Edgium-Spam: Yes.
Spam arrives without going through Lua
The header has no Received from mx.secure.edgium-dns.net. The sender delivered directly to the server, through the old MX or the IP. Remove the old MX and accept port 25 only from Lua.
A legitimate message was marked as spam
Send the message as TRUSTED, as in the training chapter. If the sender always needs to get through, add them to the allowed senders list in the panel (Delivery → Access lists).
The server is bouncing messages to senders who did not send anything
The server accepts any recipient and only bounces afterward. Configure it to reject nonexistent recipients right at RCPT TO (chapter 2).
10. Registering the Shield domain in the panel
A Shield domain is registered in the panel a little differently from a domain with mailboxes: you choose the type, enter your server's destination and say how many licenses to link to the domain. The rest of the path, including domain verification by TXT, is the same as the standard onboarding.
Before registering
- The customer needs an active Shield license with a seat available. Without a license, the panel shows the usual form, only for a domain with mailboxes.
- The customer's administrator does the registering. Read-only and support profiles see the numbers but cannot register.
- The server that will receive the email should already be ready for chapters 3 and 4. Without the panel, ask Lua to register it, as described in chapter 2.
Step by step
- In Domains, click Add domain and type the domain.
- In Domain type, choose Shield: antispam for my server. The other option, Domain with email mailboxes, remains the default.
- In Shield licenses for this domain, say how many licenses to link (at least 1). The link is for billing and usage checks: it does not limit or block email. The sum of the links across all your Shield domains cannot exceed what was subscribed, and the panel rejects anything over that. You can change the quantity later, in Edit domain.
- Enter the destination server (IP or name) and the port (blank means 25). The panel only accepts a server outside Lua: internal IPs,
localhostand Lua addresses are rejected. - Click Continue, publish the TXT record in the domain's DNS and use Check now. The deadline is 72 hours. When the TXT appears, the domain becomes active as Shield.
Fixed destination or the name's MX
In one sentence: the fixed destination always delivers to the IP or name you entered, and use this name's MX makes Lua look up the name's MX and try the next server when one is down, in order of preference. The i icon next to the option repeats this explanation on screen.
- Fixed destination (default). Use it when the server has a single IP or name. If the name has more than one IP (two A records, such as two internet links), Lua tries the name's addresses until one responds.
- Use this name's MX. Use it when you have more than one inbound server or link and want to control the order. The name must have an MX record, and each MX server goes through the same check as the fixed destination.
Example with a name that points to itself and two addresses (two links):
entrada.yourcompany.com. 3600 IN MX 5 entrada.yourcompany.com.
entrada.yourcompany.com. 3600 IN A 203.0.113.10
entrada.yourcompany.com. 3600 IN A 198.51.100.20
Example with two servers and different weights. Lua tries the one with preference 5 and, if it does not respond, the one with preference 10:
entrada.yourcompany.com. 3600 IN MX 5 principal.yourcompany.com.
entrada.yourcompany.com. 3600 IN MX 10 reserva.yourcompany.com.
principal.yourcompany.com. 3600 IN A 203.0.113.10
reserva.yourcompany.com. 3600 IN A 198.51.100.20
To check before registering:
host -t mx entrada.yourcompany.com
dig +short MX entrada.yourcompany.com
dig +short A principal.yourcompany.com
Each destination address must accept Lua's IPs (the list in chapter 3), both the primary and the backup server. The destination name is only the place where Lua delivers: the email domain's MX still points to Lua (chapter 6), and the panel rejects a destination whose address belongs to Lua.
Domain with mailboxes and Shield
| What changes | Domain with mailboxes | Shield domain |
|---|---|---|
| Where the mailboxes are | At Lua, with webmail, calendar and Colabora. | On your server. The panel does not create mailboxes, aliases or DKIM for the domain. |
| License | One per mailbox. | Shield licenses linked to the domain, in the quantity you choose (minimum 1). |
| Delivery | To the mailbox, on Lua's servers. | To the server and port you registered, after the filter. |
| Domain MX | Servers listed in the panel. | Shield MX (chapter 6). |
| IPs and spam rule | There is nothing to configure on your server. | Allow Lua's IPs (chapter 3) and create the header rule (chapter 4). |
| Domain verification | TXT record in DNS. | TXT record in DNS, the same. |
After registering
The Shield domain page shows the linked licenses, the accounts in the last 30 days (each address that received email accepted by your server counts once; email rejected or bounced because of a nonexistent account does not count) and the contract's available licenses, with a shortcut to subscribe to more. The account count appears a few moments after the screen opens, and View by day shows a chart with each day's accounts. If more accounts are receiving email than there are linked licenses, the panel warns you to adjust the quantity. Customers with a legacy license see "Legacy license" in place of the available ones, with no purchase offer.
When no license is available
If all Shield licenses are already linked, the Shield option is disabled, with a notice and a shortcut to subscribe to more licenses. The form continues as Domain with email mailboxes, and you register the domain normally.
Still need help?
Contact support. A person on Lua support answers, based in Brazil, in Portuguese.
To speed things up, send the domain, the server you use (Exchange, Zimbra, cPanel, Postfix) and the full header of a message with a problem.