Add per list member roster visibility option
[mailman.git] / src / mailman / styles / base.py
blob5d8f20f32119c32b22fca842e588e9e71107947f
1 # Copyright (C) 2012-2019 by the Free Software Foundation, Inc.
3 # This file is part of GNU Mailman.
5 # GNU Mailman is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option)
8 # any later version.
10 # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 # more details.
15 # You should have received a copy of the GNU General Public License along with
16 # GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
18 """Building blocks for styles.
20 Use these to compose higher level styles. Their apply() methods deliberately
21 have no super() upcall. You need to explicitly call all base class apply()
22 methods in your compositional derived class.
23 """
26 from datetime import timedelta
27 from mailman.core.i18n import _
28 from mailman.interfaces.action import Action, FilterAction
29 from mailman.interfaces.archiver import ArchivePolicy
30 from mailman.interfaces.autorespond import ResponseAction
31 from mailman.interfaces.bounce import UnrecognizedBounceDisposition
32 from mailman.interfaces.digests import DigestFrequency
33 from mailman.interfaces.mailinglist import (
34 DMARCMitigateAction, Personalization, ReplyToMunging, SubscriptionPolicy)
35 from mailman.interfaces.nntp import NewsgroupModeration
36 from mailman.model.roster import RosterVisibility
37 from public import public
40 @public
41 class Identity:
42 """Set basic identify attributes."""
44 def apply(self, mailing_list):
45 # For cut-n-paste convenience.
46 mlist = mailing_list
47 mlist.display_name = mlist.list_name.capitalize()
48 mlist.include_rfc2369_headers = True
49 mlist.volume = 1
50 mlist.post_id = 1
51 mlist.description = ''
52 mlist.info = ''
53 mlist.preferred_language = 'en'
54 mlist.subject_prefix = _('[$mlist.display_name] ')
55 mlist.encode_ascii_prefixes = (
56 mlist.preferred_language.charset != 'us-ascii')
59 @public
60 class BasicOperation:
61 """Set basic operational attributes."""
63 def apply(self, mailing_list):
64 # For cut-n-paste convenience.
65 mlist = mailing_list
66 mlist.emergency = False
67 mlist.personalize = Personalization.none
68 mlist.default_member_action = Action.defer
69 mlist.default_nonmember_action = Action.hold
70 mlist.subscription_policy = SubscriptionPolicy.confirm
71 mlist.unsubscription_policy = SubscriptionPolicy.confirm
72 mlist.member_roster_visibility = RosterVisibility.moderators
73 # Notify the administrator of pending requests and membership changes.
74 mlist.admin_immed_notify = True
75 mlist.admin_notify_mchanges = False
76 mlist.respond_to_post_requests = True
77 mlist.obscure_addresses = True
78 mlist.collapse_alternatives = True
79 mlist.convert_html_to_plaintext = False
80 mlist.filter_action = FilterAction.discard
81 mlist.filter_content = False
82 # Digests.
83 mlist.digests_enabled = True
84 mlist.digest_is_default = False
85 mlist.digest_size_threshold = 30 # KB
86 mlist.digest_send_periodic = True
87 mlist.digest_volume_frequency = DigestFrequency.monthly
88 mlist.next_digest_number = 1
89 # DMARC
90 mlist.dmarc_mitigate_action = DMARCMitigateAction.no_mitigation
91 mlist.dmarc_mitigate_unconditionally = False
92 mlist.dmarc_moderation_notice = ''
93 mlist.dmarc_wrapped_message_text = ''
94 # NNTP gateway
95 mlist.nntp_host = ''
96 mlist.linked_newsgroup = ''
97 mlist.gateway_to_news = False
98 mlist.gateway_to_mail = False
99 mlist.nntp_prefix_subject_too = True
100 # In patch #401270, this was called newsgroup_is_moderated, but the
101 # semantics weren't quite the same.
102 mlist.newsgroup_moderation = NewsgroupModeration.none
103 # Topics
105 # `topics' is a list of 4-tuples of the following form:
107 # (name, pattern, description, emptyflag)
109 # name is a required arbitrary string displayed to the user when they
110 # get to select their topics of interest
112 # pattern is a required verbose regular expression pattern which is
113 # used as IGNORECASE.
115 # description is an optional description of what this topic is
116 # supposed to match
118 # emptyflag is a boolean used internally in the admin interface to
119 # signal whether a topic entry is new or not (new ones which do not
120 # have a name or pattern are not saved when the submit button is
121 # pressed).
122 mlist.topics = []
123 mlist.topics_enabled = False
124 mlist.topics_bodylines_limit = 5
125 # This is a mapping between user "names" (i.e. addresses) and
126 # information about which topics that user is interested in. The
127 # values are a list of topic names that the user is interested in,
128 # which should match the topic names in mlist.topics above.
130 # If the user has not selected any topics of interest, then the rule
131 # is that they will get all messages, and they will not have an entry
132 # in this dictionary.
133 mlist.topics_userinterest = {}
134 # scrub regular delivery
135 mlist.scrub_nondigest = False
138 @public
139 class Bounces:
140 """Basic bounce processing."""
142 def apply(self, mailing_list):
143 # For cut-n-paste convenience.
144 mlist = mailing_list
145 # Bounces
146 mlist.forward_unrecognized_bounces_to = (
147 UnrecognizedBounceDisposition.administrators)
148 mlist.process_bounces = True
149 mlist.bounce_score_threshold = 5.0
150 mlist.bounce_info_stale_after = timedelta(days=7)
151 mlist.bounce_you_are_disabled_warnings = 3
152 mlist.bounce_you_are_disabled_warnings_interval = timedelta(days=7)
153 mlist.bounce_notify_owner_on_disable = True
154 mlist.bounce_notify_owner_on_removal = True
155 # Autoresponder
156 mlist.autorespond_owner = ResponseAction.none
157 mlist.autoresponse_owner_text = ''
158 mlist.autorespond_postings = ResponseAction.none
159 mlist.autoresponse_postings_text = ''
160 mlist.autorespond_requests = ResponseAction.none
161 mlist.autoresponse_request_text = ''
162 mlist.autoresponse_grace_period = timedelta(days=90)
163 # This holds legacy member related information. It's keyed by the
164 # member address, and the value is an object containing the bounce
165 # score, the date of the last received bounce, and a count of the
166 # notifications left to send.
167 mlist.bounce_info = {}
168 # New style delivery status
169 mlist.delivery_status = {}
170 # The processing chain that messages posted to this mailing list get
171 # processed by.
172 mlist.posting_chain = 'default-posting-chain'
173 # The default pipeline to send accepted messages through to the
174 # mailing list's members.
175 mlist.posting_pipeline = 'default-posting-pipeline'
176 # The processing chain that messages posted to this mailing list's
177 # -owner address gets processed by.
178 mlist.owner_chain = 'default-owner-chain'
179 # The default pipeline to send -owner email through.
180 mlist.owner_pipeline = 'default-owner-pipeline'
183 @public
184 class Public:
185 """Settings for public mailing lists."""
187 def apply(self, mailing_list):
188 # For cut-n-paste convenience.
189 mlist = mailing_list
190 mlist.advertised = True
191 mlist.reply_goes_to_list = ReplyToMunging.no_munging
192 mlist.reply_to_address = ''
193 mlist.first_strip_reply_to = False
194 mlist.archive_policy = ArchivePolicy.public
197 @public
198 class Private:
199 """Settings for private mailing lists."""
201 def apply(self, mailing_list):
202 mlist = mailing_list
203 mlist.advertised = False
204 mlist.archive_policy = ArchivePolicy.private
207 @public
208 class Announcement:
209 """Settings for announce-only lists."""
211 def apply(self, mailing_list):
212 # For cut-n-paste convenience.
213 mlist = mailing_list
214 mlist.allow_list_posts = False
215 mlist.send_welcome_message = True
216 mlist.send_goodbye_message = True
217 mlist.anonymous_list = False
220 @public
221 class Discussion:
222 """Settings for standard discussion lists."""
224 def apply(self, mailing_list):
225 # For cut-n-paste convenience.
226 mlist = mailing_list
227 mlist.allow_list_posts = True
228 mlist.send_welcome_message = True
229 mlist.send_goodbye_message = True
230 mlist.anonymous_list = False
233 @public
234 class Moderation:
235 """Settings for basic moderation."""
237 def apply(self, mailing_list):
238 # For cut-n-paste convenience.
239 mlist = mailing_list
240 mlist.max_num_recipients = 10
241 mlist.max_message_size = 40 # KB
242 mlist.require_explicit_destination = True
243 mlist.bounce_matching_headers = """
244 # Lines that *start* with a '#' are comments.
245 to: friend@public.com
246 message-id: relay.comanche.denmark.eu
247 from: list@listme.com
248 from: .*@uplinkpro.com
250 mlist.header_matches = []
251 mlist.administrivia = True
252 # Member moderation.
253 mlist.member_moderation_notice = ''
254 mlist.accept_these_nonmembers = []
255 mlist.hold_these_nonmembers = []
256 mlist.reject_these_nonmembers = []
257 mlist.discard_these_nonmembers = []
258 mlist.forward_auto_discards = True
259 mlist.nonmember_rejection_notice = ''
260 # automatic discarding
261 mlist.max_days_to_hold = 0