I'm sure variations on this question have been asked and I apologize if this is a duplicate, but I just can't seem to find something that works in my situation without breaking something else.

I'm using my VPS as a webserver and I need contact forms on websites to send mail through the server. I installed sendmail and, largely, it works. However, the mail was failing a lot of SPF tests. I added SPF entries to each domain, but when I inspected the mail headers I noticed a lot of:

ARC-Authentication-Results: i=1; mx.google.com;
   spf=neutral (google.com: is neither permitted nor denied by best guess record for domain of user@foo.localdomain) smtp.mailfrom=user@foo.localdomain

Return-Path: <user@foo.localdomain>

At first, I simply changed the hostname of the box (and added entries in /etc/hostsas well) to my primary FQDN. I did this because I used include:foo.com in my SPF entries.

This had some side effects, so I undid the changes and went back to a local box name.

I read and implemented a change in this question by editing sendmail.mc to append define(`confDOMAIN_NAME', `foo.com')dnl

I then tried to submit a contact form from my own website (located on the same primary domain) and got an error from Contact Form 7. I tried a client site (same server, different FQDN) and it worked. So I removed that custom entry and rebuilt the sendmail.mc file.

What is the right way to have sendmail create mail headers from a FQDN without upsetting something else? Should I just have tried the sendmail.mc thing again but created a mail.foo.com subdomain?

I'm very confused - I just want my mail headers to stop having local domains in them so that SPF doesn't have to best guess and will pass the mail as valid where I've got SPF records in place that specifically allow both the sending IP and domain (like I already do).

EDIT: Here is my /etc/hosts file right now: localhost localhost.localdomain example.com mail.example.com myboxname.localdomain myboxname

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

And the output of sendmail -bt -d0.1 root is:

Version 8.15.2

============ SYSTEM IDENTITY (after readcf) ============
      (short domain name) $w = myboxname
  (canonical domain name) $j = mail.example.com
         (subdomain name) $m = localdomain
              (node name) $k = myboxname
  • 1
    The easiest way is to set the machine's hostname to the proper FQDN. Or have your PHP script set the From address properly. – Michael Hampton Feb 6 '18 at 18:03
  • I was under the impression that setting a servers hostname to a FQDN was a "bad" idea. I've seen it mentioned before. I know that, for me, it caused some issues with Apache because the 000-default block would all of a sudden start kicking in (took a long time to realize that was the issue and setup that server block to point to the domain's separate entry in sites-available) – armadadrive Feb 6 '18 at 18:05
  • It's best practice to set the machine's hostname to its FQDN, and has been for decades. Unfortunately it's not something that Debian/Ubuntu boxes routinely do, so if you try to follow this best practice, you'll find that some other people have made assumptions that the FQDN would not be used as the hostname.... – Michael Hampton Feb 6 '18 at 18:07

I had the same issues - our relay rejected the ctladdr, confDOMAIN_NAME didn't work, and changing the hostname would affect other programs. I'm using CentOS 6.x but I believe these will work with Ubuntu as well. I found two solutions that worked with mail() and sendmail. Our end solution was using CodeIgniter's email class because it better fit our software setup.

Method #1: domain alias

Sources: LinuxQuestions and ServerFault

Prior to setting up the alias my hostname looked like this

[root@devbox ~]# hostname --fqdn

[root@devbox ~]# sendmail -bt -d0.1 </dev/null


============ SYSTEM IDENTITY (after readcf) ============
      (short domain name) $w = devbox
  (canonical domain name) $j = devbox.ourlocalnetwork.lan
         (subdomain name) $m = ourlocalnetwork.lan
              (node name) $k = devbox

I added this line to /etc/hosts and restarted the network   devbox.ourlocalnetwork.lan mail.myrealdomain.com

Sendmail pulled in the alias and would send emails using that domain

[root@devbox ~]# hostname --fqdn

[root@devbox ~]# sendmail -bt -d0.1 </dev/null


============ SYSTEM IDENTITY (after readcf) ============
      (short domain name) $w = mail
  (canonical domain name) $j = mail.myrealdomain.com
         (subdomain name) $m = myrealdomain.com
              (node name) $k = devbox

I sent an email with the web form and the results were visible in /var/log/maillog, the ctladdr was being set properly now

Feb  6 17:03:45 devbox sendmail[6854]: w16M3irS006852: to=<support@whatever.com>, ctladdr=<apache@mail.myrealdomain.com> (48/48), delay=00:00:01, xdelay=00:00:01, mailer=esmtp, pri=120567, relay=mx1.ourrelayprivder.com. [relay_ip_redacted], dsn=2.0.0, stat=Sent (Ok: queued as 2445F140071)

Method #2: mail() additional_parameters

Sources: PHP manual and StackOverflow

mail($to, $subject, $message, $headers, "-f ".$email)

Use additional_parameters to change the From and the Reply-To fields. This method is simpler but you must pay closer attention to sanitizing user input as noted in the comments on that page.

This also produces a warning in the log file

Authentication-Warning: devbox.ourlocalnetwork.lan: apache set sender to test@test.com using -f

I didn't like the 'smell' of this code so we went with the next method

Method #3: use a different email library / framework

This was our actual solution. Our use of mail() was in legacy code. My coworker rewrote this bit of code using CodeIgniter while I was clowning around with sendmail. This was the cleanest solution with our website setup so we used it.

| improve this answer | |
  • I've ended up using MASQUERADE to fix it for now (as seen here: cyberciti.biz/tips/…) and, though it appears to be working, I want to make sure that's a best practice. – armadadrive Feb 7 '18 at 17:05
  • Method #1 looks interesting but it didn't work for me alone. See my edit to the question. (Well formatted answer for a first-post! Thanks) :) – armadadrive Feb 7 '18 at 17:08
  • MASQUERADE looks like a solid solution. I think it wasn't working in my case but if it works for you then go for it. – Maave Feb 7 '18 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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