]>
Commit | Line | Data |
---|---|---|
a854f5b3 ER |
1 | #! /usr/bin/python |
2 | # | |
3 | # Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. | |
4 | # | |
5 | # This program is free software; you can redistribute it and/or | |
6 | # modify it under the terms of the GNU General Public License | |
7 | # as published by the Free Software Foundation; either version 2 | |
8 | # of the License, or (at your option) any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
16 | # along with this program; if not, write to the Free Software | |
17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | # | |
19 | # argv[1] should be the name of the list. | |
20 | ||
21 | # Make sure that the list of email addresses doesn't contain any comments, | |
22 | # like majordomo may throw in. For now, you just have to remove them manually. | |
23 | ||
24 | """Add nonmembers to a list from the command line. | |
25 | ||
26 | Usage: | |
27 | add_nonmembers [options] listname | |
28 | ||
29 | Options: | |
30 | ||
31 | --accepted-file=file | |
32 | -a file | |
33 | A file containing addresses of the members to be added, | |
34 | one address per line, to the list of postings which are | |
35 | automatically accepted. If file is `-', read addresses | |
36 | from stdin. | |
37 | ||
38 | --moderated-file=file | |
39 | -m file | |
40 | A file containing addresses of the members to be added, | |
41 | one address per line, to the list of postings which are | |
42 | held for moderation. If file is `-', read addresses | |
43 | from stdin. | |
44 | ||
45 | --rejected-file=file | |
46 | -r file | |
47 | A file containing addresses of the members to be added, | |
48 | one address per line, to the list of postings which are | |
49 | automatically rejected. If file is `-', read addresses | |
50 | from stdin. | |
51 | ||
52 | --discarded-file=file | |
53 | -d file | |
54 | A file containing addresses of the members to be added, | |
55 | one address per line, to the list of postings which are | |
56 | automatically discarded. If file is `-', read addresses | |
57 | from stdin. | |
58 | ||
59 | --empty | |
60 | -e | |
61 | Empty all current addresses from the list before adding | |
62 | new addresses. | |
63 | ||
64 | --verbose | |
65 | -v | |
66 | Verbose output. Display messages stating whether each | |
67 | address was added or already in a list | |
68 | ||
69 | --help | |
70 | -h | |
71 | Print this help message and exit. | |
72 | ||
73 | listname | |
74 | The name of the Mailman list you are adding members to. It must | |
75 | already exist. | |
76 | ||
77 | You must supply at least one of -n and -d options. At most one of the | |
78 | files can be `-'. | |
79 | """ | |
80 | ||
81 | import sys | |
82 | import os | |
83 | import getopt | |
84 | from cStringIO import StringIO | |
85 | ||
86 | import paths | |
87 | # Import this /after/ paths so that the sys.path is properly hacked | |
88 | from email.Utils import parseaddr | |
89 | ||
90 | from Mailman import MailList | |
91 | from Mailman import Utils | |
92 | from Mailman import Message | |
93 | from Mailman import Errors | |
94 | from Mailman import mm_cfg | |
95 | from Mailman import i18n | |
96 | ||
97 | _ = i18n._ | |
98 | ||
99 | ||
100 | \f | |
101 | def usage(status, msg=''): | |
102 | print >> sys.stderr, _(__doc__) | |
103 | if msg: | |
104 | print >> sys.stderr, msg | |
105 | sys.exit(status) | |
106 | ||
107 | ||
108 | \f | |
109 | def readfile(filename): | |
110 | if filename == '-': | |
111 | fp = sys.stdin | |
112 | closep = 0 | |
113 | else: | |
114 | fp = open(filename) | |
115 | closep = 1 | |
116 | # strip all the lines of whitespace and discard blank lines | |
117 | lines = filter(None, [line.strip() for line in fp.readlines()]) | |
118 | if closep: | |
119 | fp.close() | |
120 | return lines | |
121 | ||
122 | ||
123 | \f | |
124 | class Tee: | |
125 | def __init__(self, outfp): | |
126 | self.__outfp = outfp | |
127 | ||
128 | def write(self, msg): | |
129 | sys.stdout.write(msg) | |
130 | self.__outfp.write(msg) | |
131 | ||
132 | ||
133 | class UserDesc: pass | |
134 | ||
135 | ||
136 | \f | |
137 | def addall(mlist, submlist, list, members, verbose, outfp): | |
138 | tee = Tee(outfp) | |
139 | ||
140 | for member in members: | |
141 | if member in mlist.accept_these_nonmembers: | |
142 | if verbose: | |
143 | print >> tee, _('%(list)s: already in accept_these_nonmembers: %(member)s') | |
144 | elif member in mlist.hold_these_nonmembers: | |
145 | if verbose: | |
146 | print >> tee, _('%(list)s: already in hold_these_nonmembers: %(member)s') | |
147 | elif member in mlist.reject_these_nonmembers: | |
148 | if verbose: | |
149 | print >> tee, _('%(list)s: already in reject_these_nonmembers: %(member)s') | |
150 | elif member in mlist.discard_these_nonmembers: | |
151 | if verbose: | |
152 | print >> tee, _('%(list)s: already in discard_these_nonmembers: %(member)s') | |
153 | else: | |
154 | submlist.append(member) | |
155 | if verbose: | |
156 | print >> tee, _('%(list)s: added: %(member)s') | |
157 | ||
158 | return submlist | |
159 | ||
160 | \f | |
161 | def main(): | |
162 | try: | |
163 | opts, args = getopt.getopt(sys.argv[1:], | |
164 | 'a:m:r:d:ehv', | |
165 | ['accepted-file=', | |
166 | 'moderated-file=', | |
167 | 'rejected-file=', | |
168 | 'discarded-file=', | |
169 | 'empty-list', | |
170 | 'verbose', | |
171 | 'help']) | |
172 | except getopt.error, msg: | |
173 | usage(1, msg) | |
174 | ||
175 | if len(args) <> 1: | |
176 | usage(1) | |
177 | ||
178 | listname = args[0].lower().strip() | |
179 | afile = None | |
180 | mfile = None | |
181 | rfile = None | |
182 | dfile = None | |
183 | verbose = 0 | |
184 | empty = 0 | |
185 | stdin = 0 | |
186 | for opt, arg in opts: | |
187 | if opt in ('-h', '--help'): | |
188 | usage(0) | |
189 | elif opt in ('-a', '--accepted-file'): | |
190 | afile = arg | |
191 | if afile == "-": | |
192 | stdin += 1 | |
193 | elif opt in ('-m', '--moderated-file'): | |
194 | mfile = arg | |
195 | if mfile == "-": | |
196 | stdin += 1 | |
197 | elif opt in ('-r', '--rejected-file'): | |
198 | rfile = arg | |
199 | if rfile == "-": | |
200 | stdin += 1 | |
201 | elif opt in ('-d', '--discarded-file'): | |
202 | dfile = arg | |
203 | if dfile == "-": | |
204 | stdin += 1 | |
205 | elif opt in ('-e', '--empty-list'): | |
206 | empty = 1 | |
207 | elif opt in ('-v', '--verbose'): | |
208 | verbose = 1 | |
209 | ||
210 | if afile is None and mfile is None and rfile is None and dfile is None: | |
211 | usage(1) | |
212 | ||
213 | if stdin > 1: | |
214 | usage(1, _('Cannot read more than one list of members ' | |
215 | 'from standard input.')) | |
216 | ||
217 | try: | |
218 | mlist = MailList.MailList(listname) | |
219 | except Errors.MMUnknownListError: | |
220 | usage(1, _('No such list: %(listname)s')) | |
221 | ||
222 | otrans = i18n.get_translation() | |
223 | ||
224 | # Read the member files | |
225 | try: | |
226 | amembers = [] | |
227 | mmembers = [] | |
228 | rmembers = [] | |
229 | dmembers = [] | |
230 | if afile: | |
231 | amembers = readfile(afile) | |
232 | if empty: | |
233 | mlist.accept_these_nonmembers = [] | |
234 | if mfile: | |
235 | mmembers = readfile(mfile) | |
236 | if empty: | |
237 | mlist.hold_these_nonmembers = [] | |
238 | if rfile: | |
239 | rmembers = readfile(rfile) | |
240 | if empty: | |
241 | mlist.reject_these_nonmembers = [] | |
242 | if dfile: | |
243 | dmembers = readfile(dfile) | |
244 | if empty: | |
245 | mlist.discard_these_nonmembers = [] | |
246 | ||
247 | if not amembers and not mmembers and not rmembers and not dmembers \ | |
248 | and not empty: | |
249 | usage(0, _('Nothing to do.')) | |
250 | ||
251 | s = StringIO() | |
252 | i18n.set_language(mlist.preferred_language) | |
253 | ||
254 | if afile: | |
255 | mlist.accept_these_nonmembers = addall(mlist, mlist.accept_these_nonmembers, 'accept_these_nonmembers', amembers, verbose, s) | |
256 | ||
257 | if mfile: | |
258 | mlist.hold_these_nonmembers = addall(mlist, mlist.hold_these_nonmembers, 'hold_these_nonmembers', mmembers, verbose, s) | |
259 | ||
260 | if rfile: | |
261 | mlist.reject_these_nonmembers = addall(mlist, mlist.reject_these_nonmembers, 'reject_these_nonmembers', rmembers, verbose, s) | |
262 | ||
263 | if dfile: | |
264 | mlist.discard_these_nonmembers = addall(mlist, mlist.discard_these_nonmembers, 'discard_these_nonmembers', dmembers, verbose, s) | |
265 | ||
266 | mlist.Save() | |
267 | finally: | |
268 | mlist.Unlock() | |
269 | i18n.set_translation(otrans) | |
270 | ||
271 | \f | |
272 | if __name__ == '__main__': | |
273 | main() |