I run a shared server for my clients' websites (ubuntu 16.04). I run exim to allow the websites to send out email. It also acts as a mail forwarder and smtp server for my cleints' email software (or just gmail) to allow them to send email from their forwarders.

I currently restrict sending emails for remote users to allow the "from" address only if it matches their smtp username (to stop one client being able to send email as another client). The remote smtp users are not system users, they are just credentials stored in a passwd file. That works great.

The only email sent by local users are from php scripts. Each website runs as a different user. E.g. example.com runs as user "example", test.com runs as user "test". My question is, how can I restrict the local user accounts to only be able to send email from one domain? So that user "test" can send from anyaddress@test.com but can't send from anyaddress@example.com?

Ideally, I would like the test script to look in a file such as conf/env{USER}/allowed-from-domains and test the domain of the From: field to make sure it was in that file.

1 Answer 1


The configuration below makes exim block messages from users example and test when the From header does not contain "@example.com" or "@test.net", respectively.

I use the system filter to inspect the From header line, which is available only after the message is accepted.


system_filter  = /etc/exim/system_filter.conf
qualify_domain = mydomain.net


if $sender_address is "example@$qualify_domain" and not $h_from contains "@example.com"
or $sender_address is    "test@$qualify_domain" and not $h_from contains "@test.net"
  seen finish

test outgoing mail for local user test


mail( "me@gmail.com", "Pass Test", "My message", "From: Me <anything@test.net>" );
mail( "me@gmail.com", "Fail Test", "My message", "From: Me <anything@nottest.net>" );

Web Server Notes

This all assumes php is somehow being invoked by the clients' user account. You'll probably need to reconfigure your webserver to do this. For example, the apache webserver usually runs scripts as user "apache", rather than "test" or "example", which is what we want. Apache would need to be configured with something like mod_privileges.c, or mpm-itk.

If your webserver is configured to use CGI/FastCGI mode, you might be able to do this by adding [HOST=example.com] and [HOST=test.net] sections to php.ini.


  • Thanks for your answer. Could you clarify for me, is if $sender_address is "example@$qualify_domain" referring to for example example@hostname? My php scripts set the from address to something like no-reply@domain.com. Would this rule not match then? Mar 28, 2017 at 22:58
  • I've updated my question with a paragraph which will hopefully make my idea clearer. Mar 28, 2017 at 23:02
  • qualify_domain is whatever you define it to be in exim.conf (qualify_domain = mydomain.net). It's appended to email addresses without a domain. In particular, if I login as fred and run test.php, the mail will appear to come from fred@mydomain.net.
    – Jim U
    Mar 29, 2017 at 0:08
  • PHP is generating sender addresses for the From-header (defined by mail's 3rd parameter) and the envelope sender (which can be defined by 5th paramter's -f argument). Since these can be forged by your users, perhaps you'll want modify php.ini to explicity set the envelope sender per domain using something like [PATH=...] [HOST=...] or mail.force_extra_parameters = -fdefault@test.net. Then maybe you wouldn't need to use qualify_domain and instead use the address you defined in php.ini within system_filter.conf
    – Jim U
    Mar 29, 2017 at 0:18
  • My php setup used php-fpm to run each website as it's own user. You said Since these can be forged by your users.., hence the reason I want to limit the outgoing address in exim. Much safer that way than a fragile php.ini setup. Mar 29, 2017 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.