Sep 14, '05 09:04:00AM • Contributed by: mbogosian
This hint provides an alternative mechanism to create an SMTP daemon that listens and accepts connections on port 25 (the standard SMTP port) that is (more) appropriate for desktop/laptop users, without disturbing much of the out-of-the-box 10.4 setup and behavior.
Motivation
I suffer from mild obsessive-compulsive disorder when it comes to system administration, especially on my own machines. While I appreciate the simplicity of tools like Postfix Enabler, I naturally distrust their ability to do The Right Thing™, especially since tools like these typically hide the details of what they change "under the covers."
There are already a few hints (e.g., here and here) which explicitly advise how to set up postfix in such a way that it will provide a SMTP daemon that listens and accepts connections on port 25. Many of these use launchd, but (IMHO) do so in a way that doesn't quite seem to be in complete harmony with either postfix or launchd (at least how they were intended to be used on a desktop machine).
I wanted to create a solution that modified the 10.4 "stock" postfix behavior and configuration as little as possible, without suffering from some of the problems identified in other hints (e.g., aggravating the ability of a notebook to honor its sleep settings). I thought having the postfix master process exit after 60 seconds was a good idea and wanted to preserve that behavior. I also wanted to use launchd (as I believe it was intended) to be able to launch services on an as-needed basis (rather than force them to run all the time).
Overview
We will implement a solution which will use the (mostly) default configuration of the postfix master program to handle mail as it was intended: by monitoring /var/spool/postfix/maildrop (and that's all) for new mail and handle sending it. In addition, we will use launchd to run an inetd-like daemon, on an as-needed basis, to listen for connections on port 25 and put new mail in /var/spool/postfix/maildrop.
Implementation
From a fresh installation, there are three files which must be edited/created to implement this solution. They are as follows:
- /etc/hostconfig (one line addition/change)
- /etc/master.cf (one line change)
- /System/Library/LaunchDaemons/smtp.plist (new file)
MAILSERVER=-YES-
This tells OS X to automatically turn on various aspects of handling of sent mail. Ideally, this would be all we needed, but the default configuration is to only handle mail being sent via files created in the /var/spool/postfix/maildrop directory (e.g., the via the mail and sendmail Unix commands). The good news is that this is the exact behavior of which we intend to take advantage in order to disturb the default settings as little as possible.
After completing this step (if any change was required), then you should reboot to have the change take effect. There is probably a way to tell OS X to re-read /etc/hostconfig and adopt its changes, but I do not know what that is, so (at least for now) a reboot is my only prescribable option.
The second change is equally simple. We must make sure that the following line in /etc/postfix/master.cf is commented out (i.e., that the start of the line begins with a #) -- it's line 83 in my version of the file:
#smtp inet n - n - - smtpd
This tells postfix that when it runs master, it should not listen on port 25 when it's running.
The default behavior of OS X 10.4 is that when launchd detects a new file in /var/spool/postfix/maildrop, it fires up the postfix master program to handle the sending of the file to its intended destination. It indicates to master that it should hang around for 60 seconds (just in case the user is sending more than one file), and then exit (so that it doesn't use up system resources and keep your notebook from sleeping, etc.).
However, the default configuration of master in /etc/postfix/master.cf tells it that while it's running, it should also listen on port 25 for incoming SMTP requests. If you'd like to see this in action (once you've changed your /etc/hostconfig file and rebooted), try the following in a shell (via Terminal):
$ telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
$ echo hello | mail your_email_address
$ telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 matt.local ESMTP Postfix
quit
221 Bye
Connection closed by foreign host.
Now wait 60 seconds or more before typing the next command:
$ telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
I believe this behavior doesn't make very much sense and is not what is intended (i.e., that it is an oversight by Apple). After commenting the above line out and waiting 60 or more seconds for any existing master processes to exit, you should not be able to connect to your local port 25 regardless if any new master processes run or not.
Note for users who have already modified their mail configuration: as indicated above, the required line change was on line 83 in my default configuration, but yours may be different. If you've got other SMTP-related services running via the /etc/postfix/master.cf file, you may wish to comment those out as well. Also, if you've configured your master process not to exit (i.e., run all the time), you may wish to kill it (or restart it) once you make the above changes. You'll also want to return to the default /System -> Library -> LaunchDaemons -> org.postfix.master.plist file, which tells postfix to monitor the /var/spool/postfix/maildrop directory for new mail.
The third and final change is actually the creation of a new launchd service configuration file. The new /System/Library/LaunchDaemons/smtp.plist file needs to hold this code. The easiest way to do this (if you're not familiar with how to create a file in a directory not owned by you) is probably to do the following in a shell (via Terminal):
$ sudo cat >/System/Library/LaunchDaemons/smtp.plist
Now copy the source from the window that the above link will open, and paste it into the Terminal. Then hit COntrol-D to close the file and write it.
This creates an entry for launchd which will, on an as-needed basis, run sendmail in single-run daemon mode (via the -bs option) as user nobody on port 25. Running as nobody is important, since running it as root is a security risk (and actually doesn't work in the 10.4 default version of postfix). All that's left now is to tell launchd about its new service (this is to enable it without rebooting; launchd will automatically load this file on subsequent reboots):
$ sudo launchctl load /System/Library/LaunchDaemons/smtp.plist
$ sudo launchctl start org.postfix.sendmail
Now, every time you attempt to connect to port 25, launchd will spawn a new sendmail process which, when completed, will put new mail into /var/spool/postfix/maildrop which will trigger the default configuration of postfix to sweep it up and take care of it as needed.
Conclusion
Although rather verbose, I hope this hint has illustrated how both launchd and master work in a default 10.4 system, as well as how to tread as lightly as possible in modifying their behavior to create a usable port 25 on a desktop machine without suffering from some of the problems associated with running full-time daemons.
Acknowledgements
Despite my preference for an alternative, I must make it clear that other hints on this forum were invaluable in both inspiration and a platform from which to launch the approach described above. Without those authors' contributions, I would have never made this approach.
