In a production cPanel/CloudLinux incident, .eml attachments were being blocked globally by Exim system filter rules. The side effect was worse: bounce generation also failed, leaving frozen queue entries.
The right objective was not “allow .eml globally”, but controlled release per domain while preserving global attachment hardening.
1) Production symptoms
Reject message:
This message has been rejected because it has a potentially executable attachment "teste.eml"
Queue/log side effect:
Process failed (1) when writing error message ... (frozen)
2) Root cause
The main blocker was the global system filter:
/etc/cpanel_exim_system_filter- attachment filtering happens before custom ACL logic in many paths
- WHM may expose this list as read-only in some managed scenarios
So ACL-only changes are often insufficient.
3) Solution design
Two-layer approach:
- Global layer (System Filter): remove only
.emlfrom custom filter copy. - Policy layer (ACL): allow
.emlonly for explicitly approved domains.
This keeps dangerous extensions blocked globally while enabling controlled .eml traffic.
4) Implementation steps
4.1 Create persistent custom system filter
cp -p /etc/cpanel_exim_system_filter /etc/cpanel_exim_system_filter_custom
nano /etc/cpanel_exim_system_filter_custom
Remove |eml from relevant patterns.
4.2 Point WHM to custom filter
WHM -> Exim Configuration Manager -> Basic Editor -> FiltersSystem Filter File:
/etc/cpanel_exim_system_filter_custom
4.3 External inbound ACL (acl_smtp_mime)
acl_smtp_mime:
accept sender = :
warn
set acl_m_allowed_recipient = ${lookup{${lc:${domain:$recipients}}}lsearch{/etc/exim/allowed_ANEXOS_domains.txt}{yes}{no}}
deny
condition = ${if or{ \
{and{ {!eq{$acl_m_allowed_recipient}{yes}} {match{$mime_filename}{\N\.eml$\N}} }} \
{match{$mime_filename}{\N\.(ad[ep]|ba[st]|chm|cmd|com|cpl|crt|exe|hlp|hta|in[fs]|isp|jse?|lnk|md[be]|ms[cipt]|pcd|pif|reg|scr|sct|shs|url|vb[se]|ws[fhc])$\N}} \
} {yes}{no}}
message = Attached file '$mime_filename' has disallowed extension.
accept
4.4 Local submit/webmail ACL (acl_not_smtp_mime)
Apply the same strategy, validating sender domain ($sender_address_domain) to enforce local outbound policy.
4.5 Allowed domains list
cat > /etc/exim/allowed_ANEXOS_domains.txt << 'LIST'
client-domain.com
partner-domain.com
LIST
5) Validation flow
exim -bP system_filter
exim -bP acl_smtp_mime
exim -bP acl_not_smtp_mime
/scripts/restartsrv_exim
Delivery checks:
- inbound
.emlto allowed domain => accepted - inbound
.emlto non-allowed domain => denied - outbound from local domain policy respected
- no bounce freeze regression
Queue/log checks:
exim -bp
tail -f /var/log/exim_mainlog
6) Security and maintenance
- Keep antimalware + spam filtering active
- Recheck custom filter path after major cPanel updates
- Version ACL snippets and whitelist in internal repo/change control
Technical conclusion
Allowing .eml safely in Exim/cPanel requires controlled exception design, not global relaxation.
The stable pattern is:
- custom system filter without
.emlhard block - ACL-based domain whitelist
- explicit bounce-safe handling (
accept sender = :)
This preserves platform-wide security while enabling real business workflows that rely on .eml exchange.
This post is licensed under CC BY-NC.
Comments
Join the discussion below.
Comments are not configured yet. Add Cusdis settings in /assets/json/config/blog-comments-config.json.