initial commit

This commit is contained in:
itismadness
2018-02-20 16:57:50 +12:00
committed by Matthew Peveler
commit 032536ccc9
7 changed files with 123 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
__pycache__/
messages/*
!messages/.gitkeep
.idea/

29
README.md Normal file
View File

@@ -0,0 +1,29 @@
PostBox
=======
Smtpd server (via [aiosmtpd](https://github.com/aio-libs/aiosmtpd)) with a [falcon](https://falconframework.org/)
frontend. Incoming messages are saved as serialized JSON objects in the `messages/` folder.
Requirements
------------
* Python 3.5+
* aiosmtpd
* falcon
Installation
------------
```
pip3 install -r requirements.txt
```
Usage
-----
To start the smtpd server:
```
./smtpd.py
```
To start the web API:
```
gunicorn -b '127.0.0.1:8000' server:application
```

22
generate_mail.py Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env python3
from datetime import datetime
import json
import uuid
import os
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return json.JSONEncoder.default(self, obj)
with open(os.path.join('messages', str(uuid.uuid4().hex)), 'w') as open_file:
json.dump({'mail_from': 'test@example.com',
'rcpt_tos': 'person@example.com',
'message': 'This is an email message!',
'timestamp': datetime.utcnow().isoformat()},
open_file,
cls=DateTimeEncoder)

0
messages/.gitkeep Normal file
View File

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
falcon
aiosmtpd
gunicorn

26
server.py Normal file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env python3
import json
import os
import falcon
DATA_PATH = 'messages'
class Resource(object):
# noinspection PyMethodMayBeStatic
def on_get(self, _, resp):
response = []
for entry in os.scandir(DATA_PATH):
if entry.name == '.gitkeep':
continue
with open(entry.path) as open_file:
response.append(json.load(open_file))
os.remove(entry.path)
resp.body = str.encode(json.dumps(response))
resp.status = falcon.HTTP_200
application = falcon.API()
application.add_route('/', Resource())

39
smtpd.py Executable file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env python3
from datetime import datetime
import json
import os
import uuid
from aiosmtpd.controller import Controller
HOST = '127.0.0.1'
PORT = 10025
DATA_PATH = 'messages'
class Handler(object):
# noinspection PyPep8Naming,PyMethodMayBeStatic
async def handle_DATA(self, _, session, envelope):
# noinspection PyBroadException
try:
with open(os.path.join('messages', str(uuid.uuid4().hex)), 'w') as open_file:
json.dump({'mail_from': envelope.mail_from,
'rcpt_tos': envelope.rcpt_tos,
'message': envelope.content.decode('utf-8'),
'timestamp': datetime.utcnow().isoformat()},
open_file)
return '250 OK'
except Exception:
return '500 Could not process your message'
if __name__ == '__main__':
handler = Handler()
controller = Controller(handler, hostname='127.0.0.1', port=10025)
# noinspection PyBroadException
try:
controller.start()
input('Running smtpd server on {}:{}'.format(HOST, PORT))
except Exception:
controller.stop()