Sendmail and 'partly-there' domains
Just recently I had to set up a sendmail server for an office with 7 local users and more roaming users. The current setup had all users checking email via POP3 to the ISP. This is an issue as email sent locally within the office passed over the ADSL connection twice. Sendmail however is quite difficult to work with when it can’t handle the entire domain. As not all users on the domain have an account on the office server, email would bounce back as user unknown - even though a POP3 account existed with the ISP.
I’ll write up a dummy scenario to make this clearer.
- local1 - Checks email on the local server via IMAP. Server downloads email via fetchmail and throws it in the users IMAP mailstore.
- local2 - Same configuration as local1.
- remote1 - This user doesn’t have an account on the local server but gets email via the ISPs POP3 mail account.
All users have the same domain name in their email address. For this example, we’ll use mydomain.com.au.
The issue starts with a couple of common problems.
a) If we put mydomain.com.au in /etc/mail/local-host-names
, then email between local1 and local2 will be handled locally - which is great. The problem though is that mail between local1 and remote1 will bounce with a ‘user unknown’ error.
b) Having a smarthost defined to send email out via the ISPs mail server will also mean that mail between local1 and local2 will also go to the smarthost - essentially uploading it to be downloaded again. This adds delay and also slows things down.
To fix this, we can use the virtusertable
to rewrite the addresses of the email addresses - but by default, sendmail does not run the virtusertable on any addresses of domains it does not own.
We can however modify our sendmail.mc with the following code to tell sendmail to run domains we specify through the virtusertable! The code is as follows:
1
2
3
FEATURE(`virtusertable', `hash -o /etc/mail/virtusertable.db')dnl
LOCAL_CONFIG
F{VirtHost}/etc/mail/virtual-domains
Now we can add the domains we want to run the virtusertable on in /etc/mail/virtual-domains
:
mydomain.com.au
The final step in this solution is to then specify what users we want to rewrite to be local users. This is in /etc/mail/virtusertable
:
1
2
local1@mydomain.com.au local1@localhost
local2@mydomain.com.au local2@localhost
Now when we test these addresses using sendmail -bt
from the server, we see the address translation happen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> /parse local1@mydomain.com.au
Cracked address = $g
Parsing envelope recipient address
canonify input: local1 @ mydomain . com . au
Canonify2 input: local1 < @ mydomain . com . au >
Canonify2 returns: local1 < @ mydomain . com . au . >
canonify returns: local1 < @ mydomain . com . au . >
parse input: local1 < @ mydomain . com . au . >
Parse0 input: local1 < @ mydomain . com . au . >
Parse0 returns: local1 < @ mydomain . com . au . >
ParseLocal input: local1 < @ mydomain . com . au . >
ParseLocal returns: local1 < @ mydomain . com . au . >
Parse1 input: local1 < @ mydomain . com . au . >
Recurse input: local1 @ localhost
canonify input: local1 @ localhost
Canonify2 input: local1 < @ localhost >
Canonify2 returns: local1 < @ intranet . mydomain . com . au . >
canonify returns: local1 < @ intranet . mydomain . com . au . >
parse input: local1 < @ intranet . mydomain . com . au . >
Parse0 input: local1 < @ intranet . mydomain . com . au . >
Parse0 returns: local1 < @ intranet . mydomain . com . au . >
ParseLocal input: local1 < @ intranet . mydomain . com . au . >
ParseLocal returns: local1 < @ intranet . mydomain . com . au . >
Parse1 input: local1 < @ intranet . mydomain . com . au . >
Parse1 returns: $# local $: local1
parse returns: $# local $: local1
Recurse returns: $# local $: local1
Parse1 returns: $# local $: local1
parse returns: $# local $: local1
2 input: local1
2 returns: local1
EnvToL input: local1
EnvToL returns: local1
final input: local1
final returns: local1
mailer local, user local1
Checking against any other email address should show the normal delivery method - either normal MX lookup and delivery, or via a defined smarthost.