Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dpapathanasiou/intelligent-smtp-responder

This is an intelligent email-based agent server
https://github.com/dpapathanasiou/intelligent-smtp-responder

Last synced: about 2 months ago
JSON representation

This is an intelligent email-based agent server

Awesome Lists containing this project

README

        

intelligent-smtp-responder
==========================

About
-----

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](agents/weather_response_example.py), 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](agents/weather_response_example.py#L79), 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](http://paultyma.blogspot.com/) [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]( http://denis.papathanasiou.org/2011/11/11/re-creating-mailinator-in-python/).

It also forms the basis for the server used by the [TeamWork.io]
(http://teamwork.io/) and [ReadZap.com](http://readzap.com/) web services.

Installation
------------

Clone this repo, and make sure you have [pycurl](http://pycurl.sourceforge.net/) and [lxml](http://lxml.de/) installed (using [pip](http://www.pip-installer.org/en/latest/) is recommended):

```
git clone https://github.com/dpapathanasiou/intelligent-smtp-responder.git
sudo pip install pycurl
sudo pip install lxml
```

Optionally install [libmagic](http://sourceforge.net/projects/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
```

Important: there is a suble but important difference between [the package available via pip](http://pypi.python.org/pypi/python-magic/) versus [what apt installs](http://packages.ubuntu.com/search?keywords=python-magic). The code in [emailer.py](utils/emailer.py) depends on the latter.

Getting Started
---------------

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](http://www.postfix.org/) installed and running.

1. Edit the [config.py](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 protected]"
smtp_server_domain = "example.org"
pass_through_target = "[email protected]"
```
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](http://www.sparklewise.com/django-settings-for-production-and-development-best-practices/) applied to this project).

2. Edit the action_mailboxes dict in the [config.py](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](agents) folder.

See the [notes there](agents/responders.py#L74) for the class and functional prototype requirements, and also look at the [time](agents/time_response_example.py) and [weather](agents/weather_response_example.py) response examples.

3. (optional) Edit the pass_through_mailboxes list in the [config.py](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.

4. (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.

5. Redirect port 25 (smtp) traffic

a. IPv4 servers

Run the [set_iptables.sh](set_iptables.sh) script as root or sudo:

```
sh ./set_iptables.sh
```

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:

```sh
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules
```

For more details on this option, read:

[http://articles.slicehost.com/2011/2/21/introducing-iptables-part-3](http://articles.slicehost.com/2011/2/21/introducing-iptables-part-3) or
[https://wiki.debian.org/iptables](https://wiki.debian.org/iptables)

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](http://gmail.com), use IPv6 if available.*

Run the [set_ip6tables.sh](set_ip6tables.sh) script as root or sudo:

```
sh ./set_ip6tables.sh
```

As with [set_iptables.sh](set_iptables.sh), the default port for redirecting incoming traffic is 8888, but you can change that as necessary.

*__Note:__ If you change the port in [set_iptables.sh](set_iptables.sh) it __must__ be the same as the one in the [set_ip6tables.sh](set_ip6tables.sh) script.*

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:

```sh
#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules
/sbin/ip6tables-restore < /etc/ip6tables.up.rules
```

6. Edit the [run_smtps.sh](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:
```sh
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:
```sh
mail -s "SMTP server error!" [email protected] < /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.

7. Start the server as root/sudo using the [run_smtps.sh](run_smtps.sh) file:
```sh
sh ./run_smtps.sh
```

If you'll be running it long-term, it's best to kick this off inside a [screen session](http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/virtual-terminals.html), from which you can detach.

Acknowledgements
----------------

* [Paul Tyma](http://paultyma.blogspot.com/) for his description of how [Mailinator](http://mailinator.com/) works
* [Ian Lewis](https://github.com/IanLewis) for the [email parsing logic](http://www.ianlewis.org/en/parsing-email-attachments-python) in the [email_parser.py](server/email_parser.py) file
* [David Mertz](http://www.gnosis.cx/) for his article [Charming Python: Using state machines](http://www.ibm.com/developerworks/library/l-python-state/index.html) which is the basis of the [statemachine.py](server/statemachine.py) code
* The folks at [hostip.info](http://www.hostip.info/) for their simple and elegant [ip address geolocation API](http://www.hostip.info/use.html)
* [Forecast.io](http://forecast.io/) for their [weather report API](https://developer.forecast.io/) which is used in [the more "intelligent" weather responder example](agents/weather_response_example.py#L79)