Yasuhito FUTATSUKI at POEM has proposed merging 
lp:~futatuki/mailman/2.1-forbid-subscription into lp:mailman/2.1.

Commit message:
Add new value for MailList.subscribe_policy 4 as forbid

Requested reviews:
  Mailman Coders (mailman-coders)

For more details, see:
https://code.launchpad.net/~futatuki/mailman/2.1-forbid-subscription/+merge/347305

This extends MailList.subscribe_policy with new value '4', forbid subscribe 
request via E-mail and via Web UI (except list owners operation).

With MailList.subscribe_policy == 4,
* For Web UI
  - reject all subscribe request (Mailman/Cgi/subscribe.py, 
Mailman/HTMLFormatter.py)
  - hide subscription form from listinfo page
    (Mailman/Cgi/listinfo.py, new template 
templates/en/listinfo_nosubscribe.html)
* For request via E-mail, reject all subscribe command 
(Mailman/Command/cmd_subscribe.py)
* foolproof: MailList.AddMember() raise new exception 
Errors.MembershipIsRejectedByPolicy()
    (Mailman/Errors.py, Mailman/MailList.py)

To set new value to MailList.subscribe_policy,
* For Web UI, add new radio button and description (Mailman/Gui/Privacy.py)

For new template
* Add menu new item for new template file (Mailman/Cgi/edithtml.py)

For description
* Add description for new value (Mailman/Defauilts.py.in, misc/sitelist.cfg)

Please revise not only code logic but also identifiers, words, messages to be 
suitable.

-- 
Your team Mailman Coders is requested to review the proposed merge of 
lp:~futatuki/mailman/2.1-forbid-subscription into lp:mailman/2.1.
=== modified file 'Mailman/Cgi/edithtml.py'
--- Mailman/Cgi/edithtml.py	2017-06-06 05:47:05 +0000
+++ Mailman/Cgi/edithtml.py	2018-06-01 16:42:47 +0000
@@ -46,6 +46,8 @@
 
     template_data = (
         ('listinfo.html',    _('General list information page')),
+        ('listinfo_nosubscribe.html',
+                _('General list information page(no subscription form)')),
         ('subscribe.html',   _('Subscribe results page')),
         ('options.html',     _('User specific options page')),
         ('subscribeack.txt', _('Welcome email text file')),

=== modified file 'Mailman/Cgi/listinfo.py'
--- Mailman/Cgi/listinfo.py	2018-05-26 16:22:35 +0000
+++ Mailman/Cgi/listinfo.py	2018-06-01 16:42:47 +0000
@@ -180,51 +180,59 @@
 
     replacements = mlist.GetStandardReplacements(lang)
 
-    if not mlist.digestable or not mlist.nondigestable:
-        replacements['<mm-digest-radio-button>'] = ""
-        replacements['<mm-undigest-radio-button>'] = ""
-        replacements['<mm-digest-question-start>'] = '<!-- '
-        replacements['<mm-digest-question-end>'] = ' -->'
-    else:
-        replacements['<mm-digest-radio-button>'] = mlist.FormatDigestButton()
-        replacements['<mm-undigest-radio-button>'] = \
-                                                   mlist.FormatUndigestButton()
-        replacements['<mm-digest-question-start>'] = ''
-        replacements['<mm-digest-question-end>'] = ''
-    replacements['<mm-plain-digests-button>'] = \
-                                              mlist.FormatPlainDigestsButton()
-    replacements['<mm-mime-digests-button>'] = mlist.FormatMimeDigestsButton()
-    replacements['<mm-subscribe-box>'] = mlist.FormatBox('email', size=30)
-    replacements['<mm-subscribe-button>'] = mlist.FormatButton(
-        'email-button', text=_('Subscribe'))
-    replacements['<mm-new-password-box>'] = mlist.FormatSecureBox('pw')
-    replacements['<mm-confirm-password>'] = mlist.FormatSecureBox('pw-conf')
-    replacements['<mm-subscribe-form-start>'] = mlist.FormatFormStart(
-        'subscribe')
-    if mm_cfg.SUBSCRIBE_FORM_SECRET:
-        now = str(int(time.time()))
-        remote = os.environ.get('HTTP_FORWARDED_FOR',
-                 os.environ.get('HTTP_X_FORWARDED_FOR',
-                 os.environ.get('REMOTE_ADDR',
-                                'w.x.y.z')))
-        # Try to accept a range in case of load balancers, etc.  (LP: #1447445)
-        if remote.find('.') >= 0:
-            # ipv4 - drop last octet
-            remote = remote.rsplit('.', 1)[0]
+    if mlist.subscribe_policy != 4:
+        htmlbase = 'listinfo.html'
+        if not mlist.digestable or not mlist.nondigestable:
+            replacements['<mm-digest-radio-button>'] = ""
+            replacements['<mm-undigest-radio-button>'] = ""
+            replacements['<mm-digest-question-start>'] = '<!-- '
+            replacements['<mm-digest-question-end>'] = ' -->'
         else:
-            # ipv6 - drop last 16 (could end with :: in which case we just
-            #        drop one : resulting in an invalid format, but it's only
-            #        for our hash so it doesn't matter.
-            remote = remote.rsplit(':', 1)[0]
-        replacements['<mm-subscribe-form-start>'] += (
+            replacements['<mm-digest-radio-button>'] = \
+                                            mlist.FormatDigestButton()
+            replacements['<mm-undigest-radio-button>'] = \
+                                            mlist.FormatUndigestButton()
+            replacements['<mm-digest-question-start>'] = ''
+            replacements['<mm-digest-question-end>'] = ''
+        replacements['<mm-plain-digests-button>'] = \
+                                            mlist.FormatPlainDigestsButton()
+        replacements['<mm-mime-digests-button>'] = \
+                                            mlist.FormatMimeDigestsButton()
+        replacements['<mm-subscribe-box>'] = mlist.FormatBox('email', size=30)
+        replacements['<mm-subscribe-button>'] = mlist.FormatButton(
+            'email-button', text=_('Subscribe'))
+        replacements['<mm-new-password-box>'] = mlist.FormatSecureBox('pw')
+        replacements['<mm-confirm-password>'] = \
+                                            mlist.FormatSecureBox('pw-conf')
+        replacements['<mm-subscribe-form-start>'] = mlist.FormatFormStart(
+            'subscribe')
+        if mm_cfg.SUBSCRIBE_FORM_SECRET:
+            now = str(int(time.time()))
+            remote = os.environ.get('HTTP_FORWARDED_FOR',
+                     os.environ.get('HTTP_X_FORWARDED_FOR',
+                     os.environ.get('REMOTE_ADDR',
+                                    'w.x.y.z')))
+            # Try to accept a range in case of load balancers, etc.
+            # (LP: #1447445)
+            if remote.find('.') >= 0:
+                # ipv4 - drop last octet
+                remote = remote.rsplit('.', 1)[0]
+            else:
+                # ipv6 - drop last 16 (could end with :: in which case we just
+                #        drop one : resulting in an invalid format, but it's
+                #        only for our hash so it doesn't matter.
+                remote = remote.rsplit(':', 1)[0]
+            replacements['<mm-subscribe-form-start>'] += (
                 '<input type="hidden" name="sub_form_token" value="%s:%s">\n'
                 % (now, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET +
-                          now +
-                          mlist.internal_name() +
-                          remote
-                          ).hexdigest()
+                              now +
+                              mlist.internal_name() +
+                              remote
+                              ).hexdigest()
                     )
                 )
+    else:
+        htmlbase = 'listinfo_nosubscribe.html'
     # Roster form substitutions
     replacements['<mm-roster-form-start>'] = mlist.FormatFormStart('roster')
     replacements['<mm-roster-option>'] = mlist.FormatRosterOptionForUser(lang)
@@ -258,7 +266,7 @@
         replacements['<mm-recaptcha-ui>'] = ''
 
     # Do the expansion.
-    doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang))
+    doc.AddItem(mlist.ParseTags(htmlbase, replacements, lang))
     print doc.Format()
 
 

=== modified file 'Mailman/Cgi/subscribe.py'
--- Mailman/Cgi/subscribe.py	2018-04-11 09:36:40 +0000
+++ Mailman/Cgi/subscribe.py	2018-06-01 16:42:47 +0000
@@ -118,6 +118,12 @@
 
 
 def process_form(mlist, doc, cgidata, lang):
+    # short cut
+    if mlist.subscribe_policy == 4:
+        results = _(""" Your subscription is not allowed because the list
+        don't accept any new subscriptions by policy.""")
+        print_results(mlist, results, doc, lang)
+        return
     listowner = mlist.GetOwnerEmail()
     realname = mlist.real_name
     results = []
@@ -253,6 +259,10 @@
         results = _("""The email address you supplied is banned from this
         mailing list.  If you think this restriction is erroneous, please
         contact the list owners at %(listowner)s.""")
+    # foolproof
+    except Errors.MembershipIsRejectedByPolicy:
+        results = _(""" Your subscription is not allowed because the list
+        don't accept any new subscriptions by policy.""")
     except Errors.MMBadEmailError:
         results = _("""\
 The email address you supplied is not valid.  (E.g. it must contain an

=== modified file 'Mailman/Commands/cmd_subscribe.py'
--- Mailman/Commands/cmd_subscribe.py	2008-04-27 00:59:18 +0000
+++ Mailman/Commands/cmd_subscribe.py	2018-06-01 16:42:47 +0000
@@ -46,6 +46,10 @@
 
 def process(res, args):
     mlist = res.mlist
+    # short cut
+    if mlist.subscribe_policy == 4:
+        res.results.append(_('New subscription is forbided by policy'))
+        return STOP
     digest = None
     password = None
     address = None
@@ -115,6 +119,11 @@
 If you think this restriction is erroneous, please contact the list
 owners at %(listowner)s."""))
         return STOP
+    # foolproof
+    except Errors.MembershipIsRejectedByPolicy:
+        results = _(""" Your subscription is not allowed because the list
+        don't accept any new subscriptions by policy.""")
+        return STOP
     except Errors.MMBadEmailError:
         res.results.append(_("""\
 Mailman won't accept the given email address as a valid address.

=== modified file 'Mailman/Defaults.py.in'
--- Mailman/Defaults.py.in	2018-01-30 04:06:24 +0000
+++ Mailman/Defaults.py.in	2018-06-01 16:42:47 +0000
@@ -1310,6 +1310,7 @@
 # 1 - confirmation required for subscribes
 # 2 - admin approval required for subscribes
 # 3 - both confirmation and admin approval required
+# 4 - forbid new subscription
 #
 # ** please do not choose option 0 if you are not allowing open
 # subscribes (next variable)

=== modified file 'Mailman/Errors.py'
--- Mailman/Errors.py	2009-01-20 20:22:08 +0000
+++ Mailman/Errors.py	2018-06-01 16:42:47 +0000
@@ -40,6 +40,7 @@
 class CantDigestError(MemberError): pass
 class MustDigestError(MemberError): pass
 class MembershipIsBanned(MemberError): pass
+class MembershipIsRejectedByPolicy(MemberError): pass
 
 # Exception hierarchy for various authentication failures, can be
 # raised from functions in SecurityManager.py

=== modified file 'Mailman/Gui/Privacy.py'
--- Mailman/Gui/Privacy.py	2017-06-06 05:47:05 +0000
+++ Mailman/Gui/Privacy.py	2018-06-01 16:42:47 +0000
@@ -59,7 +59,8 @@
                            (_('None'),
                             _('Confirm'),
                             _('Require approval'),
-                            _('Confirm and approve')),
+                            _('Confirm and approve'),
+                            _('Forbid')),
                            0,
                            _('What steps are required for subscription?<br>'),
                            _("""None - no verification steps (<em>Not
@@ -67,7 +68,8 @@
                            Confirm (*) - email confirmation step required <br>
                            Require approval - require list administrator
                            Approval for subscriptions <br>
-                           Confirm and approve - both confirm and approve
+                           Confirm and approve - both confirm and approve <br>
+                           Forbid - reject all new subscription request
                            
                            <p>(*) when someone requests a subscription,
                            Mailman sends them a notice with a unique
@@ -82,13 +84,15 @@
                            # choices
                            (_('Confirm'),
                             _('Require approval'),
-                            _('Confirm and approve')),
+                            _('Confirm and approve'),
+                            _('Forbid')),
                            1,
                            _('What steps are required for subscription?<br>'),
                            _("""Confirm (*) - email confirmation required <br>
                            Require approval - require list administrator
                            approval for subscriptions <br>
-                           Confirm and approve - both confirm and approve
+                           Confirm and approve - both confirm and approve <br>
+                           Forbid - reject all new subscription request
                            
                            <p>(*) when someone requests a subscription,
                            Mailman sends them a notice with a unique

=== modified file 'Mailman/HTMLFormatter.py'
--- Mailman/HTMLFormatter.py	2017-07-31 00:37:30 +0000
+++ Mailman/HTMLFormatter.py	2018-06-01 16:42:47 +0000
@@ -202,6 +202,10 @@
             by the list moderator.  You will be notified of the moderator's
             decision by email.""")
             also = _("also ")
+        elif self.subscribe_policy == 4:
+            msg += _("""This is a closed list which don't accept any new
+            subscription request.""")
+            also = _("also ")
         if msg:
             msg += ' '
         if self.private_roster == 1:

=== modified file 'Mailman/MailList.py'
--- Mailman/MailList.py	2018-04-11 09:36:40 +0000
+++ Mailman/MailList.py	2018-06-01 16:42:47 +0000
@@ -898,6 +898,15 @@
             # Trying to subscribe the list to itself!
             raise Errors.MMBadEmailError
         realname = self.real_name
+        # Is the list allow new subscription?
+        if self.subscribe_policy == 4:
+            if remote:
+                whence = ' from %s' % remote
+            else:
+                whence = ''
+            syslog('vette', '%s reject subscription: %s%s (by policy)',
+                   realname, email, whence)
+            raise Errors.MembershipIsRejectedByPolicy
         # Is the subscribing address banned from this list?
         pattern = self.GetBannedPattern(email)
         if pattern:

=== modified file 'misc/sitelist.cfg'
--- misc/sitelist.cfg	2009-01-11 16:06:13 +0000
+++ misc/sitelist.cfg	2018-06-01 16:42:47 +0000
@@ -178,6 +178,7 @@
 #    1 = "Confirm"
 #    2 = "Require approval"
 #    3 = "Confirm and approve"
+#    4 = "Forbid"
 subscribe_policy = 2
 
 # When members want to leave a list, they will make an unsubscription

=== added file 'templates/en/listinfo_nosubscribe.html'
--- templates/en/listinfo_nosubscribe.html	1970-01-01 00:00:00 +0000
+++ templates/en/listinfo_nosubscribe.html	2018-06-01 16:42:47 +0000
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- $Revision: 5865 $ -->
+<HTML>
+  <HEAD>
+    <TITLE><MM-List-Name> Info Page</TITLE>
+  
+  </HEAD>
+  <BODY BGCOLOR="#ffffff">
+
+    <P>
+      <TABLE BORDER="0" CELLSPACING="4" CELLPADDING="5">
+	<TR>
+	  <TD COLSPAN="2" WIDTH="100%" BGCOLOR="#99CCFF" ALIGN="CENTER">
+	    <B><FONT COLOR="#000000" SIZE="+1"><MM-List-Name> --
+	<MM-List-Description></FONT></B>
+	  </TD>
+	</TR>
+	<tr>
+	    <td colspan="2">
+	      <p>&nbsp;
+	    </td>
+	  </tr>
+	  <tr>
+	    <TD COLSPAN="1" WIDTH="100%" BGCOLOR="#FFF0D0">
+	      <B><FONT COLOR="#000000">About <MM-List-Name></FONT></B>
+	    </TD>
+            <TD COLSPAN="1" WIDTH="100%" BGCOLOR="#FFF0D0">
+              <MM-lang-form-start><MM-displang-box> <MM-list-langs>
+              <MM-form-end>
+            </TD>
+	  </TR>
+	    <tr>
+	      <td colspan="2">
+		<P><MM-List-Info></P>
+	  <p> To see the collection of prior postings to the list,
+	      visit the <MM-Archive><MM-List-Name>
+		  Archives</MM-Archive>.
+	      <MM-Restricted-List-Message>
+	  </p>
+	</TD>
+      </TR>
+      <TR>
+	<TD COLSPAN="2" WIDTH="100%" BGCOLOR="#FFF0D0">
+	  <B><FONT COLOR="#000000">Using <MM-List-Name></FONT></B>
+	</TD>
+      </TR>
+      <tr>
+	<td colspan="2">
+	  To post a message to all the list members, send email to
+	  <A HREF="mailto:<MM-Posting-Addr>"><MM-Posting-Addr></A>.
+
+	  <p>You can change your existing
+	    subscription, in the sections below.
+	</td>
+      </tr>
+    <TR>
+      <TD COLSPAN="2" WIDTH="100%" BGCOLOR="#FFF0D0">
+	<a name="subscribers">
+        <B><FONT COLOR="#000000"><MM-List-Name> Subscribers</FONT></B></a>
+      </TD>
+    </TR>
+    <tr>
+      <TD COLSPAN="2" WIDTH="100%">
+	<MM-Roster-Form-Start>
+	<MM-Roster-Option>
+	    <MM-Form-End>
+	  <p>
+	<MM-Options-Form-Start>
+	<MM-Editing-Options>
+		<MM-Form-End>
+      </td>
+    </tr>
+  </table>
+<MM-Mailman-Footer>
+</BODY>
+</HTML>

=== added file 'templates/ja/listinfo_nosubscribe.html'
--- templates/ja/listinfo_nosubscribe.html	1970-01-01 00:00:00 +0000
+++ templates/ja/listinfo_nosubscribe.html	2018-06-01 16:42:47 +0000
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- $Revision: 6837 $ -->
+<HTML>
+  <HEAD>
+    <TITLE><MM-List-Name> ����ڡ���</TITLE>
+  
+  </HEAD>
+  <BODY BGCOLOR="#ffffff">
+
+    <P>
+      <TABLE BORDER="0" CELLSPACING="4" CELLPADDING="5">
+	<TR>
+	  <TD COLSPAN="2" WIDTH="100%" BGCOLOR="#99CCFF" ALIGN="CENTER">
+	    <B><FONT COLOR="#000000" SIZE="+1"><MM-List-Name> --
+	<MM-List-Description></FONT></B>
+	  </TD>
+	</TR>
+	<tr>
+	    <td colspan="2">
+	      <p>&nbsp;
+	    </td>
+	  </tr>
+	  <tr>
+	    <TD COLSPAN="1" WIDTH="70%" BGCOLOR="#FFF0D0">
+	      <B><FONT COLOR="#000000"><MM-List-Name>�ˤĤ���</FONT></B>
+	    </TD>
+            <TD COLSPAN="1" WIDTH="30%" BGCOLOR="#FFF0D0">
+              <MM-lang-form-start> <MM-displang-box> <MM-list-langs>
+              <MM-form-end>
+            </TD>
+
+	  </TR>
+	    <tr>
+	      <td colspan="2">
+		<P><MM-List-Info></P>
+	  <p> ���Υ᡼��󥰥ꥹ�Ȥ���Ƥ��줿���Υ᡼���,
+	      <MM-Archive><MM-List-Name>
+		  ��¸���</MM-Archive>����������.
+	      <MM-Restricted-List-Message>
+	  </p>
+	</TD>
+      </TR>
+      <TR>
+	<TD COLSPAN="2" WIDTH="100%" BGCOLOR="#FFF0D0">
+	  <B><FONT COLOR="#000000"><MM-List-Name> ������ˡ</FONT></B>
+	</TD>
+      </TR>
+      <tr>
+	<td colspan="2">
+	  �᡼��󥰥ꥹ�Ȥ������������᡼���, 
+	  <A HREF="mailto:<MM-Posting-Addr>"><MM-Posting-Addr></A>
+          �Υ��ɥ쥹�����������Ƥ�������.
+
+	  <p>�᡼��󥰥ꥹ�Ȥθ��ߤβ�����ץ������ѹ���, 
+          �ʲ��Υե���������Ѥ�������.
+	</td>
+      </tr>
+    <TR>
+      <TD COLSPAN="2" WIDTH="100%" BGCOLOR="#FFF0D0">
+	<a name="subscribers">
+        <B><FONT COLOR="#000000"><MM-List-Name> ���������</FONT></B></a>
+      </TD>
+    </TR>
+    <tr>
+      <TD COLSPAN="2" WIDTH="100%">
+	<MM-Roster-Form-Start>
+	<MM-Roster-Option>
+	    <MM-Form-End>
+	  <p>
+        <MM-Options-Form-Start>
+	<MM-Editing-Options>
+		<MM-Form-End>
+      </td>
+    </tr>
+  </table>
+<MM-Mailman-Footer>
+</BODY>
+</HTML>

_______________________________________________
Mailman-coders mailing list
[email protected]
https://mail.python.org/mailman/listinfo/mailman-coders

Reply via email to