Round-trip Email Monitoring on the Cheap
About a year ago, I decided to set up an email server for a couple of my personal domains. I knew it would be a technical challenge, but I wanted the privacy, control, and storage offered by the Linode I was already paying for.
My biggest concern was downtime. According to RFC 5321, failed mail should be retried for 4-5 days, so as long as I can fix things in a day or so, important mail shouldn't be lost. I'm not a big corporation with lots on the line if the mail server goes down. I just need to know within a reasonable time if my mail server stops working so I can fix it.
I set up MXToolbox first, and the primary benefit to me was its ability to monitor the SMTP connection to the server and let me know if it couldn't connect. I found MXAlerts later, and thought the idea was great: set up a mailbox on the server that forwards back to them. They send an email every 30 minutes, and if they don't get the forwarded message within 10 minutes, they send out an alert.
I configured both services to alert me at my SMS gateway email address, so, in effect, I get paged when the mail stops flowing.
Last month, I received an email from MXAlerts with the subject 'Important changes to the MXAlerts Free Account' in which I was notified that 'we are no longer able to offer the MXAlerts free account after December 8, 2014'. Well, that's quite an important change to a free account!
For me, frugality is the mother of invention.
I got to thinking. All I need is a test email to be sent at some interval and to be notified if it isn't received, but I can't run such a service from the very server I'm monitoring.
It occurred to me that services like Google App Engine, Heroku, Engine Yard have free tiers. I could make a simple app that worked for my needs as long as they could do the following within their free limits:
- Send email
- Receive email
- Store records of email tests (AKA probes)
- Run scheduled tasks
I never got farther than App Engine. It has everything I need, with incoming mail delivered as HTTP requests and a simple configuration for cron tasks.
The result is mxflow, a very small Python app that I've been running for the last couple of weeks.
So far, so good. It's rudimentary at the moment, but it does what I need. To stay under the quota limits, I have it configured to send mail probes every 30 minutes and to check every 5 minutes for expired probes.
The app consumes negligible amounts of all but two quotas: outgoing email and instance hours.
Google's current quotas for their free tier are:
- Outgoing email: 100/day
- Instance hours: 28/day
According to reports for the last two weeks, the app uses ~24/28 instance hours and 48/100 outgoing emails.
Instance hours are consistent, and apart from a touch of mystery, make sense to me. Because of the cron task running every 5 minutes to check for expired probes, the app can never really idle, so it's running 24/7. At some point I'd like to look into the Task Queue to remove the need for that cron task, and since instance hours are measured in 15 minute increments, I may be able to halve the instance hours.
Outgoing email is a bigger concern. For an app that sends email as its primary task, a limit of 100 per day is a pretty big handicap. I'd send probes more often if not for that. I could up it to every 15 minutes (96 per day), but since the alert emails also count toward the quota, I'd hate to hit the quota when I needed it most.
According to the docs, the mail quota may be increased if billing is enabled (i.e. you give Google your credit card info) to 20,000 per day, so that would take care of that. Since mxflow can monitor multiple servers, raising the mail sending limit is pretty much a requirement for monitoring more than one mail server.
In the hopes that other users with similar modest mail flow monitoring needs would find this useful, the source is available on github.
For me, this is a cheap, effective alternative to MXAlerts or MailFlow Monitoring from MxToolBox.
Thanks MXAlerts, for giving me a reason to finally try out App Engine and use Python in a project!