1 # Copyright (C) 2006-2007 by the Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 from zope
.interface
import implements
24 from Mailman
.Utils
import fqdn_listname
, makedirs
, split_listname
25 from Mailman
.configuration
import config
26 from Mailman
.interfaces
import *
27 from Mailman
.database
.types
import EnumType
, TimeDeltaType
34 class MailingList(Entity
):
37 IMailingListAddresses
,
44 has_field('list_name', Unicode
),
45 has_field('host_name', Unicode
),
46 # Attributes not directly modifiable via the web u/i
47 has_field('created_at', DateTime
),
48 has_field('web_page_url', Unicode
),
49 has_field('admin_member_chunksize', Integer
),
50 has_field('hold_and_cmd_autoresponses', PickleType
),
51 # Attributes which are directly modifiable via the web u/i. The more
52 # complicated attributes are currently stored as pickles, though that
53 # will change as the schema and implementation is developed.
54 has_field('next_request_id', Integer
),
55 has_field('next_digest_number', Integer
),
56 has_field('admin_responses', PickleType
),
57 has_field('postings_responses', PickleType
),
58 has_field('request_responses', PickleType
),
59 has_field('digest_last_sent_at', Float
),
60 has_field('one_last_digest', PickleType
),
61 has_field('volume', Integer
),
62 has_field('last_post_time', DateTime
),
63 # Attributes which are directly modifiable via the web u/i. The more
64 # complicated attributes are currently stored as pickles, though that
65 # will change as the schema and implementation is developed.
66 has_field('accept_these_nonmembers', PickleType
),
67 has_field('acceptable_aliases', PickleType
),
68 has_field('admin_immed_notify', Boolean
),
69 has_field('admin_notify_mchanges', Boolean
),
70 has_field('administrivia', Boolean
),
71 has_field('advertised', Boolean
),
72 has_field('anonymous_list', Boolean
),
73 has_field('archive', Boolean
),
74 has_field('archive_private', Boolean
),
75 has_field('archive_volume_frequency', Integer
),
76 has_field('autorespond_admin', Boolean
),
77 has_field('autorespond_postings', Boolean
),
78 has_field('autorespond_requests', Integer
),
79 has_field('autoresponse_admin_text', Unicode
),
80 has_field('autoresponse_graceperiod', TimeDeltaType
),
81 has_field('autoresponse_postings_text', Unicode
),
82 has_field('autoresponse_request_text', Unicode
),
83 has_field('ban_list', PickleType
),
84 has_field('bounce_info_stale_after', TimeDeltaType
),
85 has_field('bounce_matching_headers', Unicode
),
86 has_field('bounce_notify_owner_on_disable', Boolean
),
87 has_field('bounce_notify_owner_on_removal', Boolean
),
88 has_field('bounce_processing', Boolean
),
89 has_field('bounce_score_threshold', Integer
),
90 has_field('bounce_unrecognized_goes_to_list_owner', Boolean
),
91 has_field('bounce_you_are_disabled_warnings', Integer
),
92 has_field('bounce_you_are_disabled_warnings_interval', TimeDeltaType
),
93 has_field('collapse_alternatives', Boolean
),
94 has_field('convert_html_to_plaintext', Boolean
),
95 has_field('default_member_moderation', Boolean
),
96 has_field('description', Unicode
),
97 has_field('digest_footer', Unicode
),
98 has_field('digest_header', Unicode
),
99 has_field('digest_is_default', Boolean
),
100 has_field('digest_send_periodic', Boolean
),
101 has_field('digest_size_threshold', Integer
),
102 has_field('digest_volume_frequency', Integer
),
103 has_field('digestable', Boolean
),
104 has_field('discard_these_nonmembers', PickleType
),
105 has_field('emergency', Boolean
),
106 has_field('encode_ascii_prefixes', Boolean
),
107 has_field('filter_action', Integer
),
108 has_field('filter_content', Boolean
),
109 has_field('filter_filename_extensions', PickleType
),
110 has_field('filter_mime_types', PickleType
),
111 has_field('first_strip_reply_to', Boolean
),
112 has_field('forward_auto_discards', Boolean
),
113 has_field('gateway_to_mail', Boolean
),
114 has_field('gateway_to_news', Boolean
),
115 has_field('generic_nonmember_action', Integer
),
116 has_field('goodbye_msg', Unicode
),
117 has_field('header_filter_rules', PickleType
),
118 has_field('hold_these_nonmembers', PickleType
),
119 has_field('include_list_post_header', Boolean
),
120 has_field('include_rfc2369_headers', Boolean
),
121 has_field('info', Unicode
),
122 has_field('linked_newsgroup', Unicode
),
123 has_field('max_days_to_hold', Integer
),
124 has_field('max_message_size', Integer
),
125 has_field('max_num_recipients', Integer
),
126 has_field('member_moderation_action', Boolean
),
127 has_field('member_moderation_notice', Unicode
),
128 has_field('mime_is_default_digest', Boolean
),
129 has_field('mod_password', Unicode
),
130 has_field('msg_footer', Unicode
),
131 has_field('msg_header', Unicode
),
132 has_field('new_member_options', Integer
),
133 has_field('news_moderation', Boolean
),
134 has_field('news_prefix_subject_too', Boolean
),
135 has_field('nntp_host', Unicode
),
136 has_field('nondigestable', Boolean
),
137 has_field('nonmember_rejection_notice', Unicode
),
138 has_field('obscure_addresses', Boolean
),
139 has_field('pass_filename_extensions', PickleType
),
140 has_field('pass_mime_types', PickleType
),
141 has_field('password', Unicode
),
142 has_field('personalize', Integer
),
143 has_field('post_id', Integer
),
144 has_field('preferred_language', Unicode
),
145 has_field('private_roster', Boolean
),
146 has_field('real_name', Unicode
),
147 has_field('reject_these_nonmembers', PickleType
),
148 has_field('reply_goes_to_list', EnumType
),
149 has_field('reply_to_address', Unicode
),
150 has_field('require_explicit_destination', Boolean
),
151 has_field('respond_to_post_requests', Boolean
),
152 has_field('scrub_nondigest', Boolean
),
153 has_field('send_goodbye_msg', Boolean
),
154 has_field('send_reminders', Boolean
),
155 has_field('send_welcome_msg', Boolean
),
156 has_field('subject_prefix', Unicode
),
157 has_field('subscribe_auto_approval', PickleType
),
158 has_field('subscribe_policy', Integer
),
159 has_field('topics', PickleType
),
160 has_field('topics_bodylines_limit', Integer
),
161 has_field('topics_enabled', Boolean
),
162 has_field('unsubscribe_policy', Integer
),
163 has_field('welcome_msg', Unicode
),
165 ## has_and_belongs_to_many(
166 ## 'available_languages',
167 ## of_kind='Mailman.database.model.languages.Language')
169 using_options(shortnames
=True)
171 def __init__(self
, fqdn_listname
):
172 super(MailingList
, self
).__init
__()
173 listname
, hostname
= split_listname(fqdn_listname
)
174 self
.list_name
= listname
175 self
.host_name
= hostname
176 # For the pending database
177 self
.next_request_id
= 1
179 # Max autoresponses per day. A mapping between addresses and a
180 # 2-tuple of the date of the last autoresponse and the number of
181 # autoresponses sent on that date.
182 self
.hold_and_cmd_autoresponses
= {}
183 self
.full_path
= os
.path
.join(config
.LIST_DATA_DIR
, fqdn_listname
)
184 self
.real_name
= string
.capwords(SPACE
.join(listname
.split(UNDERSCORE
)))
185 makedirs(self
.full_path
)
189 # Avoid circular imports.
190 from Mailman
.database
.model
import roster
191 self
.owners
= roster
.OwnerRoster(self
)
192 self
.moderators
= roster
.ModeratorRoster(self
)
193 self
.administrators
= roster
.AdministratorRoster(self
)
194 self
.members
= roster
.MemberRoster(self
)
195 self
.regular_members
= roster
.RegularMemberRoster(self
)
196 self
.digest_members
= roster
.DigestMemberRoster(self
)
197 self
.subscribers
= roster
.Subscribers(self
)
200 def fqdn_listname(self
):
201 """See IMailingListIdentity."""
202 return fqdn_listname(self
.list_name
, self
.host_name
)
206 """See IMailingListWeb."""
207 return config
.domains
[self
.host_name
]
209 def script_url(self
, target
, context
=None):
210 """See IMailingListWeb."""
211 # XXX Handle the case for when context is not None; those would be
213 return self
.web_page_url
+ target
+ '/' + self
.fqdn_listname
215 # IMailingListAddresses
218 def posting_address(self
):
219 return self
.fqdn_listname
222 def noreply_address(self
):
223 return '%s@%s' % (config
.NO_REPLY_ADDRESS
, self
.host_name
)
226 def owner_address(self
):
227 return '%s-owner@%s' % (self
.list_name
, self
.host_name
)
230 def request_address(self
):
231 return '%s-request@%s' % (self
.list_name
, self
.host_name
)
234 def bounces_address(self
):
235 return '%s-bounces@%s' % (self
.list_name
, self
.host_name
)
238 def join_address(self
):
239 return '%s-join@%s' % (self
.list_name
, self
.host_name
)
242 def leave_address(self
):
243 return '%s-leave@%s' % (self
.list_name
, self
.host_name
)
246 def subscribe_address(self
):
247 return '%s-subscribe@%s' % (self
.list_name
, self
.host_name
)
250 def unsubscribe_address(self
):
251 return '%s-unsubscribe@%s' % (self
.list_name
, self
.host_name
)
253 def confirm_address(self
, cookie
):
254 template
= string
.Template(config
.VERP_CONFIRM_FORMAT
)
255 local_part
= template
.safe_substitute(
256 address
= '%s-confirm' % self
.list_name
,
258 return '%s@%s' % (local_part
, self
.host_name
)
261 return '<mailing list "%s" at %#x>' % (self
.fqdn_listname
, id(self
))