-
Notifications
You must be signed in to change notification settings - Fork 1
/
README
181 lines (144 loc) · 5.84 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
+ What is pymalist
Pymalist is a minimal and modular mail list software for Python
+ How does pymalist work
pymalist works like this:
# using fetcher it fetches mail
* if NothingMore exception is raised program ends
* if other exception is raised, it is being passed to reactor
and program ends
# mail is processed with processor
# processed mail is distributed with distributor
# go to #1
In component raises an exception (other than NothingMore) it
gets handled by reactor.
You have to supply fetcher, processor, distributor and reactor
objects the the play method. Basically you need to write a few
lines of code to do it, but you can use built-in fetchers,
distributors, processors and reactors.
[[code]]
--------------- ---------------
| | exception | |
| fetcher |--------------->| reactor |
| | | |
--------------- ---------------
| ^ ^
| | |
--------------- | |
| | exception | |
| processor |--------------------- |
| | |
--------------- |
| |
| |
--------------- |
| | exception |
| distributor |---------------------------
| |
---------------
[[/code]]
+ The basic components
The basic fetchers are:
* Pop3Fetcher - to fetch mails from dedicated POP3 account
* StdInFetcher - to get one mail from stdin (from procmail)
The basic distributors are:
* SmtpDistributor - to distribute mails with SMTP server
* MultipleDistributor - distribute mails with many distributors
* DeliverToDistributor - distribute to given list of
recipients using given distributor
The basic processors are:
* SingleListProcessor - used for a sigle list list
(does not check To: header)
* ManyListsProcessor - container of many SingleListProcessors
that directs the mail to be processed
by right one
The basic reactor is:
* StdErrLogger - loggs each exception to standard error
+ Example mail list server
Example script, that fetches all mail from POP3 account processes
two mail lists and distributes mails with SMTP server and send each
copy of mail to archive mail address using the same SMTP distributor
as for distributing the emails to real recipients:
[[code]]
from pymalist import play
from fetchers import *
from processors import *
from distributors import *
from reactors import *
pop3 = Pop3Fetcher(
host = 'pop3.example.com',
user = 'example',
password = 'hackyou',
ssl = True,
)
smtp = SmtpDistributor(
host = 'smtp.example.com',
user = 'example',
password = 'hackyou',
tls = True,
)
play(
fetcher = pop3,
distributor = MultipleDistributor(
smtp,
DeliverToDistributor(['[email protected]'], smtp),
)
processor = MoreListsProcessor(
SingleListProcessor(
list_mail = 'Red mail list <[email protected]>',
subject_prefix = '[Red] ',
subscribers = ['[email protected]', '[email protected]']
),
SingleListProcessor(
list_mail = 'Green mail list <[email protected]>',
subject_prefix = '[Green] ',
subscribers = ['[email protected]', '[email protected]']
),
),
reactor=StdErrLogger(),
)
[[/code]]
You'll want to run the script periodically (for example in cron).
+ Customization or adding new features
If you need another logic to fetch, distribute, process or react
to exceptions, you need to create a custom fetcher, distributor,
processor or reactor.
Every fetcher object must have "fetch" method, that returns
the next mail as a email.Message object. Convert it from message
string by email.message_from_string(message_string). If there
is no new mail, raise fetchers.NothingMore exception.
Every distributor object must have "distribute" method, that
gets mail message (email.Message) with has additional
properties set:
* ml_sender - the original sender
* ml_send_to - addresses to send message to
* ml_list - "Mail List Name" <address@somewhere>
Distributor should distribute the mails (but of course it can
do anything - store, archive, send, play music, eject CD tray
and play 8-bit music on PC speaker).
Every processor must have "process" method, that takes one
argument - the mail message fetched and returns mail message
enhanced with at least ml_sender, ml_send_to and ml_list
properties (see above for explanation). An exception should
be raised if the message should not be distributed because of
some violation (person can't post to list or something). If
message should be delivered, but there is zero recipients,
just set ml_send_to property to empty list: [].
Every reactor implements "react" method that takes two
arguments: type of error (currently string "fetcher",
"processor" or "distributor") and the exception that was
raised. NothingMore exception raised by fetcher is not passed
to reactor.
+ Why did I write this
I wrote this software in a few hours, because I didn't find
any good mail list software that was flexible enough to
* read email from a remote mailbox (with POP3 or IMAP)
* distribute emails with a remote SMTP server (possibly using
the same mailbox)
* require no root permissions
* is modular enough
I know my mail list is not perfect, because it has no
input/output queues, no (un)subscribe features nor mail
archive, but using the concepts of fetchers, distributors,
processors and reactors they can be easily plugged-in.
Author: Piotr Gabryjeluk
Started: 22 May 2009