Skip to content

Commit

Permalink
WIP new README
Browse files Browse the repository at this point in the history
  • Loading branch information
Mortal committed Jul 30, 2017
1 parent f0a71c3 commit 07852c3
Showing 1 changed file with 21 additions and 103 deletions.
124 changes: 21 additions & 103 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,113 +1,31 @@
## A lightweight email forwarding framework
# Tutorgruppens mailsystem

### Introduction
Mailsystemet er bygget ovenpå
[emailtunnel](https://github.com/TK-IT/emailtunnel)
som i sig selv bygger ovenpå
[aiosmtpd](https://github.com/aio-libs/aiosmtpd).

`emailtunnel` is a small Python 3 framework that uses the `smtpd`, `smtplib`
and `email` modules in the Python standard library to implement simple mailing
list forwarding.

The user must supply a function that maps symbolic recipient addresses on their
own domain to user email addresses.

A simple example, operating on the domain `maillist.local` with two users
and three lists:
Mailserveren køres således:

```
USERS = {
'[email protected]': ['[email protected]'],
'[email protected]': ['[email protected]'],
'[email protected]': ['[email protected]', '[email protected]'],
}
class SimpleForwarder(emailtunnel.SMTPForwarder):
def translate_recipient(self, rcptto):
try:
return USERS[rcptto]
except KeyError:
raise emailtunnel.InvalidRecipient(rcptto)
def translate_subject(self, envelope):
return '[Simple-List] %s' % envelope.message.subject
cd path/to/tutormail
. venv/bin/activate
MAILHOLE_KEY=my_mailhole_key python -m tutormail -d path/to/tutorweb
```

The `translate_recipient` method either returns a list of external recipients
to relay the envelope to, or the empty list to silently drop the email,
or it may raise `InvalidRecipient` to respond with SMTP error 550.
If another exception is raised while processing the message,
emailtunnel responds to the SMTP peer with SMTP error 451,
indicating that the error is temporary, and the peer should try again later.
In this case, the application should override `handle_error` to inform the
local admin of the failure.


### Repository overview

The framework is implemented in `emailtunnel/__init__.py`,
implementing the following classes:

* InvalidRecipient (exception)
* Message (encapsulating an instance of `email.message.Message`)
* Envelope (encapsulating a Message, a recipient and a sender)
* SMTPReceiver (abstract subclass of `smtpd.SMTPServer`)
* LoggingReceiver (simple implementation of SMTPReceiver)
* RelayMixin (mixin providing envelope delivery to a relay)
* SMTPForwarder (subclass of SMTPReceiver)

The framework may be tested by running `python -m emailtunnel --help`,
which runs the code in `emailtunnel/__main__.py`
that allows simple logging and relaying of emails.

The `emailtunnel.send` module may be run from the command line to send simple
emails specified via command line parameters and standard input.

Når mailserveren starter op, skriver den noget à la:

### Application example

The `tkmail.server` module implements `TKForwarder`, an application of
`emailtunnel.SMTPForwarder`.

It supports logging of exceptions and misdeliveries to a list of admins,
and it uses the `tkmail.address` module to perform delicate parsing of
recipient addresses.

The `TKForwarder` is started by running the `tkmail` module from the command
line by calling `python -m tkmail --help`.

The `tkmail.monitor` module is designed to be run daily from a cron job,
and it checks the error directory and sends a report to admins.

The `tkmail.test` module starts an instance of `TKForwarder`,
feeds it test messages and checks the relayed messages for correctness.


### SMTPForwarder logic

The main entry point from the `smtpd` module is `SMTPReceiver.process_message`.
First, the message data is stored in an instance of `Message`,
which performs a sanity roundtrip parsing check to make sure that
`data == str(Message(data))` modulo trailing whitespace.

Then, the envelope is passed to `handle_envelope`,
which is implemented in a subclass (such as SMTPForwarder).
If `handle_envelope` returns None, `smtpd` assumes that the envelope was
successfully delivered.
Otherwise, it must return a string, which is returned to the SMTP remote peer.
If an exception occurs in `handle_envelope`, SMTP error 451 is returned to the
peer ("Requested action aborted: error in processing").
The subclass may implement `handle_error` to do further logging.
```
TutorForwarder listening on 0.0.0.0:9001, relaying to port 25, Year from mftutor.settings: (2018, 2017, 2017)
```

The `SMTPForwarder` class implements `handle_envelope`
by transforming the Subject via `translate_subject` in the subclass
and by transforming the list of recipients via `get_envelope_recipients`.
The default implementation of `get_envelope_recipients` transforms each
recipient using `translate_recipient`, which is the identity map by default.
The forwarded envelope has the sender provided in `get_envelope_mailfrom`.
The default implementation of `get_envelope_mailfrom` returns the sender
of the incoming envelope as the outgoing sender.
Tuplen `(2018, 2017, 2017)` betyder at GF-året er sat til 2018;
tutoråret til 2017; og rusåret til 2017.
Det betyder med andre ord, at emails til GF-bestemte grupper
(best, koor, webfar, og andre) skal sendes til 2018-grupper;
emails til 1. stormøde-bestemte grupper (dvs. de fleste) skal sendes til
2017-grupper; emails til rushold og holdtutorer skal sendes til 2017-lister.

The envelope is passed on with only the subject changed
using `RelayMixin.deliver`, which requires the attributes
`relay_host` and `relay_port` to be set.

If `InvalidRecipient` is raised during `get_envelope_recipients`, SMTP error
550 is returned to the SMTP peer (mailbox unavailable) and no email is relayed.
I `tutormail/server.py` defineres klassen `TutorForwarder`
som står for at modtage og videresende emails.

0 comments on commit 07852c3

Please sign in to comment.