How to setup a Postfix mailserver on Ubuntu LTS to send/receive emails for a web application.
Created: Fri 03 June 2011 / Last updated: Wed 04 March 2015
At the moment, the trend is to externalize the management of a company mail server in the cloud and pay a per email fee. It is good if you do not want to worry about the security implications of managing a mail server, but they are usually pretty expensive for something which can be very easily managed in house. It is only when you start to send really a lot of emails that you need to have a very robust infrastructure and in this case, your system has most likely already been growing with you.
Setting up your own mail server with SMTP authentication, DKIM signing and SPF records at the DNS level is relatively easy, this is why here at Céondo we have setup a dedicated mail server to do just that.
This mail server is setup to serve web applications to send and receive emails and email clients to send emails. No IMAP servers are provided, we use external providers to manage our mailboxes.
The server is running Ubuntu LTS, Trusty Tahr.
192.168.0.0/16
without authentication.As we have a very limited number of clients, the login/password can be stored as a file on the mail server. No need to setup a database server for a maximum of 5 clients.
The base server is a Ubuntu LTS Trusty Tahr server. Just use your provider of choice to run the base server. It can run as a virtual machine like KVM or in the cloud. If you are running in the cloud, you will have to pay attention to the open ports.
First some utility tools are installed after a full upgrade.
# apt-get update && apt-get dist-upgrade
# apt-get install sysstat screen curl rsync dialog wget unzip telnet
Then, the mail server related packages are installed.
# apt-get install postfix
When the type of mail server is asked, Internet Site
is selected.
When asking for the email address, I used support@my-domain.com
.
For the signing of the outgoing email, OpenDKIM is used:
# apt-get install opendkim opendkim-tools
For the authenticated SMTP connection, SASL2 is used:
# apt-get install libsasl2-modules sasl2-bin
Now, you can already test a connection to the mail server:
$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 nsbis1-1 ESMTP Postfix (Ubuntu)
EHLO blah
250-nsbis1-1
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Connection closed by foreign host.
What you see here is nsbis1-1
for the hostname. This is just the
local hostname and not a fully qualified hostname. This is easy to
change it. We need to change the banner and reload the server:
# postconf -e 'smtpd_banner = nsbis1-1.ceondo.com ESMTP Postfix'
# postconf -e 'myhostname = nsbis1-1.ceondo.com'
# /etc/init.d/postfix reload
Reloading Postfix configuration...done.
Which provides us with the correct banner:
$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 nsbis1-1.ceondo.com ESMTP Postfix
quit
221 2.0.0 Bye
Connection closed by foreign host.
Note that this setup is already allowing you to send emails from this server to other servers. Also, be sure that a reverse lookup of your mail server IP address is correcly providing the name in the banner. The reverse lookup is a standard control of the spam filters.
The internal networks an the authenticated users are able to send emails through the SMTP server, we reject the others.
# postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject'
We also need to enable SASL:
# postconf -e 'smtpd_sasl_auth_enable = yes'
# postconf -e 'smtpd_sasl_local_domain = nsbis1-1.ceondo.com'
# postconf -e 'broken_sasl_auth_clients = yes'
Of course do not forget to reload Postfix to test.
$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 nsbis1-1.ceondo.com ESMTP Postfix
EHLO bloah
250-nsbis1-1.ceondo.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-AUTH=DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Here we can see that authentification is available. We can now open the server on the port 587 and try to send an email from our remote connection.
Add the line:
587 inet n - n - - smtpd
to the /etc/postfix/master.cf
file and reload. You can now try to
send an email from your desktop:
$ telnet nsbis1-1.ceondo.com 587
Trying 185.26.124.138...
Connected to nsbis1-1.ceondo.com.
Escape character is '^]'.
220 nsbis1-1.ceondo.com ESMTP Postfix
EHLO blah
250-nsbis1-1.ceondo.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-AUTH=DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:you@hostname.com
250 2.1.0 Ok
RCPT TO:somewhere@hostname.com
454 4.7.1 <somewhere@hostname.com>: Relay access denied
quit
221 2.0.0 Bye
Connection closed by foreign host.
Ok, everything is in order, your server is not an open relay and will not accept a non authenticated connection. Time to setup the database with a login and a password to authenticate the client and allow the local network to send emails without authentication.
The IP address based authentication is already at work when you send an email from the same host, it is defined by:
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
coupled with the permit_mynetworks
in smtpd_recipient_restrictions
.
The last step is of course to setup the login/password authentication, this is done with the corresponding SASL tool:
# saslpasswd2 -c -u nsbis1-1.ceondo.com -a smtpauth testuser
Password:
Again (for verification):
You can list the users in the database:
# sasldblistusers2
testuser@nsbis1-1.ceondo.com: userPassword
Change the rights of the sasl database for Postfix to be able to read the content and have the content of the database in its chrooted environment.
# chown root:postfix /etc/sasldb2
Then you need to make the copy of the /etc/sasldb2
file in the
chroot at each reload/restart (if you add new users, you will need to
reload to have the update of the database file).
Find in /etc/init.d/postfix
the line with:
FILES="etc/localtime etc/services etc/resolv.conf etc/hosts \
etc/nsswitch.conf etc/nss_mdns.config"
and replace it with:
FILES="etc/localtime etc/services etc/resolv.conf etc/hosts \
etc/nsswitch.conf etc/nss_mdns.config etc/sasldb2"
If somebody knows how to do that without the need to change
/etc/init.d/postfix
I would be glad to know!
Now you can try from your laptop:
$ telnet nsbis1-1.ceondo.com 587
Trying 185.26.124.138...
Connected to nsbis1-1.ceondo.com.
Escape character is '^]'.
220 nsbis1-1.ceondo.com ESMTP Postfix
EHLO blah
250-nsbis1-1.ceondo.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-AUTH=DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN AHRlc3R1c2VyAHRlc3R1c2VyMTIz
235 2.7.0 Authentication successful
QUIT
221 2.0.0 Bye
Connection closed by foreign host.
It works and if you wonder how do you get the
AHRlc3R1c2VyAHRlc3R1c2VyMTIz
line, this is simple, just type in a
terminal:
perl -MMIME::Base64 -e 'print encode_base64("\000testuser\000password")'
In all the answers from the SMTP daemon, 250-STARTTLS
told us that
TLS was enabled, we can test it:
openssl s_client -starttls smtp -crlf -connect nsbis1-1.ceondo.com:587
you will see the TLS exchange and then be able to authenticate and send an email over the encrypted channel.
CONNECTED(00000003)
depth=0 CN = nsbis1-1
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = nsbis1-1
verify return:1
---
Certificate chain
0 s:/CN=nsbis1-1
i:/CN=nsbis1-1
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICtjCCAZ6gAwIBAgIJALGia1LJozM0MA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
BAMTCG5zYmlzMS0xMB4XDTE1MDIyODEzMDIyNVoXDTI1MDIyNTEzMDIyNVowEzER
MA8GA1UEAxMIbnNiaXMxLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQDE1nmMfNuA0QfEiWQk74RGj+DFhq2xt2XJ9BV7OSyNTK/zf6IdQesVdgcjjdU2
riRd+s6vRFNp9EckJmuZHSqUM9rBxn5XmIxViVPKcYQUmK4bzbbciuvI5C29go/F
0SGdJF/2YROrs+lOmM6DZl1xMbYYu/ZyNB0S6F9j3W+NpW9PZzjZUk9XdOdz00ua
QakZhNjwRxBp2bkGRYDwX0qWjGdBa6dyotp8VQErCNDZHXUK7/tTKNMQSOyzkl02
Y3IAGrYpnF4tPKT4Jq+qvrwGhx/mmrUimN8IGdNGZbtZW+gJJrfda7QKZUhkwWI7
kCxr0xOv4nVX7H3cwghfAPNnAgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcN
AQELBQADggEBAFwpLMdZCoGhWR0mYAmRX4PFOtUmUe8BY5V56wM89Xul5WnOjua1
e93LVhY7mb7FGG0SXeQNWzWtOGhaLq+zPtsKGrDL/MQTJLnrhZCQnQe8Y9rYxrE0
0ayjqG9Mgc0SVD/X9D5pKn3HEabEmHJXQfIw/J1cS6RDoVqETdzR1s56sTbh/QDk
mRrfPvFweYtYXEB0R/ninbSTi51j5iAlMxDOIokSm/HG6dO5pKBGBhBSWW7VJ5AJ
+3666MFY0Pwmnri47iGZfs/VgdRGfB1xEmcvkPC9CupO2DC2ascizbyRA3RZ7eOa
IWkhgaN/oxAek2AvIVrgJxDPkU/ZuDyS9CI=
-----END CERTIFICATE-----
subject=/CN=nsbis1-1
issuer=/CN=nsbis1-1
---
No client certificate CA names sent
---
SSL handshake has read 1515 bytes and written 466 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: B08A3901510DFDF696BC...ACFE9554EF502127D7E7BD3A96
Session-ID-ctx:
Master-Key: 1535DB23DFC8A1B9CDBC...B95987F4DF19B459293578FE7C
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1425478176
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
250 DSN
EHLO blah
250-nsbis1-1.ceondo.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-AUTH=DIGEST-MD5 CRAM-MD5 NTLM LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN AHRlc3R1c2VyAHRlc3R1c2VyMTIz
235 2.7.0 Authentication successful
QUIT
DONE
Fine, but we have a self signed certificate, so, time to setup the
right certificate. For that, you need a SSL certificate. As we have a
wildcard certificate for *.ceondo.com
that you are currently using
to access this page, we can reuse it for the SMTP over SSL connection.
# postconf -e 'smtpd_use_tls = yes'
# postconf -e 'smtpd_tls_key_file = /etc/ssl/ceondo/ceondo.com.key'
# postconf -e 'smtpd_tls_cert_file = /etc/ssl/ceondo/ceondo.com.crt'
# postconf -e 'smtpd_tls_loglevel = 1'
# postconf -e 'smtpd_tls_received_header = yes'
# postconf -e 'smtpd_tls_session_cache_timeout = 600s'
Reload postfix and you now have your smtp server using your SSL certificate.
$ openssl s_client -starttls smtp -crlf -CAfile comodo.cert -connect nsbis1-1.ceondo.com:587
CONNECTED(00000003)
depth=2 C = US, ST = UT, L = Salt Lake City, O = The USERTRUST Network, OU = http://www.usertrust.com, CN = UTN-USERFirst-Hardware
verify return:1
depth=1 C = FR, O = GANDI SAS, CN = Gandi Standard SSL CA
verify return:1
depth=0 OU = Domain Control Validated, OU = Gandi Standard Wildcard SSL, CN = *.ceondo.com
verify return:1
---
Certificate chain
0 s:/OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.ceondo.com
i:/C=FR/O=GANDI SAS/CN=Gandi Standard SSL CA
1 s:/C=FR/O=GANDI SAS/CN=Gandi Standard SSL CA
i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE3zCCA8egAwIBAgIQZACKlW/WHKCpVsLAKR34STANBgkqhkiG9w0BAQUFADBB
MQswCQYDVQQGEwJGUjESMBAGA1UEChMJR0FOREkgU0FTMR4wHAYDVQQDExVHYW5k
aSBTdGFuZGFyZCBTU0wgQ0EwHhcNMTQxMTEyMDAwMDAwWhcNMTUxMTEyMjM1OTU5
WjBgMSEwHwYDVQQLExhEb21haW4gQ29udHJvbCBWYWxpZGF0ZWQxJDAiBgNVBAsT
G0dhbmRpIFN0YW5kYXJkIFdpbGRjYXJkIFNTTDEVMBMGA1UEAxQMKi5jZW9uZG8u
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzfLEfYiTvbGoT3dg
1xIYW4imEtVt/C3iiPFP238xOCzc40ipkCOPhodZPeUcO8ZWs7nCgKFZEnNOl2FT
bO/2adypG+wxnMO3aTIl2tOV19rbYhFpvjxV/7RsHcQECfdSluXBF5zZv3omsk/i
sw9x4MVpQMu8kOBkAClomJfrqVrKsDNzECC2mCELKzIf93H1YymAI4W13kguoJIR
+gTXSlFeJcckTamXS6OddZeRJNAegd5/Wjav9R3kVllKZI/OYrU+wABMdBQ0SmKS
rTPwFYq6Fp50ld7HuarpzECCj8sJqcDvr+B/ox7VSrdA/1J6Y0DFpWk8GrQbX8kl
+O94zwIDAQABo4IBsjCCAa4wHwYDVR0jBBgwFoAUtqj/oqgv0KbNS7Fo8+dQEDGn
eSEwHQYDVR0OBBYEFICG0Gex9zgr7pS2ZfDoEI9rYxMyMA4GA1UdDwEB/wQEAwIF
oDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBg
BgNVHSAEWTBXMEsGCysGAQQBsjEBAgIaMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93
d3cuZ2FuZGkubmV0L2NvbnRyYWN0cy9mci9zc2wvY3BzL3BkZi8wCAYGZ4EMAQIB
MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuZ2FuZGkubmV0L0dhbmRpU3Rh
bmRhcmRTU0xDQS5jcmwwagYIKwYBBQUHAQEEXjBcMDcGCCsGAQUFBzAChitodHRw
Oi8vY3J0LmdhbmRpLm5ldC9HYW5kaVN0YW5kYXJkU1NMQ0EuY3J0MCEGCCsGAQUF
BzABhhVodHRwOi8vb2NzcC5nYW5kaS5uZXQwIwYDVR0RBBwwGoIMKi5jZW9uZG8u
Y29tggpjZW9uZG8uY29tMA0GCSqGSIb3DQEBBQUAA4IBAQB87TRKFXsadFwD7Y6/
AaBJ/LzJOAcyRNplURAeFjMBe0tLcgEi+2U5qzGMoWlBl7jAAi2LTj9ITz+qXj7M
/iCGOuaGodp5E13vosUu+K3Is14n+uWTZctKevVZV2d4VHxqAE5NYuWP+BLF9N0K
UtARRtDEIZ3TxELy5MXI2Gsi7pUT2Igsjiai64Ub2RCSEhKqEAuReysjs08yZiPV
9yRI2oLUntOzraddcGBICxVgEjbkZAAJ0xngD3H0aglPr67Dx70SBskUBa6gu+Zi
IYRdouXFPhDgFryDKGe3HKq0loKgtbyE88ZWZiMQUPvBdWe8POXvW62SYSJiw5jh
zMc9
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=Gandi Standard Wildcard SSL/CN=*.ceondo.com
issuer=/C=FR/O=GANDI SAS/CN=Gandi Standard SSL CA
---
No client certificate CA names sent
---
SSL handshake has read 3262 bytes and written 466 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 1F6B2B9BC7156...A141F82F5388856CBB9D44F
Session-ID-ctx:
Master-Key: 1AB7B5C534544...EA9C1F8C608CF226F857977
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1425479153
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
250 DSN
quit
221 2.0.0 Bye
closed
Here you have Verify return code: 0 (ok)
everything is running as we
want. Authentication, encryption, the only thing left is to be able
sign the emails with DKIM.
You can now start to use the SMTP server. The configuration is simple:
saslpasswd2
.Now, if you look at the headers of an email you send through your SMTP server, you will see something like:
Received: from [192.168.178.21] (pA1F2D3C46.dip0.t-ipconnect.de [93.123.124.125])
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
(No client certificate requested)
by nsbis1-1.ceondo.com (Postfix) with ESMTPSA id 417F0A6C;
Thu, 5 Mar 2015 08:35:16 +0000 (UTC)
This is a problem because it means your Postfix server is providing
your IP address - here 93.123.124.125
- to everybody. It may even
confuse spam filters because your IP address is most likely a dialup
(DSL) connection and these IP address ranges tend to be automatically
blacklisted.
The solution is to
get Postfix to remove this header. This header is a
Received
header from a client sending an email over ESMTPSA
- that
is, an Extended SMTP connection with Simple Authentication and
Security Layer.
Postfix is great, you can easily do this. First create a file in
/etc/postfix/smtp_header_checks
with the following content:
/^Received:.*with ESMTPSA/ IGNORE
/^User-Agent:/ REPLACE User-Agent: Mozilla-Thunderbird
You can see, that I even replace the version string of the
User-Agent
because if my user agent as a security bug, I do not need
to inform all my correspondance (which possibly includes public
mailing lists) that I am running a buggy software.
Then we inform Postfix to use this file to check the headers of the incoming SMTP emails.
# postconf -e 'smtp_header_checks = regexp:/etc/postfix/smtp_header_checks'
and we compile this special regex database:
# postmap /etc/postfix/smtp_header_checks
# /etc/init.d/postfix reload
Now, if you send again an email, you will see that your email client
is changed to Mozilla-Thunderbird
and the header with your IP
address was removed.
DKIM is using a private/public key system to allow the receiver of an email to very the integrity of the email. The public key used to verify the signature of the email is delivered by the DNS server of the sender email.
So, the verification flow is:
you@example.org
for foo@otherdomain.org
.example.org
with the right DNS lookup.As it relies on a DNS lookup, it means that you, as the owner of
example.org
, need to add your public key in your DNS record of
example.org
. This also means that this system is as robust as the
DNS system. That is, not very but good enough for this purpose.
So, for our mail server to correctly sign the outgoing emails and allow the receiver servers to check the signature we need:
For once, this is simple as OpenDKIM provides a utility to do it for us. You should do some tests with a non critical domain first, in my case, my personal domain:
# opendkim-genkey -d danterroches.org -s mail -t
# ls
mail.private mail.txt
What we get is a RSA private key in the private
file and what to put
as TXT
entry for your DNS record in the txt
file — that is, the
public key with some added information. It is following the Bind
format.
We are going to setup directly both an SPF record and the DKIM public key. For a Bind zone, just add:
mail._domainkey 28800 IN TXT v=DKIM1; g=*; k=rsa; t=y; p=MIGfMA...
@ 10800 IN TXT v=spf1 a:nsbis1-1.ceondo.com include:_mailcust.gandi.net ~all
@ 10800 IN SPF v=spf1 a:nsbis1-1.ceondo.com include:_mailcust.gandi.net ~all
The first line is the DKIM public key (truncated at the end) and the
others the SPF record. What is defined in the SPF record is that
my provider Gandi is allowed to send emails too. Of course they will
not be able to sign my emails with my DKIM private key, but this is
why t=y
is set for the key, it means that if not signed, the email
should not be rejected (the server can possibly mark it as more
susceptible to be some spam).
You can test to see if the DNS record is correctly set:
$ dig +short TXT danterroches.org.
"v=spf1 a:nsbis1-1.ceondo.com include:_mailcust.gandi.net ~all"
$ dig +short TXT mail._domainkey.danterroches.org.
"v=DKIM1\; g=*\; k=rsa\; t=y\; p=MIGfMA0GCS..."
The mail
part in mail._domainkey
is the selector or the name of
the generated key pair.
To sign, OpenDKIM must be configured, launched and Postfix must be
configured to interact with the OpenDKIM milter. A simple
configuration for a single domain is pretty simple, here are the 3
changed lines in /etc/opendkim.conf
:
Domain danterroches.org
KeyFile /etc/opendkim/mail.key
Selector mail
Socket inet:8991@127.0.0.1
If you are going to sign emails coming from virtual machines on your local network, you should add your local network to the list of sources to sign.
InternalHosts 127.0.0.1,192.168.1.0/24
Of course you need to create the /etc/opendkim
folder and copy the
mail.private
file (your private key) as mail.key
in the folder. Chmod the key to 0600
and change the owner to opendkim
:
chmod 0600 /etc/opendkim/mail.key
chown opendkim:opendkim /etc/opendkim/mail.key
and start the milter.
# /etc/init.d/opendkim start
Starting OpenDKIM: opendkim.
You can check that the milter is correctly listening for work:
# netstat -a | grep 8991
tcp 0 0 localhost:8991 *:* LISTEN
Now, the game is to have Postfix push the outgoing emails to the OpenDKIM milter before sending them.
In the /etc/postfix/main.cf
file we need to add the milter:
smtpd_milters = inet:localhost:8991
non_smtpd_milters = inet:localhost:8991
milter_protocol = 2
milter_default_action = accept
The default action is important, it means that if the OpenDKIM milter fails, it will still send the email. Do not forget to restart Postfix.
Time to test.
$ openssl s_client -starttls smtp -crlf -connect nsbis1-1.ceondo.com:587
EHLO blah
AUTH PLAIN auth-string
MAIL FROM:you@danterroches.org
rcpt to:you@danterroches.org
DATA
From: me@danterroches.org
To: me@danterroches.org
Subject: Testing the milter
Hello,
I am testing the milter of Postfix.
loic
.
250 2.0.0 Ok: queued as F14AD1FD75
quit
And now, waiting a bit and checking the email, I find the headers:
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=danterroches.org;
s=mail; t=1313746486;
bh=GlQYLi2MdsEJ1lCtPhoJ6j2+PvMu2G/vEoDmWwqlWqo=; h=From:To:Subject;
b=JrkasVKpQwhanu1Uz9hO7cKy8NPo/bzs7tkVxu6xOMBCKJJDn/jRmnDiaQt5JOSAT
a0r32KJyY2K+GrQfkNRB2Ucq0/jsPl15FVZQVTooi2o0eLhecBHawxvYSUcgkH3pj8
xmtu32pDuAVNRTnzwphbxK+EoBdCicu2ECsEYdbg=
The email has been signed successfully. Happy day!
If you are well securing your email server, you can simply add the
same public key and SPF records for all the domains and in the
/etc/opendkim.conf
file, simply change the line:
Domain danterroches.org
with:
Domain danterroches.org, example.org, example.net
You can also use a database, a file, a sleepycat database. man
opendkim
will give you the way to configure a dataset. OpenDKIM is
very flexible digging into the documentation will provide you with a
large list of options and functionalities to match your requirements.
If you rationalize a bit the way you work, your mail server will
handle many web applications and as such will need to receive emails
for many domains. This is handled very easily with the
virtual_alias_domains
system of Postfix.
For example we are going to handle the domain gitmanual.org with this system. So, first, we inform that we want to handle this domain as a virtual domain:
postconf -e 'virtual_alias_domains = gitmanual.org'
Be sure to never add a domain both in the mydestination
and the
virtual_alias_domains
entries.
We need also to define what to do with the emails coming for this domain, we define for this an alias map:
postconf -e 'virtual_alias_maps = hash:/etc/postfix/virtual'
The content of the file is for example:
foo@gitmanual.org gitmanual
bar@gitmanual.org gitmanual
This means that we are going to accept only emails for foo
and
bar
, and send them to the local alias gitmanual
. Now, we need to
define this alias.
Open /etc/aliases
and add at the end:
gitmanual: you@yourdomain.com
This means that the emails coming for foo
and bar
on the
gitmanual.org
domain will be forwarded to you@yourdomain.com
. You
cannot really make it simpler.
You need now to compile the virtual
and aliases
databases:
# postmap /etc/postfix/virtual
# newaliases
If you try now to send an email, it will fail because your mail
server is still secured not to receive emails from smtp servers or
client outside of mynetworks
or SASL authenticated. So, we need to
add the reception of emails for the authorized domains in the virtual
alias (and as a side effect to the mydestination
domains).
postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, \
permit_auth_destination, permit_sasl_authenticated, reject'
Note the addition of permit_auth_destination
compared to the
previous configuration. Do not forget to reload the configuration:
# /etc/init.d/postfix reload
You first need to be able to receive emails, then you simply create an alias which is piping the content to a command:
gitmanual: "|/usr/bin/php -q /path/to/script.php gitmanual"
Here you can for example read the content of the email and process it:
<?php
$email = file_get_contents('php://stdin');
// do something with $email
exit($errorcode);
The $errorcode
should be:
0
: Success;67
: Address unknown — good if you catch all and let the script decide if the email address is good or not.75
: Temporary failure, invite the client to send the email later — good if your database is down for maintenance.If you receive emails for your webapplication, you may want to verify the DKIM signature, greylist and spam filter.
At the end, the setup is simple, robust and pretty fast to setup. It requires only a sound understanding of the elements (DNS, SMTP) in play. If you are not sending 100,000's emails in a day, you do not need more. The verification of the DKIM signature is not shown here as not really needed.
InternalHosts
option.