Merge lp:~stylistica/systers/adminUI into lp:~systers-dev/systers/development

Proposed by Sneha Priscilla
Status: Merged
Merged at revision: 83
Proposed branch: lp:~stylistica/systers/adminUI
Merge into: lp:~systers-dev/systers/development
Diff against target: 506 lines (+501/-0)
1 file modified
Mailman/Gui/General.py (+501/-0)
To merge this branch: bzr merge lp:~stylistica/systers/adminUI
Reviewer Review Type Date Requested Status
Nicki Hutchens (community) Approve
Anna SdG Approve
Robin J Pending
Review via email: mp+114890@code.launchpad.net

This proposal supersedes a proposal from 2012-07-04.

Description of the change

Added admin UI for essays, essay questions and full name .

Made changes to one file from Mailman : ../Mailman/Gui/General.py and added it.
 Changed lines 383-401

To post a comment you must log in.
Revision history for this message
Robin J (robin-jeffries) wrote : Posted in a previous version of this proposal

Looks good

review: Approve
Revision history for this message
Anna SdG (anna-granudd) wrote : Posted in a previous version of this proposal

I agree with Robin but maybe you could add a "." at the end of each sentence of the description text (to match the other fields on the page)? Sorry for being picky... Thanks.

Revision history for this message
Sneha Priscilla (stylistica) wrote : Posted in a previous version of this proposal

That's alright :) I had totally missed that !

On Fri, Jul 6, 2012 at 12:40 AM, Anna SdG <email address hidden> wrote:
> I agree with Robin but maybe you could add a "." at the end of each sentence of the description text (to match the other fields on the page)? Sorry for being picky... Thanks.
> --
> https://code.launchpad.net/~stylistica/systers/adminUI/+merge/113416
> You are the owner of lp:~stylistica/systers/adminUI.

Revision history for this message
Anna SdG (anna-granudd) wrote :

Thanks for adding the dots. :)

review: Approve
Revision history for this message
Nicki Hutchens (nhutchen) wrote :

Thanks for explaining the changes. It looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'Mailman/Gui'
2=== added file 'Mailman/Gui/General.py'
3--- Mailman/Gui/General.py 1970-01-01 00:00:00 +0000
4+++ Mailman/Gui/General.py 2012-07-13 15:35:28 +0000
5@@ -0,0 +1,501 @@
6+# Copyright (C) 2001-2007 by the Free Software Foundation, Inc.
7+#
8+# This program is free software; you can redistribute it and/or
9+# modify it under the terms of the GNU General Public License
10+# as published by the Free Software Foundation; either version 2
11+# of the License, or (at your option) any later version.
12+#
13+# This program is distributed in the hope that it will be useful,
14+# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+# GNU General Public License for more details.
17+#
18+# You should have received a copy of the GNU General Public License
19+# along with this program; if not, write to the Free Software
20+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21+# USA.
22+
23+"""MailList mixin class managing the general options."""
24+
25+import re
26+
27+from types import IntType
28+
29+from Mailman import mm_cfg
30+from Mailman import Utils
31+from Mailman import Errors
32+#from Mailman import MailList #sneha
33+#from Mailman.DlistUserDesc import DlistUserDesc
34+from Mailman.i18n import _
35+from Mailman.Gui.GUIBase import GUIBase
36+
37+OPTIONS = ('hide', 'ack', 'notmetoo', 'nodupes')
38+
39+
40+
41
42+class General(GUIBase):
43+ def GetConfigCategory(self):
44+ return 'general', _('General Options')
45+
46+ def GetConfigInfo(self, mlist, category, subcat):
47+ if category <> 'general':
48+ return None
49+ WIDTH = mm_cfg.TEXTFIELDWIDTH
50+
51+ # These are for the default_options checkboxes below.
52+ bitfields = {'hide' : mm_cfg.ConcealSubscription,
53+ 'ack' : mm_cfg.AcknowledgePosts,
54+ 'notmetoo' : mm_cfg.DontReceiveOwnPosts,
55+ 'nodupes' : mm_cfg.DontReceiveDuplicates
56+ }
57+ bitdescrs = {
58+ 'hide' : _("Conceal the member's address"),
59+ 'ack' : _("Acknowledge the member's posting"),
60+ 'notmetoo' : _("Do not send a copy of a member's own post"),
61+ 'nodupes' :
62+ _('Filter out duplicate messages to list members (if possible)'),
63+ }
64+
65+ optvals = [mlist.new_member_options & bitfields[o] for o in OPTIONS]
66+ opttext = [bitdescrs[o] for o in OPTIONS]
67+
68+ rtn = [
69+ _('''Fundamental list characteristics, including descriptive
70+ info and basic behaviors.'''),
71+
72+ _('General list personality'),
73+
74+ ('real_name', mm_cfg.String, WIDTH, 0,
75+ _('The public name of this list (make case-changes only).'),
76+ _('''The capitalization of this name can be changed to make it
77+ presentable in polite company as a proper noun, or to make an
78+ acronym part all upper case, etc. However, the name will be
79+ advertised as the email address (e.g., in subscribe confirmation
80+ notices), so it should <em>not</em> be otherwise altered. (Email
81+ addresses are not case sensitive, but they are sensitive to
82+ almost everything else :-)''')),
83+
84+ ('owner', mm_cfg.EmailList, (3, WIDTH), 0,
85+ _("""The list administrator email addresses. Multiple
86+ administrator addresses, each on separate line is okay."""),
87+
88+ _('''There are two ownership roles associated with each mailing
89+ list. The <em>list administrators</em> are the people who have
90+ ultimate control over all parameters of this mailing list. They
91+ are able to change any list configuration variable available
92+ through these administration web pages.
93+
94+ <p>The <em>list moderators</em> have more limited permissions;
95+ they are not able to change any list configuration variable, but
96+ they are allowed to tend to pending administration requests,
97+ including approving or rejecting held subscription requests, and
98+ disposing of held postings. Of course, the <em>list
99+ administrators</em> can also tend to pending requests.
100+
101+ <p>In order to split the list ownership duties into
102+ administrators and moderators, you must
103+ <a href="passwords">set a separate moderator password</a>,
104+ and also provide the <a href="?VARHELP=general/moderator">email
105+ addresses of the list moderators</a>. Note that the field you
106+ are changing here specifies the list administrators.''')),
107+
108+ ('moderator', mm_cfg.EmailList, (3, WIDTH), 0,
109+ _("""The list moderator email addresses. Multiple
110+ moderator addresses, each on separate line is okay."""),
111+
112+ _('''There are two ownership roles associated with each mailing
113+ list. The <em>list administrators</em> are the people who have
114+ ultimate control over all parameters of this mailing list. They
115+ are able to change any list configuration variable available
116+ through these administration web pages.
117+
118+ <p>The <em>list moderators</em> have more limited permissions;
119+ they are not able to change any list configuration variable, but
120+ they are allowed to tend to pending administration requests,
121+ including approving or rejecting held subscription requests, and
122+ disposing of held postings. Of course, the <em>list
123+ administrators</em> can also tend to pending requests.
124+
125+ <p>In order to split the list ownership duties into
126+ administrators and moderators, you must
127+ <a href="passwords">set a separate moderator password</a>,
128+ and also provide the email addresses of the list moderators in
129+ this section. Note that the field you are changing here
130+ specifies the list moderators.''')),
131+
132+ ('description', mm_cfg.String, WIDTH, 0,
133+ _('A terse phrase identifying this list.'),
134+
135+ _('''This description is used when the mailing list is listed with
136+ other mailing lists, or in headers, and so forth. It should
137+ be as succinct as you can get it, while still identifying what
138+ the list is.''')),
139+
140+ ('info', mm_cfg.Text, (7, WIDTH), 0,
141+ _('''An introductory description - a few paragraphs - about the
142+ list. It will be included, as html, at the top of the listinfo
143+ page. Carriage returns will end a paragraph - see the details
144+ for more info.'''),
145+ _("""The text will be treated as html <em>except</em> that
146+ newlines will be translated to &lt;br&gt; - so you can use links,
147+ preformatted text, etc, but don't put in carriage returns except
148+ where you mean to separate paragraphs. And review your changes -
149+ bad html (like some unterminated HTML constructs) can prevent
150+ display of the entire listinfo page.""")),
151+
152+ ('subject_prefix', mm_cfg.String, WIDTH, 0,
153+ _('Prefix for subject line of list postings.'),
154+ _("""This text will be prepended to subject lines of messages
155+ posted to the list, to distinguish mailing list messages in
156+ mailbox summaries. Brevity is premium here, it's ok to shorten
157+ long mailing list names to something more concise, as long as it
158+ still identifies the mailing list.
159+ You can also add a sequential number by %%d substitution
160+ directive. eg.; [listname %%d] -> [listname 123]
161+ (listname %%05d) -> (listname 00123)
162+ """)),
163+
164+ ('anonymous_list', mm_cfg.Radio, (_('No'), _('Yes')), 0,
165+ _("""Hide the sender of a message, replacing it with the list
166+ address (Removes From, Sender and Reply-To fields)""")),
167+
168+ _('''<tt>Reply-To:</tt> header munging'''),
169+
170+ ('first_strip_reply_to', mm_cfg.Radio, (_('No'), _('Yes')), 0,
171+ _('''Should any existing <tt>Reply-To:</tt> header found in the
172+ original message be stripped? If so, this will be done
173+ regardless of whether an explict <tt>Reply-To:</tt> header is
174+ added by Mailman or not.''')),
175+
176+ ('reply_goes_to_list', mm_cfg.Radio,
177+ (_('Poster'), _('This list'), _('Explicit address')), 0,
178+ _('''Where are replies to list messages directed?
179+ <tt>Poster</tt> is <em>strongly</em> recommended for most mailing
180+ lists.'''),
181+
182+ # Details for reply_goes_to_list
183+ _("""This option controls what Mailman does to the
184+ <tt>Reply-To:</tt> header in messages flowing through this
185+ mailing list. When set to <em>Poster</em>, no <tt>Reply-To:</tt>
186+ header is added by Mailman, although if one is present in the
187+ original message, it is not stripped. Setting this value to
188+ either <em>This list</em> or <em>Explicit address</em> causes
189+ Mailman to insert a specific <tt>Reply-To:</tt> header in all
190+ messages, overriding the header in the original message if
191+ necessary (<em>Explicit address</em> inserts the value of <a
192+ href="?VARHELP=general/reply_to_address">reply_to_address</a>).
193+
194+ <p>There are many reasons not to introduce or override the
195+ <tt>Reply-To:</tt> header. One is that some posters depend on
196+ their own <tt>Reply-To:</tt> settings to convey their valid
197+ return address. Another is that modifying <tt>Reply-To:</tt>
198+ makes it much more difficult to send private replies. See <a
199+ href="http://www.unicom.com/pw/reply-to-harmful.html">`Reply-To'
200+ Munging Considered Harmful</a> for a general discussion of this
201+ issue. See <a
202+ href="http://www.metasystema.net/essays/reply-to.mhtml">Reply-To
203+ Munging Considered Useful</a> for a dissenting opinion.
204+
205+ <p>Some mailing lists have restricted posting privileges, with a
206+ parallel list devoted to discussions. Examples are `patches' or
207+ `checkin' lists, where software changes are posted by a revision
208+ control system, but discussion about the changes occurs on a
209+ developers mailing list. To support these types of mailing
210+ lists, select <tt>Explicit address</tt> and set the
211+ <tt>Reply-To:</tt> address below to point to the parallel
212+ list.""")),
213+
214+ ('reply_to_address', mm_cfg.Email, WIDTH, 0,
215+ _('Explicit <tt>Reply-To:</tt> header.'),
216+ # Details for reply_to_address
217+ _("""This is the address set in the <tt>Reply-To:</tt> header
218+ when the <a
219+ href="?VARHELP=general/reply_goes_to_list">reply_goes_to_list</a>
220+ option is set to <em>Explicit address</em>.
221+
222+ <p>There are many reasons not to introduce or override the
223+ <tt>Reply-To:</tt> header. One is that some posters depend on
224+ their own <tt>Reply-To:</tt> settings to convey their valid
225+ return address. Another is that modifying <tt>Reply-To:</tt>
226+ makes it much more difficult to send private replies. See <a
227+ href="http://www.unicom.com/pw/reply-to-harmful.html">`Reply-To'
228+ Munging Considered Harmful</a> for a general discussion of this
229+ issue. See <a
230+ href="http://www.metasystema.net/essays/reply-to.mhtml">Reply-To
231+ Munging Considered Useful</a> for a dissenting opinion.
232+
233+ <p>Some mailing lists have restricted posting privileges, with a
234+ parallel list devoted to discussions. Examples are `patches' or
235+ `checkin' lists, where software changes are posted by a revision
236+ control system, but discussion about the changes occurs on a
237+ developers mailing list. To support these types of mailing
238+ lists, specify the explicit <tt>Reply-To:</tt> address here. You
239+ must also specify <tt>Explicit address</tt> in the
240+ <tt>reply_goes_to_list</tt>
241+ variable.
242+
243+ <p>Note that if the original message contains a
244+ <tt>Reply-To:</tt> header, it will not be changed.""")),
245+
246+ _('Umbrella list settings'),
247+
248+ ('umbrella_list', mm_cfg.Radio, (_('No'), _('Yes')), 0,
249+ _('''Send password reminders to, eg, "-owner" address instead of
250+ directly to user.'''),
251+
252+ _("""Set this to yes when this list is intended to cascade only
253+ to other mailing lists. When set, meta notices like
254+ confirmations and password reminders will be directed to an
255+ address derived from the member\'s address - it will have the
256+ value of "umbrella_member_suffix" appended to the member's
257+ account name.""")),
258+
259+ ('umbrella_member_suffix', mm_cfg.String, WIDTH, 0,
260+ _('''Suffix for use when this list is an umbrella for other
261+ lists, according to setting of previous "umbrella_list"
262+ setting.'''),
263+
264+ _("""When "umbrella_list" is set to indicate that this list has
265+ other mailing lists as members, then administrative notices like
266+ confirmations and password reminders need to not be sent to the
267+ member list addresses, but rather to the owner of those member
268+ lists. In that case, the value of this setting is appended to
269+ the member's account name for such notices. `-owner' is the
270+ typical choice. This setting has no effect when "umbrella_list"
271+ is "No".""")),
272+
273+ _('Notifications'),
274+
275+ ('send_reminders', mm_cfg.Radio, (_('No'), _('Yes')), 0,
276+ _('''Send monthly password reminders?'''),
277+
278+ _('''Turn this on if you want password reminders to be sent once
279+ per month to your members. Note that members may disable their
280+ own individual password reminders.''')),
281+
282+ ('welcome_msg', mm_cfg.Text, (4, WIDTH), 1,
283+ _('''List-specific text prepended to new-subscriber welcome
284+ message'''),
285+
286+ _("""This value, if any, will be added to the front of the
287+ new-subscriber welcome message. The rest of the welcome message
288+ already describes the important addresses and URLs for the
289+ mailing list, so you don't need to include any of that kind of
290+ stuff here. This should just contain mission-specific kinds of
291+ things, like etiquette policies or team orientation, or that kind
292+ of thing.
293+
294+ <p>Note that this text will be wrapped, according to the
295+ following rules:
296+ <ul><li>Each paragraph is filled so that no line is longer than
297+ 70 characters.
298+ <li>Any line that begins with whitespace is not filled.
299+ <li>A blank line separates paragraphs.
300+ </ul>""")),
301+
302+ ('send_welcome_msg', mm_cfg.Radio, (_('No'), _('Yes')), 0,
303+ _('Send welcome message to newly subscribed members?'),
304+ _("""Turn this off only if you plan on subscribing people manually
305+ and don't want them to know that you did so. This option is most
306+ useful for transparently migrating lists from some other mailing
307+ list manager to Mailman.""")),
308+
309+ ('goodbye_msg', mm_cfg.Text, (4, WIDTH), 0,
310+ _('''Text sent to people leaving the list. If empty, no special
311+ text will be added to the unsubscribe message.''')),
312+
313+ ('send_goodbye_msg', mm_cfg.Radio, (_('No'), _('Yes')), 0,
314+ _('Send goodbye message to members when they are unsubscribed?')),
315+
316+ ('admin_immed_notify', mm_cfg.Radio, (_('No'), _('Yes')), 0,
317+ _('''Should the list moderators get immediate notice of new
318+ requests, as well as daily notices about collected ones?'''),
319+
320+ _('''List moderators (and list administrators) are sent daily
321+ reminders of requests pending approval, like subscriptions to a
322+ moderated list, or postings that are being held for one reason or
323+ another. Setting this option causes notices to be sent
324+ immediately on the arrival of new requests as well.''')),
325+
326+ ('admin_notify_mchanges', mm_cfg.Radio, (_('No'), _('Yes')), 0,
327+ _('''Should administrator get notices of subscribes and
328+ unsubscribes?''')),
329+
330+ ('respond_to_post_requests', mm_cfg.Radio,
331+ (_('No'), _('Yes')), 0,
332+ _('Send mail to poster when their posting is held for approval?')
333+ ),
334+
335+ _('Additional settings'),
336+
337+ ('emergency', mm_cfg.Toggle, (_('No'), _('Yes')), 1,
338+ _('Emergency moderation of all list traffic.'),
339+ _("""When this option is enabled, all list traffic is emergency
340+ moderated, i.e. held for moderation. Turn this option on when
341+ your list is experiencing a flamewar and you want a cooling off
342+ period.""")),
343+
344+ ('new_member_options', mm_cfg.Checkbox,
345+ (opttext, optvals, 0, OPTIONS),
346+ # The description for new_member_options includes a kludge where
347+ # we add a hidden field so that even when all the checkboxes are
348+ # deselected, the form data will still have a new_member_options
349+ # key (it will always be a list). Otherwise, we'd never be able
350+ # to tell if all were deselected!
351+ 0, _('''Default options for new members joining this list.<input
352+ type="hidden" name="new_member_options" value="ignore">'''),
353+
354+ _("""When a new member is subscribed to this list, their initial
355+ set of options is taken from the this variable's setting.""")),
356+
357+ ('administrivia', mm_cfg.Radio, (_('No'), _('Yes')), 1,
358+ _('''(Administrivia filter) Check postings and intercept ones
359+ that seem to be administrative requests?'''),
360+
361+ _("""Administrivia tests will check postings to see whether it's
362+ really meant as an administrative request (like subscribe,
363+ unsubscribe, etc), and will add it to the the administrative
364+ requests queue, notifying the administrator of the new request,
365+ in the process.""")),
366+
367+ ('max_message_size', mm_cfg.Number, 7, 0,
368+ _('''Maximum length in kilobytes (KB) of a message body. Use 0
369+ for no limit.''')),
370+
371+ ('admin_member_chunksize', mm_cfg.Number, 7, 0,
372+ _('''Maximum number of members to show on one page of the
373+ Membership List.''')),
374+
375+ ('host_name', mm_cfg.Host, WIDTH, 0,
376+ _('Host name this list prefers for email.'),
377+
378+ _("""The "host_name" is the preferred name for email to
379+ mailman-related addresses on this host, and generally should be
380+ the mail host's exchanger address, if any. This setting can be
381+ useful for selecting among alternative names of a host that has
382+ multiple addresses.""")),
383+
384+ ('essay_enabled', mm_cfg.Radio, (_('No'), _('Yes')), 0,
385+ _('Should an essay be provided during subscription?'),
386+ _("""Turn this on if you want to require subscribers to answer
387+ some questions about their eligibility for the list when they
388+ request membership. """)),
389+
390+ ('questions', mm_cfg.Text, (4, WIDTH), 0,
391+ _('''Text for subscription essay.'''),
392+ _("""The essay instructions may include the lightweight markup
393+ language <a href="http://en.wikipedia.org/wiki/Markdown" Title=
394+ "Link to examples of markdown syntax">Markdown</a>.Changing this
395+ section will have no effect until you have set the value of
396+ essay_enabled to True in the previous section. """)),
397+
398+
399+ ('fullname_required', mm_cfg.Radio, (_('No'), _('Yes')), 0,
400+ _('''Should a name be provided during subscription?'''),
401+ _("""Turn this on if you want to require subscribers to include
402+ their name as well as email when they request membership.""")),
403+
404+
405+ ]
406+
407+ if mm_cfg.ALLOW_RFC2369_OVERRIDES:
408+ rtn.append(
409+ ('include_rfc2369_headers', mm_cfg.Radio,
410+ (_('No'), _('Yes')), 0,
411+ _("""Should messages from this mailing list include the
412+ <a href="http://www.faqs.org/rfcs/rfc2369.html">RFC 2369</a>
413+ (i.e. <tt>List-*</tt>) headers? <em>Yes</em> is highly
414+ recommended."""),
415+
416+ _("""RFC 2369 defines a set of List-* headers that are
417+ normally added to every message sent to the list membership.
418+ These greatly aid end-users who are using standards compliant
419+ mail readers. They should normally always be enabled.
420+
421+ <p>However, not all mail readers are standards compliant yet,
422+ and if you have a large number of members who are using
423+ non-compliant mail readers, they may be annoyed at these
424+ headers. You should first try to educate your members as to
425+ why these headers exist, and how to hide them in their mail
426+ clients. As a last resort you can disable these headers, but
427+ this is not recommended (and in fact, your ability to disable
428+ these headers may eventually go away)."""))
429+ )
430+ # Suppression of List-Post: headers
431+ rtn.append(
432+ ('include_list_post_header', mm_cfg.Radio,
433+ (_('No'), _('Yes')), 0,
434+ _('Should postings include the <tt>List-Post:</tt> header?'),
435+ _("""The <tt>List-Post:</tt> header is one of the headers
436+ recommended by
437+ <a href="http://www.faqs.org/rfcs/rfc2369.html">RFC 2369</a>.
438+ However for some <em>announce-only</em> mailing lists, only a
439+ very select group of people are allowed to post to the list; the
440+ general membership is usually not allowed to post. For lists of
441+ this nature, the <tt>List-Post:</tt> header is misleading.
442+ Select <em>No</em> to disable the inclusion of this header. (This
443+ does not affect the inclusion of the other <tt>List-*:</tt>
444+ headers.)"""))
445+ )
446+
447+ # Discard held messages after this number of days
448+ rtn.append(
449+ ('max_days_to_hold', mm_cfg.Number, 7, 0,
450+ _("""Discard held messages older than this number of days.
451+ Use 0 for no automatic discarding."""))
452+ )
453+
454+ return rtn
455+
456+ def _setValue(self, mlist, property, val, doc):
457+ if property == 'real_name' and \
458+ val.lower() <> mlist.internal_name().lower():
459+ # These values can't differ by other than case
460+ doc.addError(_("""<b>real_name</b> attribute not
461+ changed! It must differ from the list's name by case
462+ only."""))
463+ elif property == 'new_member_options':
464+ newopts = 0
465+ for opt in OPTIONS:
466+ bitfield = mm_cfg.OPTINFO[opt]
467+ if opt in val:
468+ newopts |= bitfield
469+ mlist.new_member_options = newopts
470+ elif property == 'subject_prefix':
471+ # Convert any html entities to Unicode
472+ mlist.subject_prefix = Utils.canonstr(
473+ val, mlist.preferred_language)
474+ elif property == 'info':
475+ if val <> mlist.info:
476+ if Utils.suspiciousHTML(val):
477+ doc.addError(_("""The <b>info</b> attribute you saved
478+contains suspicious HTML that could potentially expose your users to cross-site
479+scripting attacks. This change has therefore been rejected. If you still want
480+to make these changes, you must have shell access to your Mailman server.
481+This change can be made with bin/withlist or with bin/config_list by setting
482+mlist.info.
483+ """))
484+ else:
485+ mlist.info = val
486+ elif property == 'admin_member_chunksize' and (val < 1
487+ or not isinstance(val, IntType)):
488+ doc.addError(_("""<b>admin_member_chunksize</b> attribute not
489+ changed! It must be an integer > 0."""))
490+ else:
491+ GUIBase._setValue(self, mlist, property, val, doc)
492+
493+
494+ def _postValidate(self, mlist, doc):
495+ if not mlist.reply_to_address.strip() and \
496+ mlist.reply_goes_to_list == 2:
497+ # You can't go to an explicit address that is blank
498+ doc.addError(_("""You cannot add a Reply-To: to an explicit
499+ address if that address is blank. Resetting these values."""))
500+ mlist.reply_to_address = ''
501+ mlist.reply_goes_to_list = 0
502+
503+ def getValue(self, mlist, kind, varname, params):
504+ if varname <> 'subject_prefix':
505+ return None
506+ # The subject_prefix may be Unicode
507+ return Utils.uncanonstr(mlist.subject_prefix, mlist.preferred_language)

Subscribers

People subscribed via source and target branches