Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: TK-IT/mail
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: matfystutor/mail
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.

Commits on May 1, 2015

  1. Copy the full SHA
    648d3e6 View commit details
  2. Copy the full SHA
    ae039b1 View commit details
  3. Add tutormail/__init__.py

    Mortal committed May 1, 2015
    Copy the full SHA
    161fda0 View commit details
  4. Copy the full SHA
    1592c8e View commit details
  5. Copy the full SHA
    e7ba25d View commit details
  6. Copy the full SHA
    6321da2 View commit details
  7. Remove envelope line from message

    This appears in Python 2 and not in Python 3 for some reason
    Mortal committed May 1, 2015
    Copy the full SHA
    911f831 View commit details
  8. Copy the full SHA
    39c1ef6 View commit details
  9. No policy in Python 2

    Mortal committed May 1, 2015
    Copy the full SHA
    c896ece View commit details
  10. Fix tutormail

    Mortal committed May 1, 2015
    Copy the full SHA
    174e295 View commit details
  11. Add tutormail/__main__.py

    Mortal committed May 1, 2015
    Copy the full SHA
    5e0b349 View commit details
  12. Copy the full SHA
    e1a040d View commit details
  13. Copy the full SHA
    76cea8f View commit details
  14. Copy the full SHA
    1f63a28 View commit details

Commits on May 2, 2015

  1. Copy the full SHA
    49268ae View commit details
  2. Normalize leading whitespace

    Mortal committed May 2, 2015
    Copy the full SHA
    97defeb View commit details
  3. Copy the full SHA
    ee99a63 View commit details
  4. Copy the full SHA
    9218118 View commit details
  5. Copy the full SHA
    6048cfa View commit details
  6. Copy the full SHA
    bcacba0 View commit details
  7. Remove debug logging

    Mortal committed May 2, 2015
    Copy the full SHA
    429287e View commit details

Commits on May 3, 2015

  1. Copy the full SHA
    5b04a68 View commit details

Commits on Jul 9, 2015

  1. TutorGroup has a year now!

    Mortal committed Jul 9, 2015
    Copy the full SHA
    aef41d2 View commit details

Commits on Dec 9, 2016

  1. Tweak sys.path

    Mortal committed Dec 9, 2016
    Copy the full SHA
    5a94160 View commit details
  2. Copy the full SHA
    139ab4c View commit details
  3. Copy the full SHA
    ea4ec93 View commit details
  4. Copy the full SHA
    e968f18 View commit details

Commits on May 17, 2017

  1. Copy the full SHA
    1a0acd5 View commit details
  2. Use MailholeRelayMixin

    Mortal committed May 17, 2017
    Copy the full SHA
    ac4a113 View commit details
  3. Fixes for Python 2

    Mortal committed May 17, 2017
    Copy the full SHA
    f04a260 View commit details
  4. Add ravtest special case

    Mortal committed May 17, 2017
    Copy the full SHA
    4da82b5 View commit details
  5. Add log message

    Mortal committed May 17, 2017
    Copy the full SHA
    95bbc26 View commit details

Commits on Jul 5, 2017

  1. Copy the full SHA
    41c132e View commit details
  2. Copy the full SHA
    5e29e67 View commit details
  3. fixup

    Mortal committed Jul 5, 2017
    Copy the full SHA
    77452f5 View commit details
  4. Add missing import

    Mortal committed Jul 5, 2017
    Copy the full SHA
    c7b471c View commit details
  5. Fix for Python 2

    Mortal committed Jul 5, 2017
    Copy the full SHA
    0f2c8d4 View commit details

Commits on Jul 30, 2017

  1. Copy the full SHA
    8b238e3 View commit details
  2. Refactor

    Mortal committed Jul 30, 2017
    Copy the full SHA
    152b6c1 View commit details
  3. Copy the full SHA
    060697d View commit details
  4. Copy the full SHA
    c37da23 View commit details
  5. Only log from emailtunnel

    Mortal committed Jul 30, 2017
    Copy the full SHA
    4cfce69 View commit details
  6. Listen on all interfaces

    Mortal committed Jul 30, 2017
    Copy the full SHA
    34a6a19 View commit details
  7. Copy the full SHA
    2192742 View commit details
  8. Copy the full SHA
    5b8a66c View commit details
  9. Remove tkmail fork

    Mortal committed Jul 30, 2017
    Copy the full SHA
    6a6f614 View commit details
  10. Copy the full SHA
    f0a71c3 View commit details
  11. WIP new README

    Mortal committed Jul 30, 2017
    Copy the full SHA
    07852c3 View commit details
  12. Send eveyrhting to mailhole

    Mortal committed Jul 30, 2017
    Copy the full SHA
    e0d2bbf View commit details
  13. Refactor handle_envelope

    Mortal committed Jul 30, 2017
    Copy the full SHA
    4806574 View commit details
Showing with 796 additions and 1,840 deletions.
  1. +37 −98 README.md
  2. +0 −515 emailtunnel/__init__.py
  3. +0 −60 emailtunnel/__main__.py
  4. +0 −124 emailtunnel/send.py
  5. +59 −0 insane.py
  6. +1 −0 prodekanus/mailhole_key.env.sample
  7. +0 −56 tkmail/__main__.py
  8. +0 −203 tkmail/address.py
  9. +0 −131 tkmail/database.py
  10. +0 −184 tkmail/monitor.py
  11. +0 −234 tkmail/server.py
  12. +0 −235 tkmail/test.py
  13. +14 −0 tutormail.service
  14. 0 {tkmail → tutormail}/__init__.py
  15. +59 −0 tutormail/__main__.py
  16. +377 −0 tutormail/server.py
  17. +249 −0 tutormail/test.py
135 changes: 37 additions & 98 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,113 +1,52 @@
## 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 = {
'admin@maillist.local': ['c2h5oh@example.com'],
'luser@maillist.local': ['noreply@yahoo.com'],
'all@maillist.local': ['c2h5oh@example.com', 'noreply@yahoo.com'],
}
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.


### 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`.
Når mailserveren starter op, skriver den noget à la:

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.
`TutorForwarder listening on 0.0.0.0:9001, relaying to mailhole.
Year from mftutor.settings: (2018, 2017, 2017)`

The `tkmail.test` module starts an instance of `TKForwarder`,
feeds it test messages and checks the relayed messages for correctness.
Tuplen `(2018, 2017, 2017)` betyder at GF-året er sat til 2018;
tutoråret til 2017; og rusåret til 2017.
Det betyder 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.

Det betyder desuden at når man
**ændrer på GF-året/tutoråret/rusåret, skal mailserveren genstartes**.

### SMTPForwarder logic
Emails bliver videresendt til mailhole på https://mail.tket.dk
hvorfra de bliver videresendt til tutorer og russer.
Her skal `MAILHOLE_KEY` ovenfor
sættes til en nøgle der også er konfigureret i mailhole.

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.
Emaillister hentes direkte fra Django-databasen
ved at importere `mftutor.tutor.models`
og lave Django queryset-opslag.

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.
Den overordnede metode er `translate_recipient()`
i `TutorForwarder` i `tutormail/server.py`.
Her implementeres logikken der følger gruppealiaser,
finder passende grupper i passende årgange,
og finder tutorers emailadresser.
Desuden er der logik til at finde rushold/holdtutorers emailadresser.

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.

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.
## Delivery status notifications

If `InvalidRecipient` is raised during `get_envelope_recipients`, SMTP error
550 is returned to the SMTP peer (mailbox unavailable) and no email is relayed.
Når en DSN (delivery status notification) sendes retur til webfar@matfystutor.dk
bliver den fanget i `error`-mappen af mailserveren.
Det sker via `TutorForwarder.reject()` metoden.
Loading