diff options
| -rw-r--r-- | Mailman/Cgi/admin.py | 28 | ||||
| -rw-r--r-- | Mailman/Cgi/subscribe.py | 87 | ||||
| -rw-r--r-- | Mailman/Defaults.py.in | 24 | ||||
| -rw-r--r-- | Mailman/Errors.py | 3 | ||||
| -rw-r--r-- | Mailman/MailCommandHandler.py | 134 | ||||
| -rw-r--r-- | Mailman/MailList.py | 134 | ||||
| -rw-r--r-- | Mailman/Makefile.in | 2 | ||||
| -rw-r--r-- | Mailman/versions.py | 9 |
8 files changed, 236 insertions, 185 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py index 3a16d3760..95a671765 100644 --- a/Mailman/Cgi/admin.py +++ b/Mailman/Cgi/admin.py @@ -428,7 +428,18 @@ def GetItemCharacteristics(table_entry): def GetItemGuiValue(lst, kind, varname, params): """Return a representation of an item's settings.""" if kind == mm_cfg.Radio or kind == mm_cfg.Toggle: - return RadioButtonArray(varname, params, getattr(lst, varname)) + # + # if we are sending returning the option for subscribe + # policy and this site doesn't allow open subscribes, + # then we have to alter the value of lst.subscribe_policy + # as passed to RadioButtonArray in order to compensate + # for the fact that there is one fewer option. correspondingly, + # we alter the value back in the change options function -scott + # + if varname == "subscribe_policy" and not mm_cfg.ALLOW_OPEN_SUBSCRIBE: + return RadioButtonArray(varname, params, getattr(lst, varname) - 1) + else: + return RadioButtonArray(varname, params, getattr(lst, varname)) elif (kind == mm_cfg.String or kind == mm_cfg.Email or kind == mm_cfg.Host or kind == mm_cfg.Number): return TextBox(varname, getattr(lst, varname), params) @@ -669,6 +680,15 @@ def ChangeOptions(lst, category, cgi_info, document): # if category != 'members' and not cgi_info.has_key("request_login") and\ len(cgi_info.keys()) > 1: + if cgi_info.has_key("subscribe_policy"): + if not mm_cfg.ALLOW_OPEN_SUBSCRIBE: + # + # we have to add one to the value because the + # page didn't present an open list as an option + # + page_setting = string.atoi(cgi_info["subscribe_policy"].value) + cgi_info["subscribe_policy"].value = str(page_setting + 1) + opt_list = GetConfigOptions(lst, category) for item in opt_list: if len(item) < 5: @@ -699,10 +719,6 @@ def ChangeOptions(lst, category, cgi_info, document): names.remove('') subscribe_success = [] subscribe_errors = [] - if lst.send_welcome_msg: - noack = 0 - else: - noack = 1 for new_name in map(string.strip,names): digest = 0 if not lst.digestable: @@ -711,7 +727,7 @@ def ChangeOptions(lst, category, cgi_info, document): digest = 1 try: lst.ApprovedAddMember(new_name, (Utils.GetRandomSeed() + - Utils.GetRandomSeed()), digest, noack) + Utils.GetRandomSeed()), digest) subscribe_success.append(new_name) except Errors.MMAlreadyAMember: subscribe_errors.append((new_name, 'Already a member')) diff --git a/Mailman/Cgi/subscribe.py b/Mailman/Cgi/subscribe.py index 1366ab6ca..f6a5e68b2 100644 --- a/Mailman/Cgi/subscribe.py +++ b/Mailman/Cgi/subscribe.py @@ -34,7 +34,7 @@ def main(): if len(list_info) < 1: doc.AddItem(htmlformat.Header(2, "Error")) doc.AddItem(htmlformat.Bold("Invalid options to CGI script.")) - print doc.Format() + print doc.Format(bgcolor="#ffffff") sys.exit(0) try: @@ -42,14 +42,14 @@ def main(): except: doc.AddItem(htmlformat.Header(2, "Error")) doc.AddItem(htmlformat.Bold("%s: No such list." % list_name )) - print doc.Format() + print doc.Format(bgcolor="#ffffff") sys.exit(0) if not list._ready: doc.AddItem(htmlformat.Header(2, "Error")) doc.AddItem(htmlformat.Bold("%s: No such list." % list_name )) - print doc.Format() + print doc.Format(bgcolor="#ffffff") list.Unlock() sys.exit(0) @@ -80,7 +80,7 @@ def main(): doc.AddItem( htmlformat.Bold("You must supply your email address.")) doc.AddItem(list.GetMailmanFooter()) - print doc.Format() + print doc.Format(bgcolor="#ffffff") list.Unlock() sys.exit(0) addr = form['info'].value @@ -90,7 +90,7 @@ def main(): doc.AddItem(htmlformat.Bold("%s has no subscribed addr <i>%s</i>." % (list.real_name, addr))) doc.AddItem(list.GetMailmanFooter()) - print doc.Format() + print doc.Format(bgcolor="#ffffff") list.Unlock() sys.exit(0) list.Unlock() @@ -150,41 +150,11 @@ def main(): digesting = " digest" else: digesting = "" - cookie = Pending.gencookie() - Pending.add2pending(email, pw, digest, cookie) - frmremote = " from %s" % remote - text = Utils.maketext('verify.txt', - {"email" : email, - "listaddr" : list.GetListEmail(), - "listname" : list.real_name, - "cookie" : cookie, - "hostname" : frmremote, - "requestaddr": list.GetRequestEmail(), - "remote" : frmremote, - "listadmin" : list.GetAdminEmail(), - }) - list.SendTextToUser( - subject=("%s -- confirmation of subscription -- request %d" % - (list.real_name, cookie)), - recipient = email, - sender = list.GetRequestEmail(), - text = text, - add_headers = ["Reply-to: %s" % list.GetRequestEmail(), - "Errors-To: %s" % list.GetAdminEmail()]) - results = results + ("Confirmation from your email address is " - "required, to prevent anyone from covertly " - "subscribing you. Instructions are being " - "sent to you at %s." % email) - if remote: - by = " " + remote - else: - by = "" - list.LogMsg("subscribe", "%s: pending %s %s%s", - list._internal_name, - "web", - email, - by) - + list.AddMember(email, pw, digest, remote) + # + # check for all the errors that list.AddMember can throw + # options on the web page for this cgi + # except Errors.MMBadEmailError: results = results + ("Mailman won't accept the given email " "address as a valid address. (Does it " @@ -192,22 +162,35 @@ def main(): except Errors.MMListNotReady: results = results + ("The list is not fully functional, and " "can not accept subscription requests.<p>") - # - # deprecating this, it might be useful if we decide to - # allow approved based subscriptions without confirmation - # - ## except Errors.MMNeedApproval, x: - ## results = results + ("Subscription was <em>deferred</em> " - ## "because:<br> %s<p>Your request must " - ## "be approved by the list admin. " - ## "You will receive email informing you " - ## "of the moderator's descision when they " - ## "get to your request.<p>" % x) + except Errors.MMSubscribeNeedsConfirmation: + results = results + ("Confirmation from your email address is " + "required, to prevent anyone from covertly " + "subscribing you. Instructions are being " + "sent to you at %s." % email) + + except Errors.MMNeedApproval, x: + results = results + ("Subscription was <em>deferred</em> " + "because:<br> %s<p>Your request must " + "be approved by the list admin. " + "You will receive email informing you " + "of the moderator's descision when they " + "get to your request.<p>" % x) except Errors.MMHostileAddress: results = results + ("Your subscription is not allowed because " "the email address you gave is insecure.<p>") except Errors.MMAlreadyAMember: results = results + "You are already subscribed!<p>" + # + # these shouldn't happen, but if someone's futzing with the cgi + # they might -scott + # + except Errors.MMCantDigestError: + results = results + "No one can subscribe to the digest of this list!" + except Errors.MMMustDigestError: + results = results + "This list only supports digest subscriptions!" + else: + results = results + "You have been successfully subscribed to %s." % (list.real_name) + PrintResults(list, results, doc) @@ -221,7 +204,7 @@ def PrintResults(list, results, doc): output = list.ParseTags('subscribe.html', replacements) doc.AddItem(output) - print doc.Format() + print doc.Format(bgcolor="#ffffff") list.Unlock() sys.exit(0) diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index 780d06fc6..45a88301d 100644 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -51,6 +51,7 @@ PRIVATE_ARCHIVE_URL_EXT = '/' HOME_PAGE = 'index.html' MAILMAN_OWNER = 'mailman-owner@%s' % DEFAULT_HOST_NAME + # System ceiling on number of batches into which deliveries are divided: MAX_SPAWNS = 40 @@ -113,8 +114,23 @@ from: .*@uplinkpro.com """ # Replies to posts inherently directed to list or original sender? DEFAULT_REPLY_GOES_TO_LIST = 0 -# Admin approval unnecessary for subscribes? -DEFAULT_OPEN_SUBSCRIBE = 1 +# +# SUBSCRIBE POLICY +# 0 - open list (only when ALLOW_OPEN_SUBSCRIBE is set to 1) ** +# 1 - confirmations required for subscribes +# 2 - admin approval required for subscribes +# 3 - both confirmations and admin approval required +# +# ** please do not choose option 0 if you are not allowing open +# subscribes (next variable) +# +DEFAULT_SUBSCRIBE_POLICY = 1 +# +# does this site allow completely unchecked subscriptions? +# +ALLOW_OPEN_SUBSCRIBE = 0 + + # Private_roster == 0: anyone can see, 1: members only, 2: admin only. DEFAULT_PRIVATE_ROSTER = 0 # When exposing members, make them unrecognizable as email addrs. To @@ -122,8 +138,6 @@ DEFAULT_PRIVATE_ROSTER = 0 DEFAULT_OBSCURE_ADDRESSES = 1 # Make it 1 when it works. DEFAULT_MEMBER_POSTING_ONLY = 0 -# 1 for email subscription verification, 2 for admin confirmation: -DEFAULT_WEB_SUBSCRIBE_REQUIRES_CONFIRMATION = 1 # Digestification Defaults # @@ -229,4 +243,4 @@ PRIVATE_ARCHIVE_FILE_DIR = os.path.join(PREFIX, 'archives/private') VERSION = '@VERSION@' # Data file version number -DATA_FILE_VERSION = 3 +DATA_FILE_VERSION = 5 diff --git a/Mailman/Errors.py b/Mailman/Errors.py index 224d4c4bb..5cdfc1b88 100644 --- a/Mailman/Errors.py +++ b/Mailman/Errors.py @@ -32,13 +32,14 @@ MMListNotReady = "MMListNotReady" MMNoSuchUserError = "MMNoSuchUserError" MMBadPasswordError = "MMBadPasswordError" MMNeedApproval = "MMNeedApproval" +MMSubscribeNeedsConfirmation = "MMSubscribeNeedsConfirmation" +MMBadConfirmation = "MMBadConfirmation" MMHostileAddress = "MMHostileAddress" MMAlreadyAMember = "MMAlreadyAMember" MMPasswordsMustMatch = "MMPasswordsMustMatch" MMAlreadyDigested = "MMAlreadyDigested" MMAlreadyUndigested = "MMAlreadyUndigested" MMBadRequestId = "MMBadRequestId" -MMWebSubscribeRequiresConfirmation = "MMWebSubscribeRequiresConfirmation" MODERATED_LIST_MSG = "Moderated list" IMPLICIT_DEST_MSG = "Implicit destination" diff --git a/Mailman/MailCommandHandler.py b/Mailman/MailCommandHandler.py index 4459b36d4..9ef4a5c42 100644 --- a/Mailman/MailCommandHandler.py +++ b/Mailman/MailCommandHandler.py @@ -445,45 +445,46 @@ class MailCommandHandler: password = "%s%s" % (Utils.GetRandomSeed(), Utils.GetRandomSeed()) if not address: - pending_addr = mail.GetSender() + subscribe_address = string.lower(mail.GetSender()) else: - pending_addr = address + subscribe_address = address remote = mail.GetSender() - if pending_addr == self.GetListEmail(): - badremote = "\n\tfrom " - if remote: badremote = badremote + remote - else: badremote = badremote + "unidentified sender" - self.LogMsg("mischief", ("Attempt to self subscribe %s:%s" - % (pending_addr, badremote))) - self.AddApprovalMsg("Attempt to subscribe a list to itself!") - return - if self.FindUser(pending_addr): - self.AddError("%s is already a list member." % pending_addr) - return - cookie = Pending.gencookie() - Pending.add2pending(pending_addr, password, digest, cookie) - if remote == pending_addr: - remote = "" + try: + self.AddMember(subscribe_address, password, digest, remote) + except Errors.MMSubscribeNeedsConfirmation: + # + # the confirmation message that's been sent takes place + # of the results of the mail command message + # + self.__NoMailCmdResponse = 1 + except Errors.MMNeedApproval, admin_email: + self.AddToResponse("your subscription request has been forwarded the list " + "administrator\nat %s for review.\n" % admin_email) + except Errors.MMBadEmailError: + self.AddError("Mailman won't accept the given email " + "address as a valid address. \n(Does it " + "have an @ in it???)") + except Errors.MMListNotReady: + self.AddError("The list is not fully functional, and " + "can not accept subscription requests.") + except Errors.MMHostileAddress: + self.AddError("Your subscription is not allowed because\n" + "the email address you gave is insecure.") + except Errors.MMAlreadyAMember: + self.AddError("You are already subscribed!") + except Errors.MMCantDigestError: + self.AddError("No one can subscribe to the digest of this list!") + except Errors.MMMustDigestError: + self.AddError("This list only supports digest subscriptions!") else: - remote = " from " + remote - text = Utils.maketext( - 'verify.txt', - {'email' : pending_addr, - 'listaddr' : self.GetListEmail(), - 'listname' : self.real_name, - 'listadmin' : self.GetAdminEmail(), - 'cookie' : cookie, - 'remote' : remote, - 'requestaddr' : self.GetRequestEmail(), - }) - self.SendTextToUser( - subject = "%s -- confirmation of subscription -- request %d" % - (self.real_name, cookie), - recipient = pending_addr, - sender = self.GetRequestEmail(), - text = text) - self.__NoMailCmdResponse = 1 - return + # + # if the list sends a welcome message, we don't need a response + # from the mailcommand handler. + # + if self.send_welcome_msg: + self.__NoMailCmdResponse = 1 + else: + self.AddToResponse("Succeeded") @@ -497,56 +498,27 @@ class MailCommandHandler: except: self.AddError("Usage: confirm <confirmation number>\n") return - pending = Pending.get_pending() - if not pending.has_key(cookie): + try: + self.ProcessConfirmation(cookie) + except Errors.MMBadConfirmation: self.AddError("Invalid confirmation number!\n" "Please recheck the confirmation number and" " try again.") - return - (email_addr, password, digest, ts) = pending[cookie] - if self.open_subscribe: - self.FinishSubscribe(email_addr, password, digest, - approved=1) + except Errors.MMNeedApproval, admin_addr: + self.AddToResponse("your request has been forwarded to the list " + "administrator for approval") + else: - self.FinishSubscribe(email_addr, password, digest) - del pending[cookie] - Pending.set_pending(pending) - - def FinishSubscribe(self, addr, password, digest, approved=0): - try: - if approved: - self.ApprovedAddMember(addr, password, digest) + # + # if the list sends a welcome message, we don't need a response + # from the mailcommand handler. + # + if self.send_welcome_msg: + self.__NoMailCmdResponse = 1 else: - self.AddMember(addr, password, digest) - self.AddToResponse("Succeeded.") - except Errors.MMBadEmailError: - self.AddError("Email address '%s' not accepted by Mailman." % - addr) - except Errors.MMMustDigestError: - self.AddError("List only accepts digest members.") - except Errors.MMCantDigestError: - self.AddError("List doesn't accept digest members.") - except Errors.MMListNotReady: - self.AddError("List is not functional.") - except Errors.MMNeedApproval: - self.AddApprovalMsg("Subscription is pending list admin approval.") - except Errors.MMHostileAddress: - self.AddError("Email address '%s' not accepted by Mailman " - "(insecure address)" % addr) - except Errors.MMAlreadyAMember: - self.AddError("%s is already a list member." % addr) - except: - self.AddError("An unknown Mailman error occured.") - self.AddError("Please forward your request to %s" % - self.GetAdminEmail()) - self.AddError("%s" % sys.exc_type) - self.LogMsg("error", ("%s:\n\t%s.FinishSubscribe() encountered" - " unexpected exception:\n\t'%s', '%s'" - % (__name__, - self._internal_name, - str(sys.exc_info()[0]), - str(sys.exc_info()[1])))) - + self.AddToResponse("Succeeded") + + def AddApprovalMsg(self, cmd): text = Utils.maketext( 'approve.txt', diff --git a/Mailman/MailList.py b/Mailman/MailList.py index 5f05b9e82..6ef9e9c0c 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -172,12 +172,10 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, self.info = '' self.welcome_msg = '' self.goodbye_msg = '' - self.open_subscribe = mm_cfg.DEFAULT_OPEN_SUBSCRIBE + self.subscribe_policy = mm_cfg.DEFAULT_SUBSCRIBE_POLICY self.private_roster = mm_cfg.DEFAULT_PRIVATE_ROSTER self.obscure_addresses = mm_cfg.DEFAULT_OBSCURE_ADDRESSES self.member_posting_only = mm_cfg.DEFAULT_MEMBER_POSTING_ONLY - self.web_subscribe_requires_confirmation = \ - mm_cfg.DEFAULT_WEB_SUBSCRIBE_REQUIRES_CONFIRMATION self.host_name = mm_cfg.DEFAULT_HOST_NAME # Analogs to these are initted in Digester.InitVars @@ -353,6 +351,34 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, " list. It can be useful for selecting a particular URL" " of a host that has multiple addresses."), ] + if mm_cfg.ALLOW_OPEN_SUBSCRIBE: + sub_cfentry = ('subscribe_policy', mm_cfg.Radio, + ('none', 'confirm', 'require approval', 'confirm+approval'), 0, + "What steps are required for subscription?", + "None - no verification steps (<em>Not Recommended </em>)<br>" + "confirm (*) - email confirmation step required <br>" + "require approval - require list administrator approval for subscriptions <br>" + "confirm+approval - both confirm and approve" + + "<p> (*) when someone requests a subscription, mailman sends" + "them a notice with a unique subscription request number that " + "they must reply to in order to subscribe.<br> This prevents " + "list abusers from subscribing people to your list who don't want" + "to be subscribed." + ) + else: + sub_cfentry = ('subscribe_policy', mm_cfg.Radio, + ('confirm', 'require approval', 'confirm+approval'), 1, + "What steps are required for subscription?", + "confirm (*) - email confirmation required <br>" + "require approval - require list administrator approval for subscription" + "confirm+approval - both confirm and approve" + "<p> (*) when someone requests a subscription, mailman sends" + "them a notice with a unique subscription request number that " + "they must reply to in order to subscribe.<br> This prevents " + "list abusers from subscribing people to your list who don't want" + "to be subscribed." ) + config_info['privacy'] = [ "List access policies, including anti-spam measures," @@ -367,25 +393,8 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, 'Advertise this list when people ask what lists are on ' 'this machine?'), - ('open_subscribe', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Are subscribes done without admins approval (ie, is this' - ' an <em>open</em> list)?', - - "Disabling this option makes the list <em>closed</em>, where" - " members are admitted only at the discretion of the list" - " administrator."), - - ('web_subscribe_requires_confirmation', mm_cfg.Radio, - ('None', 'Requestor confirms via email', 'Admin approves'), 0, - 'What confirmation is required for on-the-web subscribes?', - - "This option determines whether web-initiated subscribes" - " require further confirmation, either from the subscribed" - " address or from the list administrator. Absence of" - " <em>any</em> confirmation makes web-based subscription a" - " tempting opportunity for mischievous subscriptions by third" - " parties."), - + sub_cfentry, + "Membership exposure", ('private_roster', mm_cfg.Radio, @@ -633,8 +642,8 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, file.close() self._ready = 1 if check_version: - self.CheckValues() - self.CheckVersion(dict) + self.CheckValues() + self.CheckVersion(dict) def LogMsg(self, kind, msg, *args): """Append a message to the log file for messages of specified kind.""" @@ -669,7 +678,7 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, if not self._ready: raise Errors.MMListNotReady - def AddMember(self, name, password, digest=0, web_subscribe=0): + def AddMember(self, name, password, digest=0, remote=None): self.IsListInitialized() # Remove spaces... it's a common thing for people to add... name = string.join(string.split(string.lower(name)), '') @@ -688,25 +697,56 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, elif not digest and not self.nondigestable: raise Errors.MMMustDigestError - if self.open_subscribe: - if (web_subscribe and self.web_subscribe_requires_confirmation): - if self.web_subscribe_requires_confirmation == 1: - # Requester confirmation required. - raise Errors.MMWebSubscribeRequiresConfirmation - else: - # Admin approval required. - self.AddRequest('add_member', digest, name, password) + if self.subscribe_policy == 0: # no confirmation or approval necessary + self.ApprovedAddMember(name, password, digest) + elif self.subscribe_policy == 1 or self.subscribe_policy == 3: # confirmation + import Pending + cookie = Pending.gencookie() + Pending.add2pending(name, password, digest, cookie) + if remote is not None: + by = " " + remote + remote = " from %s" % remote else: - # No approval required. - self.ApprovedAddMember(name, password, digest) - else: - # Blanket admin approval requred... + by = "" + remote = "" + text = Utils.maketext('verify.txt', + {"email" : name, + "listaddr" : self.GetListEmail(), + "listname" : self.real_name, + "cookie" : cookie, + "hostname" : remote, + "requestaddr": self.GetRequestEmail(), + "remote" : remote, + "listadmin" : self.GetAdminEmail(), + }) + self.SendTextToUser( + subject=("%s -- confirmation of subscription -- request %d" % + (self.real_name, cookie)), + recipient = name, + sender = self.GetRequestEmail(), + text = text, + add_headers = ["Reply-to: %s" % self.GetRequestEmail(), + "Errors-To: %s" % self.GetAdminEmail()]) + self.LogMsg("subscribe", "%s: pending %s %s", + self._internal_name, + name, + by) + raise Errors.MMSubscribeNeedsConfirmation + else: # approval needed self.AddRequest('add_member', digest, name, password) + raise Errors.MMNeedApproval, self.GetAdminEmail() + - def ApprovedAddMember(self, name, password, digest, noack=0): + + def ApprovedAddMember(self, name, password, digest, ack=None): # XXX klm: It *might* be nice to leave the case of the name alone, # but provide a common interface that always returns the # lower case version for computations. + if ack is None: + if self.send_welcome_msg: + ack = 1 + else: + ack = 0 name = string.lower(name) if self.IsMember(name): raise Errors.MMAlreadyAMember @@ -720,9 +760,25 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, self._internal_name, kind, name) self.passwords[name] = password self.Save() - if not noack: + if ack: self.SendSubscribeAck(name, password, digest) + + def ProcessConfirmation(self, cookie): + import Pending + pending = Pending.get_pending() + if not pending.has_key(cookie): + raise Errors.MMBadConfirmation + (email_addr, password, digest, ts) = pending[cookie] + del pending[cookie] + Pending.set_pending(pending) + if self.subscribe_policy == 3: # confirm + approve + self.AddRequest('add_member', digest, email_addr, password) + raise Errors.MMNeedApproval, self.GetAdminEmail() + self.ApprovedAddMember(email_addr, password, digest) + + + def DeleteMember(self, name, whence=None): self.IsListInitialized() # FindMatchingAddresses *should* never return more than 1 address. diff --git a/Mailman/Makefile.in b/Mailman/Makefile.in index 85075f7f3..5a1f63f29 100644 --- a/Mailman/Makefile.in +++ b/Mailman/Makefile.in @@ -83,7 +83,7 @@ clean: done distclean: - -rm Makefile Defaults.py + -rm Makefile Defaults.py mm_cfg.py for d in $(SUBDIRS); \ do \ (cd $$d; $(MAKE) distclean); \ diff --git a/Mailman/versions.py b/Mailman/versions.py index 94ece1ad6..d030f2e3d 100644 --- a/Mailman/versions.py +++ b/Mailman/versions.py @@ -61,6 +61,15 @@ def UpdateOldVars(l, stored_state): 'mimimum_post_count_before_bounce_action') PreferStored('bad_posters', 'forbidden_posters') PreferStored('automatically_remove', 'automatic_bounce_action') + if hasattr(l, "open_subscribe"): + if l.open_subscribe: + if mm_cfg.ALLOW_OPEN_SUBSCRIBE: + l.subscribe_policy = 0 + else: + l.subscribe_policy = 1 + else: + l.subscribe_policy = 2 # admin approval + delattr(l, "open_subscribe") # - dropped vars: # for a in ['archive_retain_text_copy', # 'archive_update_frequency']: |
