This is an intelligent email-based agent server, written in Python, using state machine logic to handle the SMTP protocol.
The server works by responding to email sent to designated inboxes with canned, dynamic, or custom replies.
Among the included examples, email sent to nyc-weather@ will be automatically replied with the current weather forecast for NYC, using data from the National Weather Service website.
Email sent to just weather@ will return a report based on the sender's physical location, automatically determined from the email headers.
With the exception of the latter, more "intelligent" weather responder example, the basic examples do not take account the sender, subject, or email message text, but the server can be extended with natural language processing and other AI techniques to provide more customized auto-replies.
This code is loosely based on Paul Tyma's [Mailinator] (http://mailinator.com/) in that it does not support the full range of SMTP commands, and instead uses ip traps and timeouts to foil spammers and other scripts or bots, continuing the work described here.
git clone https://github.com/dpapathanasiou/intelligent-smtp-responder.git sudo pip install pycurl sudo pip install lxml
Optionally install libmagic for python since it is helpful for identifying mime types found in email messages (though this code will run without it):
sudo apt-get install python-magic
Note that this server listens to incoming requests, but it does NOT provide a way to send outbound emails, so make sure you have a outgoing mail server such as Postfix installed and running.
- Edit the config.py file in this folder and redefine these variables with your server's domain instead of example.org:
domain_logo = "example.org" server_auto_email = "email@example.com" smtp_server_domain = "example.org" pass_through_target = "firstname.lastname@example.org"
Ideally, the pass_through_target email address resides on a different server than the one running this code.
You can also define a local_config.py file with environment-specific configuration settings which is exempt from source control (this is basically the django local settings approach applied to this project).
- Edit the action_mailboxes dict in the config.py file.
Each key is the name of the inbox you want the server to auto-respond to, and the value is the name of the module.class which is instantiated to carry out the request.
Each class needs to be implemented or referenced in the agents folder.
- (optional) Edit the pass_through_mailboxes list in the config.py file.
These are the inboxes which the server ignores, and just passes through to the email address defined by the pass_through_target variable.
- (optional) For logging, set the smtp_server_debug variable to True
This will record the ip address, timestamp, and all commands up to DATA sent to the server by each client.
- Redirect port 25 (smtp) traffic
a. IPv4 servers
Run the set_iptables.sh script as root or sudo:
The default port for redirecting incoming traffic is 8888, but you can change that as necessary.
Optionally, create an /etc/iptables.up.rules file, so that the redirect takes effect on reboots:
iptables-save > /etc/iptables.up.rules vi /etc/network/if-pre-up.d/iptables chmod +x /etc/network/if-pre-up.d/iptables
Where the /etc/network/if-pre-up.d/iptables file contains:
#!/bin/sh /sbin/iptables-restore < /etc/iptables.up.rules
For more details on this option, read:
You can always undo the iptables setting by running the unset_iptables.sh script as root/sudo (remember to remove or edit /etc/iptables.up.rules as well, if you chose that option initially).
b. IPv6 servers
If the server you are running this software also accepts IPv6 traffic, then you will need to do the following steps as well, since some email senders, notably Google's gmail, use IPv6 if available.
Run the set_ip6tables.sh script as root or sudo:
As with set_iptables.sh, the default port for redirecting incoming traffic is 8888, but you can change that as necessary.
As as before, create an /etc/ip6tables.up.rules file, so that the redirect takes effect on reboots:
ip6tables-save > /etc/ip6tables.up.rules vi /etc/network/if-pre-up.d/iptables
And update the /etc/network/if-pre-up.d/iptables file to contain a third line, like so:
#!/bin/sh /sbin/iptables-restore < /etc/iptables.up.rules /sbin/ip6tables-restore < /etc/ip6tables.up.rules
- Edit the run_smtps.sh file.
By default, the server runs as user daemon, but if your auto-responder agents need access to different resources/user groups, just change the user defined at the end of this line:
su -c "export PYTHONPATH=$PYTHONPATH:$smtps:$smtps/server:$smtps/utils:$smtps/agents; python -c 'import smtp_server; smtp_server.start()' > /tmp/smtp_server_$logfile.log 2>&1" daemon
The script is designed to restart in case of an error, and if you'd like to get the log by email when that happens, change the target email address in this line:
mail -s "SMTP server error!" email@example.com < /tmp/smtp_server_$logfile.log
Note that logfiles do not over-write each other, so you can remove that line altogether, if you'd rather not get the alert.
- Start the server as root/sudo using the run_smtps.sh file:
If you'll be running it long-term, it's best to kick this off inside a screen session, from which you can detach.
- Paul Tyma for his description of how Mailinator works
- Ian Lewis for the email parsing logic in the email_parser.py file
- David Mertz for his article Charming Python: Using state machines which is the basis of the statemachine.py code
- The folks at hostip.info for their simple and elegant ip address geolocation API
- Forecast.io for their weather report API which is used in the more "intelligent" weather responder example