How to set up sendmail on CentOS?

It is said postfix is the most popular mail server now. However, postfix is not installed on my VPS. Instead, sendmail is installed by default although I never started the service before. So I decide to use sendmail as the email server. This article is a very helpful guide for sendmail configuration, which I follow to do my work. To summarize, the steps to configure sendmail are:

  1. edit /etc/mail/sendmail.mc to change the line:DAEMON_OPTIONS(‘Port=smtp,Addr=127.0.0.1, Name=MTA’)dnlto: dnl DAEMON_OPTIONS(‘Port=smtp,Addr=127.0.0.1, Name=MTA’)dnlNow sendmail listens on 0.0.0.0:25 instead of 127.0.0.1:25, which means sendmail can accept connections from any ip address on the machine rather than the loop back interface.
  2. m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
  3. add domain names(one domain name per line) in /etc/mail/local-host-names
  4. service sendmail restart

If you have not installed the sendmail related packages, install them first:

yum install m4 telnet mailx

yum install sendmail sendmail-cf

 

Then I add two users on the CentOS system:aaa,bbb, for email sending/receiving test.

First, I login as aaa and send an email to bbb using mail:

mail -s “test from aaa” bbb

hello from aaa

.

EOT

Then I login as bbb and simply type “mail” to see if I’ve received the email from aaa. Unfortunately, the output of mail command is “No mail for bbb” which means the email was not sent successfully.

To investigate the problem, I look into the sendmail log using “tail -f /var/log/maillog”. That log file is generated by sendmail components using the syslog service.

Surprisingly, I see the log file is being flooded by many messages. The sendmail log format is:

<date> <host> sendmail/sm-msp-queue[pid]: <qid>: <what>=<value>

I have no idea of most <what>=<value> equates except from=xxx, to=xxx which I guess are the from/to value of emails.

Most messages refer to the program sm-msp-queue. What is sm-msp-queue?  What is sm-msp-queue used for. After a little research, I found sm-msp-queue is a queue runner that fetches messages stored in /var/spool/clientmqueue/ periodically and delivers them to sendmail for sending out. Specifically, if sendmail service is turned off when email client is sending messages, the messages are saved in /var/spool/clientmqueue/. When sendmail service is started, sm-msp-queue will transfer files in /var/spool/clientmqueue/ to /var/spool/mqueue/ for delivery by sendmail. That explains why so many log message are flooding the mail log file. Because there are many mails in /var/spool/clientmqueue/ that are waiting to be delivered and the sendmail service was never started before.  But where do those emails come from? I never sent or received emails using this server before. Are those emails sent by spammers or hackers compromised my server and used it  for email relay? After carefully looking into the log, it does not seem to be this situation because most messages are related to localhost or 127.0.0.1. I need to dig into the emails to see what on earth they are. Most files in /var/spool/clientmqueue/ are qf/df pair. the df files are data files containing the content of emails, while the qf files contain the control information to deliver the email such as the email headers. By checking the df files, I see most of them are generated by crond. I have a cron job which runs every 5 minute and generated a lot of emails I have not noticed beofore. I do not want those junk emails so I add a line MAILTO=”” before the cron job line by issuing the command “crontab -e”, which will stop crond sending emails. The remaining issue would be removing all the existing emails from the system. How to remove all emails from message queue? Although there are many methods to delete all deferred emails or emails that are bounced back or not delivered successfully for a reason. In my case, I just stop sendmail service and delete all files in /var/spool/clientmqueue/ then restart sendmail.

Now I continue to do the aaa to bbb email delivery test. New errors occur in the log file:

My unqualified host name  unknown; sleeping for retry

unable to qualify my own domain name (xxxx) — using short name

stat=Deferred: Connection timed out with [127.0.0.1]

I solved this problem by adding a line 127.0.0.1 localhost….hostname in /etc/hosts. Note that you must restart sendmail after modifying /etc/hosts. It seems sendmail pre-loads the host file at the start time. It is a little weird that in another test, even I did not add the 127.0.0.1 to hostname mapping, the email was still sent successfully after some delay after the second error message “unable to qualify my own domain name (xxxx) — using short name”. But adding the mapping line, the email was sent instantly and  no error logged, and the time taking to restart the sendmail service is also reduced. Note that you must unblock the port 25 to make the email delivery success even if you are sending mail to the user on the same machine. The mail command uses the port 25 to send emails. If port 25 is blocked or sendmail is not listening on port 25, you will get the following error:

mailer=relay, pri=30219, relay=[127.0.0.1] [127.0.0.1], dsn=4.0.0, stat=Deferred: Connection refused by [127.0.0.1]

The next step is to configure sendmail to enable ssl. sendmail supports ssl in itself. You just need to un-comment the following lines in /etc/mail/sendmail.mc
define(confCACERT_PATH', /etc/pki/tls/certs’)dnl
define(confCACERT', /etc/pki/tls/certs/ca-bundle.crt’)dnl
define(confSERVER_CERT', /etc/pki/tls/certs/sendmail.pem’)dnl
define(confSERVER_KEY', /etc/pki/tls/certs/sendmail.pem’)dnl

DAEMON_OPTIONS(Port=smtps, Name=TLSMTA, M=s')dnl
and make a dummy certificate in /etc/pki/tls/certs/.

cd /etc/pki/tls/certs/ and execute ./make-dummy-cert sendmail.pem

After restarting sendmail, netstat -antp will list sendmail is listening on port 465 instead of 25. Of course, you should modify your iptables to allow connection to port 465:

iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT

Otherwise, you will get the error,

stat=Deferred: Connection refused by [127.0.0.1]

We have tested sending/receiving emails using sendmail by logging in the server and using the mail command. Now it is time to do real work. We will configure an email client to send emails to real email addresses. You may think it is a hard thing because you heard about creating MX dns record on your domain registrar. Let's not get into that trouble at present. In fact, if  you have added an A record on your registrar, there is no need to add MX record at all. When sendmail relays mails, it looks up DNS for MX record of the host of recipient email. The MX record eventually maps to an ip address where the mail is to be delivered.  If sendmail cannot find a MX record, it looks up the A-record of the domain for the ip address. So MX record is not a necessity. But creating MX record has the advantage of using a different host than what the A-record points to, to handle emails for the domain. But you do need to add the domains your sendmail controls to  /etc/mail/local-host-names. Otherwise, when sendmail receives an email destined to your server, sendmail will consider it is an email to elsewhere and try to relay the email. But the dns lookup results in an ip address of the server itself. Thus, the error occurs:"SYSERR(root): domainhostseotool.com. config error: mail loops back to me (MX problem?)".  Remember we have added two user accounts on the linux system(aaa and bbb)? Those account names, together with the domain name, form the email addresses. For example, your domain name is domainhostseotool.com, and you've created an A record pointing the domain name to some ip address where your email server(sendmail in our case) is set up, the linux accounts aaa/bbb on this server form the email addresses: aaa@domainhostseotool.com, bbb@domainhostseotool.com.

How to set up an email client to send emails?

You may think it is not an easy thing. Take outlook express for example, it seems you have a lot of parameters to configure. Double click an email account in tools/accounts, you can find the properties of the email account.

In the General tab, you can set a name to note a server, your name, and an email address. This information is what you filled using the "add an email account" wizard. What matter are the name and the email address, while the server name is just a local concept that helps you differentiate different email accounts and won't be used in the delivery of emails. The email address here is very important. It will appear in the "From", "Return-Path" header of the email you send. The name also appears in the "From" header. For example, you set the name "myname" and the email address: bbb@domainhostseotool.com, the emails you send will have the following headers:

Return-Path: <bbb@domainhostseotool.com>

From: "myname" <bbb@domainhostseotool.com>

The Server tab lists the sending server and receiving server you input in the internet connection wizard when adding a new email account. For receiving email server, the account name and password below the server are what you input when adding the new email account. For sending server, you can check on the option "my server need authentication" and click the "setting..." button to fill the information that's needed for authentication. You can choose to use the same account information as the receiving server or input a different account that is used for sending emails. People often tick on the  "my server need authentication" and choose to use the same account information as the receiving server. But it is not always necessary. For example, in our case, the sending server does not require authentication(which means anyone can use our sendmail server to send emails to the users on the domain our sendmail server is managing, or use the sendmail server to relay emails to other domains if the sender is allowed to do so by our policy). Even we tick on the  "my server need authentication"  option, outlook express will never use the account information here to log to the sending server. So you can input any user/password here.

For sending server that requires authentication, the sending server of the email client must be set to the domain name(domainhostseotool.com). The user name is the email address(i.e., aaa@domainhostseotool.com, or aaa) and the password is the linux login password for the user aaa.

The Advanced tab lists the options for SSL connection for SMTP and POP3. The insecure SMTP uses port 25 while the secure SMTP(SMTPS) uses port 465. The ordinary POP3 uses port 110 while POP3S uses port 995. In our case, we check SSL on for both SMTP and POP, and use the port 465 and 995, respectively.

 

That is all needed to configure the email client for sending emails. As stated before, you must add the domain name(domainhostseotool.com) in /etc/mail/local-host-names, otherwise, when you try to send emails, you will get the error:

reject=550  <bbb@domainhostseotool.com>... Relaying denied. IP name possibly forged

This is because the domain of the recipient is not managed by sendmail on this server, so sendmail tries to relay the email to the destination domain. However by default, sendmail will reject any email that 's not destined for the domain it manages and not originated from localhost. In other words, sendmail only accepts emails from localhost and emails with recipient host is what it manages. Those emails sent to other domains may be relayed if policy allows. How to enable sendmail to relay your email? You can add your ipaddress to /etc/mail/access as

Connect:xx.xx.xx.xx                    RELAY

Then execute the command to rebuild access.db

makemap hash /etc/mail/access.db < /etc/mail/access

After restarting sendmail, the email sent from xx.xx.xx.xx will be relayed.

We can talk a little more about "IP name possibly forged". This message is generated if sendmail cannot find the domain name of the source ip address of receiving email by reverse DNS lookup or the domain name got by reverse DNS lookup does not have an A-record pointing to that same ip address.

We've modified access to let sendmail accept our email for relay. You won't see an error dialog in your email client. However, it does not mean sendmail can deliver the email to the peer successfully. In fact, using the configuration we talked above, you will get the following error:

stat=Deferred: Connection refused by peerdomain.com

This is because by default, sendmail uses port 25 for server to server communication. When we enabled SSL for sendmail on the peer server(the server our email is relayed to), sendmail MTA  listened on port 465 and the default port 25 was shut down. Although we also enabled SSL for the relaying server and shut down the port 25, sendmail still uses port 25 to relay the email to the peer. We attempted to change the communication port from to 465 by adding the following lines in sendmail.mc on the relaying server.

define(RELAY_MAILER_ARGS’, TCP $h 465')
define(
ESMTP_MAILER_ARGS’, TCP $h 465')

But it did not work. Using netstat -antp|grep sendmail on both servers, we can observe the connection through port 465 has been established successfully. But the relaying server eventually times out with the error:

timeout waiting for input from peerdomain.com. during client greeting
stat=Deferred: Connection timed out with peerdomain.com

And the relay-to server times out with the following errors:

STARTTLS=server, error: accept failed=0, SSL_error=5, errno=0, retry=-1, relay=[relayingserveripaddress]
did not issue MAIL/EXPN/VRFY/ETRN during connection to TLSMTA

There are two choices now. One is to comment the line

FEATURE(no_default_msa’, dnl')dnl

in sendmail.mc on the peer server to use default msa that listens on port 587 , and add the lines:
define(
RELAY_MAILER_ARGS’, TCP $h 587')
define(
ESMTP_MAILER_ARGS’, TCP $h 587')
for the relaying server to let it connect to the peer via port 587.
The second way is to add another mta that listens on port 25 on the peer server:
DAEMON_OPTIONS(
Family=inet,  Name=MTA-v4, Port=25′)dnl
,and do not change the configuration on the relaying server.

Both methods work. But the second way is the preferred one. Why? If you want your sendmail server to receive incoming emails from external sendmail servers or other smtp servers, you need to configure sendmail to use port 25, because public smtp servers such as gmail/outlook send emails to your server through port 25. They do not know you listen on other port.  They won’t change port to 587 to cater for you.

 

Now we can talk about something interesting.

Add a fake domain in local-host-names 

You’ve known that /etc/mail/local-host-names contains the domains sendmail controls. But what happens if you add a domain name,i.e.,gmail.com, that is not actually controlled by sendmail on this server? Well, the result is the email is sent to the user with the same account name as the destination email address, not the real person that needs to receive the email. For example, if you send an email to bbb@gmail.com, the user bbb on your SMTP server(domainhostseotool.com) will receive the email. The bbb om gmail.com will never receive the email. If there is no such user name existing on your SMTP server, it returns the error: User unknown.

how to use telnet/openssl to send email?

telnet xx.xx.xx.xx 25

helo localhost

mail from:aaa@domainhostseotool.com

rcpt to:bbb@domainhostseotool.com

data

hello from aaa

.

EOT

quit

 

openssl s_client -connect xx.xx.xx.xx:465

openssl s_client -starttls -connect xx.xx.xx.xx:465

Now I think you are able to send emails without problem. As to receive emails, you can always log onto the server and use the mail command to check emails. But most people are used to having an email client such as outlook to receive emails from the server to their local computers. How to configure the email client to receive emails? You must have noticed the pop3 settings in your email client. But if you  try to retrieve emails using the account information we set for the sending server, you will get socket error:10060,error number 0x80ccc0e as we have not set up a pop3 server yet. Dovecot is a good pop3 server that supports SSL(POP3S). Let’s install and set up dovecot.

  1. yum install dovecot
  2. cd /etc/dovecot
  3. vi conf.d/10-mail.conf, un-comment the line: mail_location = maildir:~/Maildir, this is where Dovecot gets emails for you.
  4. vi conf.d/10-ssl.conf, un-comment the line:ssl = yes, to enable secure pop3
  5. vi conf.d/10-auth.conf, change the line: disable_plaintext_auth = no to disable_plaintext_auth = yes; change the line: auth_mechanisms = plain to auth_mechanisms = plain login
  6. cd ..
  7. vi dovecot.conf, uncomment the line: protocols = imap pop3 lmtp; uncomment the line:listen = *, ::
  8. service dovecot restart

Now you can see dovecot is listening on port 995 (POP3S) using netstat -antp

Now we can configure the email client to use this pop3s service: the pop3 server is domainhostseotool.com, the account name is the linux user name(aaa/bbb), the password is linux user password, the pop3 port is 995,and the SSL option is ticked on. It is a little tricky here. Since the account name is the linux user name, not an email address, if you send two emails to aaa@domainhostseotool1.com and aaa@domainhostseotool2.com, respectively, both domainhostseotool1.com and domainhostseotool1.com are hosted on the same server controlled by sendmail and you added two email accounts for aaa@domainhostseotool1.com and aaa@domainhostseotool2.com in your outlook, then the first account that logs in will receive all emails to the two email addresses, the other email account will not receive any email.  If Everything is ok and the email client can connect to the pop3 server without failure. But surprisingly, no emails are retrieved. This is abnormal because we have sent several emails in the test.  I remember the mail location specified in 10-mail.conf is:

mail_location = maildir:~/Maildir

However I know sendmail delivers emails to /var/spool/mail/$u. Is it because I specified the wrong mail location so that dovecot could not find the emails I received? To verify it, I modify the mail location to:

mail_location = maildir:/var/spool/mail/username

hoping dovecot can pick up mails there. Sadly, this time, the email client even fails to connect to the server. We need to dig into the dovecot log too. Where is the dovevot log file? Using the command:

doveadm log find

I find all dovevot log information is also put into /var/log/maillog, the same as sendmail. There are some errors in the log file:

Error: stat(/var/spool/mail/username/tmp) failed: Not a directory

Error: Couldn’t open INBOX: Internal error occurred. Refer to server log for more information.

Couldn’t open INBOX top=0/0, retr=0/0, del=0/0, size=0

I notice /var/spool/mail/username is a file not a directory. Maybe I should use anther format of the mail location. I change the mail location to this one:

mail_location = mbox:~/mail:INBOX=/var/spool/mail/%u

Still  no luck, but the errors in the log file change to the following:

Error: chown(/home/username/mail/.imap/INBOX, -1, 12(mail)) failed: Operation not permitted

Error: mkdir(/home/username/mail/.imap/INBOX) failed: Operation not permitted

I tried to un-comment and change the following line in conf.d/10-mail.conf:

mail_privileged_group = mail

But still it does not work. Finally I find the solution in this article:

chmod 0600 /var/spool/mail/*

The original permission of the files under /var/spool/mail is 660. I do not know why it can solve the problem but it does. All errors gone and the email client successfully fetched all emails to my pc. I guess many people have encountered this stupid issue and hope people can find the fix more easily than me.

The above problem indicates the integration between dovecot and sendmail is not perfect at all. You should explicitly tell dovecot where it  should get the emails sendmail delivered.

 

 

Posted in tips of hosting