Why cats? They kept me company while making this page, and decided to stay. Or search this page for 'cat ' (with trailing blank).

What It Is Subtitle


Nullmailer Benefits Subtitle

What It Does Subtitle

Dependencies Subtitle

Fast types follow the . Others hop on the

Licorice Conveyor belt

for the complete tour.

Preparation Checking just 6 lines

Gmail (like Hotmail/Live/Outlook, and Yahoo! Mail) overwrites "From" information in every email batch that you relay. They overwrite with the main email address of the account which was used to log into their email servers. Usually this email address is one-on-one with the email address in the file "remote" (your login credentials).
Although Google discontinued the free Google Apps Standard Account service, individual developers can still register for a free single user Google Apps Standard Account. By first creating a Google App Engine Account (free), and then from their App Engine Admin Console register for the free Google Apps Standard Account. At Google Apps they should then add their own domain name to : host their App Engine Apps, and create their @yourdomainname.com email address and aliases. Read the paragraph highlighted in blue.
If you're running a business, or for whatever reason can't use a free email address, paid services similar to Google Apps for Business' Gmail and Namecheap's Cloud Email Hosting enable you to use "@yourdomainname.com" email addresses.

It's probably best to create a new email address at each of Gmail, Yahoo!, Hotmail, etc (or use an alias, or disposable email address) for relaying with nullmailer, because :

Everything was developed in a Bash shell (not dash, sh, ash, zsh, csh, ksh, etc). Shell Expansion might be different when you use a different shell. Check which shell you are running with :
"ps -p $$" or "echo $SHELL".

Download the archive and extract, or clone the repository, into a directory on your server.
Open the installation script "install_nullmailer.sh" in your favorite text editor.
Please also read the few comments in the script that belong to the instructions discussed below.

Scroll to the block of instructions with initialization of constants starting with "cNULLMAILER".

My advice is to leave the paths in "cNULLMAILERROOT" and "cNULLMAILERCONFIG" initialized to their defaults. This are the locations where self-compiled binaries and config files should be placed on Ubuntu.
You can change the default path for the log files by changing the value of "cNULLMAILERLOGDIR".
Any change that you make, will have to be reflected in the start/stop script named : "nullmailer-send.prefab".

Scroll to the following block of instructions, and comment out what you already have and do NOT want to update.


86. # Update the list of packages. Install linkers, compilers, etc. And also TLS dev libs.
87. /usr/bin/apt-get update
88. /usr/bin/apt-get install build-essential
89. /usr/bin/apt-get install libgnutls-dev


Scroll to the following block of instructions, and uncomment what you want to UNINSTALL after the installation is completed.


230. # apt-get purge libgnutls-dev # Optional
231. # apt-get purge build-essential # Optional
232. # apt-get autoremove; apt-get autoclean # Optional


Any change that you make, must also be reflected in the uninstaller.
Execute the commands chmod 700 install_nullmailer.sh and chmod 700 uninstall_nullmailer.sh to make these scripts accessible and executable by root only.
At this point, you have the option to do the minimal configuration which is mentioned in "Post Installation". Because it doesn't really matter if you configure Nullmailer before or after running the installer.

Running The Installer Beckon the daemon

Make sure that you have root access
Run the installation script from the directory where you unpacked it (I'm installing from /root/nmi), with :


cd /root/nmi
./install_nullmailer.sh


If all went well, a line showing a running nullmailer daemon process followed by a line with the daemon's status, will be displayed by the installer. :

nullmail 550 0.0 0.0 12540 8 ? S Aug01 0:00 /usr/local/sbin/nullmailer-send --logging --onelog

"* nullmailer-send is running"

The installer will also have copied a file named defines.cc to /root/nmi. You MUST keep this file because the uninstaller depends on it.
This file contains all paths where nullmailer installed its parts to.
There is a flow diagram of the various nullmailer components in the nullmailer source code. The installer copies it to /root/nmi.

Post Installation Just 4 lines in 4 files

This is entirely optional : I closed ports 25 (SMTP), 110 (POP3), 143 (IMAP) in iptables.

The nullmailer man pages : man nullmailer, man nullmailer-inject, man nullmailer-queue, man nullmailer-send, man sendmail.

If you kept the default path, your config files were most likely copied to : /usr/local/etc/nullmailer/.
When you changed the default path, you'll have to look what's assigned to constant "CONFIG_DIR" in file "defines.cc". Nullmailer's "./configure" command decides the locations of almost everything.

I included some example content in the configuration files. Which should be clear enough to set things up correctly. This is provided as is.
The hostname/FQDN of the server in the examples below is : server1.yourdomainname.com. Replace this with your server's real hostname information.
The following 3 configuration files, are created and filled with your server's hostname (FQDN), by the installation script, so nothing to do here. :

Config file me : server1.yourdomainname.com
Config file defaulthost : server1.yourdomainname.com
Config file helohost : server1.yourdomainname.com

The other 6 supplied config files have to be filled by you. When the config file "helohost" is not found, the "nullmailer-send" daemon will create and fill the envvar HELOHOST with the FQDN found in config file "me" and use the envvar to say "HEL(L)O it is I, server1.yourdomainname.com" to the remote mail server.
The only mandatory configuration files are : me, defaulthost, and remote. Fill these correctly to let nullmailer provide its basic functions.
Some example content for the 6 files provided follows. The ".prefab" suffix was dropped during installation. :
The 2 time values (in seconds) were taken from the defaults in the CPP source code.


Config file sendtimeout.prefab : 3600

Config file pausetime.prefab : 60

Config file adminaddr.prefab : admin@**NOT**-yourdomainname.com

Config file defaultdomain.prefab : yourdomainname.com

Config file idhost.prefab : server1

Config file remote.prefab :
#
# Live email servers :
#
# Preferred remote email server to relay to.
smtp.gmail.com smtp --port=587 --auth-login --starttls --insecure --user=ItIsIRene@gmail.com --pass=Secret
# Fallback remote email server #1.
smtp.live.com smtp --port=587 --auth-login --starttls --insecure --user=leftenantGruber@hotmail.com --pass=Geheimnis
# Fallback remote email server #2.
smtp.mail.yahoo.co.uk smtp --port=465 --auth-login --ssl --insecure --user=tv-show@yahoo.com --pass=AlloAllo
# Fallback remote email server #3.
.....
# Fallback remote email server #4.
.....
# Fallback remote email server #5.
.....
# Fallback remote email server #umpteen.
.....
#
# Alternatives or with other options :
#
#smtp.gmail.com smtp --port=465 --auth-login --ssl --insecure --user=myhomies@gmail.com --pass=12?345%6789$0
#smtp.mail.yahoo.com smtp --port=465 --auth-login --ssl --insecure --user=whoever@yahoo.com --pass=12?345%6789$0
#plus.smtp.mail.yahoo.com smtp --port=465 --auth-login --ssl --insecure --user=officialtest@yahoo.com --pass=12?345%6789$0


The binary which is daemonized is named "nullmailer-send".
"nullmailer-send --help" displays help for each parameter/argument.
All parameters/arguments listed below were added. (The original nullmailer-send has no parameters.)


    --logging            : Switches logging of stdout+stderr to log files on. This option on its own is enough to log to the defaults.
-p, --logpath <pathname> : Full path to the directory where the log file(s) should be created. No trailing slash.
                           Default: '/var/log/nullmailer'.
-m, --msglog  <filename> : Filename for message log (stdout) or combined log (stdout+stderr) (see --onelog option).
                           Default: 'nm-s.msg.log'.
-e, --errlog  <filename> : Filename for error log (stderr). Default: 'nm-s.err.log'.
    --onelog             : When specified, indicates that message log and error log will be combined into one log file.
    --help, --?          : Display this help and exit.

All command line options are optional. When not specified the defaults will be used.
Without any command line option, nullmailer-send will revert to default behavior : No redirection of stdout and stderr.
--logging:
        Required to turn on logging to log files.
        When not specified, any other logging options will be ignored.
--logpath:
        When specified, must contain the path to a directory which already exists.
        This directory must be owned by user nullmail, with the permissions 755 (-rwxr-xr-x).
        When not specified, it defaults to path '/var/log/nullmailer'.
        Which is created by the installer 'install_nullmailer.sh' with owner nullmail and permissions 755 (-rwxr-xr-x)
--logpath, --msglog, --errlog:
        Any change from their default value, before and after installation, should always be reflected to their equivalents in the
        start/stop daemon script '/etc/init.d/nullmailer-send'.


The start/stop script which controls the daemon, is also named "nullmailer-send".
The binary's parameters/arguments listed above should be configured in this start/stop script. You must specify them in the variable DAEMON_ARGS.
Or just leave them at the defaults.
When overriding "$logPath" make sure that the directory specified exists, and is owned by user "nullmailer" with 644.
The configurable variables (6) and their defaults are :


40. nm_root=/usr/local # Change this if you specified a different path during installation.
41. nm_config=/usr/local/etc/nullmailer # Change this if you specified a different path during installation.

50. #logPath="/var/log/nullmailer" # Hardcoded in the binary. Only uncomment (and add to DAEMON_ARGS) to override.

52. #msgLog="nm-s.msg.log" # Hardcoded in the binary. Only uncomment (and add to DAEMON_ARGS) to override.
53. #errLog="nm-s.err.log" # Hardcoded in the binary. Only uncomment (and add to DAEMON_ARGS) to override

64. DAEMON_ARGS="--logging --onelog"


After configuring the files and the nullmailer-send daemon script, restart the daemon with : "service nullmailer-send restart".

Testing The Nullmailer Daemon Examples (3) for quick testing provided

You can have more than one remote email server listed in the "remote" config file. When the first fails, the second will be used, and so on. But for the examples I'll assume that Gmail is configured as the preferred remote server. For example with :

smtp.gmail.com smtp --port=587 --auth-login --starttls --insecure --user=your-email@gmail.com --pass=password-for-your-email@gmail.com

When you relay email to Gmail, Yahoo!, Hotmail, etc be prepared to authorize your server when asked. This will be asked at each reception of a relayed batch. Until you Accept and authorize. For example with Gmail a message in a red bar at the top of the screen :

Warning: we prevented a recent suspicious login attempt from: United States (123.456.789.123). Show details and preferences | Ignore


Click "Show details and preferences", check that the IP number and domain name belong to your server, and follow the instructions.
And you will also receive an email message with a title similar to : "Suspicious sign in prevented"

Yahoo! Mail on the other hand, silently refuses your initial relay request(s). You'll have to check the logs for a message similar to this one :

smtp: Failed: 553 From address not verified - see http://help.yahoo.com/l/us/yahoo/mail/original/ manage/sendfrom-07.html


Finally testing time. Check that the nullmailer daemon is running with : "service nullmailer-send status"
Nullmailer's sendmail emulator is a front-end for nullmailer-inject, so that you can keep using your scripts unchanged.
After configuration change the 2 email addresses in the following and copy+paste into a Bash shell and hit [ENTER] to test the nullmailer daemon. :


echo -e "From:Firstname Lastname <me@mydomainname.com>\nTo: Someone Else <somerecipient@someemailserver.com>\n\
Subject: MTA Relay Test\nThis is a test message from ${USER}@${HOSTNAME} at $(date)" | /usr/local/sbin/sendmail -t


or just :


echo -e "From: me@mydomainname.com\nTo: somerecipient@someemailserver.com\n\
Subject: MTA Relay Test\nThis is a test message from ${USER}@${HOSTNAME} at $(date)" | sendmail -t


For when you compose your own messages, when sendmail shows you an error message "Unable to parse the addresses.", check if you have any spaces after a newline ("\n") and delete them. Because Nullmailer's sendmail emulator likes its keywords to start at the first position of a line.
Check the Nullmailer man pages of sendmail and nullmail-inject for what is supported in your email message.

A more comprehensive test email message, mimicking a web form filled out by a visitor to your site:
Amend the following email message (i.e. variables destination, carboncopy1, carboncopy2, and optionally yourdomainname), copy & paste it in a Bash shell, and hit [ENTER]:


originname="Web Form XYZ";\
destinationname="Mrs. Main-Addressee";\
carboncopyname1="Mr. Carbon-Copy";\
carboncopyname2="Mrs. Carbon-Copy";\
\
origin="webform-xyz@$yourdomainname";\
destination=recipient@yahoo.com;\
carboncopy1=cc1-recipient@zonnet.nl;\
carboncopy2=cc2-recipient@hotmail.com;\
\
yourdomainname=yourdomainname.com;\
visitorname="Happy Visitor";\
visitor=happy@visitorsunlimited.com;\
visitorsite="http://visitorsunlimited.com";\
formdatetime="04-08-2012 07:07";\
formtext="Hello,\n\nRequesting a quote for your AAA Server Spit Polishing Service.\n\nRSVP";\
\
emailfile=webformXYZ.email;\
\
echo -e "Subject: $originname relayed from $yourdomainname. $originname completed around $formdatetime by $visitorname" >$emailfile;\
echo -e "From: $originname  <$origin>" >>$emailfile;\
echo -e "To: $destinationname  <$destination>" >>$emailfile;\
echo -e "Cc: $carboncopyname1 <$carboncopy1>,$carboncopyname2 <$carboncopy2>" >>$emailfile;\
echo -e "Bcc:\n\n" >>$emailfile;\
echo -e "Sent at: `date`\n\nFrom: $originname at $yourdomainname\nVisitor name: $visitorname\nVisitor email: $visitor\n\
Visitor website: $visitorsite\nForm date+time: $formdatetime\n\n$formtext" >>$emailfile;\
cat $emailfile | /usr/local/bin/nullmailer-inject -h


For more examples, you could also look in the nullmalier source code directory : "nullmailer-1.13/test".
You will not see anything onscreen, because nulmailer's stdout and stderr are redirected to a file (the default).
So check the log file(s) for error messages if no email arrives at recipients, or no call to action for authorization.
While they're short, display the log files with :


cat /var/log/nullmailer/nm-s.msg.log    # For the stdout log or the combined log (--onelog).
cat /var/log/nullmailer/nm-s.err.log    # For the stderr log.


When you choose to log to 2 separate log files, you will soon find out, that nullmailer is not very precise with where it logs messages. Sometimes non-error messages are logged to stderr. You'll soon end up logging to one file. Which also makes it easier to see the proper sequence in which the messages were logged.

The Nullmailer Daemon Services Command 1 Command, 6 services

The nullmailer daemon listens to the following service commands :


service nullmailer-send
service nullmailer-send start
service nullmailer-send stop
service nullmailer-send status
service nullmailer-send restart
service nullmailer-send force-reload
service nullmailer-send check


Whithout service command specified :
Displays command help : Usage: /etc/init.d/nullmailer-send {start|stop|status|restart|force-reload|check}

start :
Checks that the 3 mandatory config files exist, are not empty, and have the correct ownership and permissions.
Does NOT check the correctness of the content of the config file.
Prints an error message with instructions when a check fails, and does not attempt to start the daemon.
Starts the Nullmailer daemon when all checks are passed.

stop :
Attempts to stop the nullmailer daemon.
Displays a message indicating whether this succeeded or not.

status :
Displays 1 of 3 possible messages :
nullmailer-send is running
Could not access PID file for nullmailer-send.
nullmailer-send is not running

restart :
First performs the same checks as service command "start".
Then attempts to stop the nullmailer daemon.
When stopping the daemon fails, a message is displayed, and no attempt is made to start the daemon.
Starts the Nullmailer daemon if it was successfully stopped.

force-reload :
An alias for service command "restart".

check :
First performs the same checks as service command "start".
When all is OK, nothing will be printed. (Because the accuracy of the contents in the config files is not checked.)

Example Of A Combined Log File ( --logging --onelog ) Zzzzzzzzzz


root@server1:~# cat /var/log/nullmailer/nm-s.msg.log
Rescanning queue.
Trigger pulled.
Rescanning queue.
Starting delivery, 1 message(s) in queue.
Starting delivery: protocol: smtp host: smtp.gmail.com file: 1344813730.24352
smtp: Succeeded: 250 2.0.0 OK 1344813888 qd7sm4810139obc.5
Sent file.
Delivery complete, 0 message(s) remain.
Rescanning queue.
Rescanning queue.
Rescanning queue.
Rescanning queue.
Rescanning queue.
Rescanning queue.
Rescanning queue.
Trigger pulled.
Rescanning queue.
Starting delivery, 1 message(s) in queue.
Starting delivery: protocol: smtp host: smtp.gmail.com file: 1360838322.15581
smtp: Failed: 535-5.7.1 Username and Password not accepted. Learn more at
535 5.7.1 http://support.google.com/mail/bin/answer.py?answer=14257 p7sm64190003vdt.2 - gsmtp
Sending failed: Permanent error in sending the message
Starting delivery: protocol: smtp host: smtp.live.com file: 1360838322.15581
smtp: Succeeded: 250 2.6.0  <1360838322. 899526. 15579.nullmailer@server1.yourdomainname.com> Queued mail for delivery
Sent file.
Delivery complete, 0 message(s) remain.
Rescanning queue.
Starting delivery, 4 message(s) in queue.
Starting delivery: protocol: smtp host: smtp.gmail.com file: 1343901712.1386
smtp: Succeeded: 250 2.0.0 OK 1343907081 i2sm5516763obn.19
Sent file.
Starting delivery: protocol: smtp host: smtp.gmail.com file: 1343901398.1372
smtp: Succeeded: 250 2.0.0 OK 1343907082 ig3sm5525758obb.0
Sent file.
Starting delivery: protocol: smtp host: smtp.gmail.com file: 1343877663.951
smtp: Succeeded: 250 2.0.0 OK 1343907083 ig3sm5525569obb.0
Sent file.
Starting delivery: protocol: smtp host: smtp.gmail.com file: 1343901744.1394
smtp: Succeeded: 250 2.0.0 OK 1343907084 l10sm4212662oeb.13
Sent file.
Delivery complete, 0 message(s) remain.


Running The Uninstaller Uninstalling?

The uninstaller is specific to the nullmailer version it was created for. Do not use it to uninstall another version of nullmailer.
Make sure that you have root access
Make sure that the file named "defines.cc" is in the same directory as the uninstaller.
Check the script before you run it.
Run the uninstallation script from the directory where you unpacked it (e.g. /root/nmi), with :


cd /root/nmi
./uninstall_nullmailer.sh


The uninstaller script will perform a clean uninstall.
Everything installed will be removed, the locate and man databases will be rebuilt.

Screenshots Page subtitle

Download Latest stable release

Without DVCS bloat.

1.13M0 (2013-03-24)
Zipped Up
Zipped 7 Up
Tarred And Feathered
Rarred And Feathered


Bitbucket Repository

Download as: zip tar bz2

Programmer Robert Waarde

<superherowolverine-hacks[at]heeyaahoooooooooooooooooooooooo!.com>

Licensing Allowing great freedom

MIT license
The nullmailer installer
The nullmailer start/stop script (daemonizer)
The nullmailer uninstaller

GPLv2 license, or (at your option) any later version.
The Nullmailer source distribution : nullmailer-1.13.tar.gz
The enhanced Nullmailer "send.cc" file
The copied Nullmailer "defines.cc" file
The copied Nullmailer "diagram" file
Nullmailer is ©(C)opyright Bruce Guenter.

Do Not Copy Be a sport

Do not copy the content of this website.
Do not copy or mirror this entire website.
But feel free to browse the source code to make something original with (parts of) it, elsewhere.

Get in touch!

We'd love to hear from you, you attractive person you.