David Siebörger has proposed merging lp:~dsieborger/mailman/recaptcha into 
lp:mailman/2.1.

Requested reviews:
  Mailman Coders (mailman-coders)

For more details, see:
https://code.launchpad.net/~dsieborger/mailman/recaptcha/+merge/336782

This adds support for using the Google reCAPTCHA service to protect the list 
subscription form from spam bots.  Our Mailman installation has been targeted 
by spam bots which are able to defeat the protection offered by 
SUBSCRIBE_FORM_SECRET and SUBSCRIBE_FORM_MIN_TIME, and they were sending 
invitations at a rate of ~10 per minute.

To enable this, sign up for the service at https://www.google.com/recaptcha to 
create a pair of keys for your site.  Once those keys are set as the 
configuration variables RECAPTCHA_SECRET_KEY and RECAPTCHA_SITE_KEY, 
Mailman/Cgi/listinfo.py will show the reCAPTCHA interface on the list 
subscription form, and Mailman/Cgi/subscribe.py will verify that the captcha 
was correctly completed via a Google API.  I've avoided adding any text to the 
listinfo.html template as I wouldn't be able to translate it, but reCAPTCHA's 
UI does show the "I'm not a robot" prompt according to the browser's language 
preferences.

This was inspired by an existing patch[1] by Andrea Veri, but uses reCAPTCHA v2 
as the reCAPTCHA v1 API is about to be discontinued.

[1] https://www.dragonsreach.it/2014/05/03/adding-recaptcha-support-to-mailman/

-- 
Your team Mailman Coders is requested to review the proposed merge of 
lp:~dsieborger/mailman/recaptcha into lp:mailman/2.1.
=== modified file 'Mailman/Cgi/listinfo.py'
--- Mailman/Cgi/listinfo.py	2017-06-06 05:47:05 +0000
+++ Mailman/Cgi/listinfo.py	2018-01-29 15:08:57 +0000
@@ -243,6 +243,16 @@
     replacements['<mm-displang-box>'] = displang
     replacements['<mm-lang-form-start>'] = mlist.FormatFormStart('listinfo')
     replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname', size=30)
+    # If reCAPTCHA is enabled, display its user interface
+    if mm_cfg.RECAPTCHA_SITE_KEY:
+        replacements['<mm-recaptcha-ui>'] = (
+            """<tr><td>&nbsp;</td><td>
+            <script src="https://www.google.com/recaptcha/api.js";></script>
+            <div class="g-recaptcha" data-sitekey="%s"></div>
+            </td></tr>"""
+            % mm_cfg.RECAPTCHA_SITE_KEY)
+    else:
+        replacements['<mm-recaptcha-ui>'] = ''
 
     # Do the expansion.
     doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang))

=== modified file 'Mailman/Cgi/subscribe.py'
--- Mailman/Cgi/subscribe.py	2017-06-06 05:47:05 +0000
+++ Mailman/Cgi/subscribe.py	2018-01-29 15:08:57 +0000
@@ -22,6 +22,9 @@
 import cgi
 import time
 import signal
+import urllib
+import urllib2
+import json
 
 from Mailman import mm_cfg
 from Mailman import Utils
@@ -131,6 +134,25 @@
              os.environ.get('HTTP_X_FORWARDED_FOR',
              os.environ.get('REMOTE_ADDR',
                             'unidentified origin')))
+
+    # Check reCAPTCHA submission, if enabled
+    if mm_cfg.RECAPTCHA_SECRET_KEY:
+        request = urllib2.Request(
+            url = 'https://www.google.com/recaptcha/api/siteverify',
+            data = urllib.urlencode({
+                'secret': mm_cfg.RECAPTCHA_SECRET_KEY,
+                'response': cgidata.getvalue('g-recaptcha-response', ''),
+                'remoteip': remote}))
+        try:
+            httpresp = urllib2.urlopen(request)
+            captcha_response = json.load(httpresp)
+            httpresp.close()
+            if not captcha_response['success']:
+                results.append(_('reCAPTCHA validation failed: %s' %
+                    ', '.join(captcha_response['error-codes'])))
+        except urllib2.URLError as e:
+            results.append(_('reCAPTCHA could not be validated: %s' % e.reason))
+
     # Are we checking the hidden data?
     if mm_cfg.SUBSCRIBE_FORM_SECRET:
         now = int(time.time())

=== modified file 'Mailman/Defaults.py.in'
--- Mailman/Defaults.py.in	2017-11-06 11:23:01 +0000
+++ Mailman/Defaults.py.in	2018-01-29 15:08:57 +0000
@@ -131,6 +131,12 @@
 # test.
 SUBSCRIBE_FORM_MIN_TIME = seconds(5)
 
+# Use Google reCAPTCHA to protect the subscription form from spam bots.  The
+# following must be set to a pair of keys issued by the reCAPTCHA service at
+# https://www.google.com/recaptcha/
+RECAPTCHA_SITE_KEY = None
+RECAPTCHA_SECRET_KEY = None
+
 # Installation wide ban list.  This is a list of email addresses and regexp
 # patterns (beginning with ^) which are not allowed to subscribe to any lists
 # in the installation.  This supplements the individual list's ban_list.

=== modified file 'templates/ar/listinfo.html'
--- templates/ar/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/ar/listinfo.html	2018-01-29 15:08:57 +0000
@@ -111,6 +111,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/ast/listinfo.html'
--- templates/ast/listinfo.html	2009-12-08 23:25:52 +0000
+++ templates/ast/listinfo.html	2018-01-29 15:08:57 +0000
@@ -103,6 +103,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></P></center>

=== modified file 'templates/ca/listinfo.html'
--- templates/ca/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/ca/listinfo.html	2018-01-29 15:08:57 +0000
@@ -114,6 +114,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
               <td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/cs/listinfo.html'
--- templates/cs/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/cs/listinfo.html	2018-01-29 15:08:57 +0000
@@ -112,6 +112,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/da/listinfo.html'
--- templates/da/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/da/listinfo.html	2018-01-29 15:08:57 +0000
@@ -108,6 +108,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/de/listinfo.html'
--- templates/de/listinfo.html	2018-01-12 12:44:15 +0000
+++ templates/de/listinfo.html	2018-01-29 15:08:57 +0000
@@ -114,6 +114,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/el/listinfo.html'
--- templates/el/listinfo.html	2012-06-20 23:32:30 +0000
+++ templates/el/listinfo.html	2018-01-29 15:08:57 +0000
@@ -116,6 +116,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></P></center>

=== modified file 'templates/en/listinfo.html'
--- templates/en/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/en/listinfo.html	2018-01-29 15:08:57 +0000
@@ -115,6 +115,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/es/listinfo.html'
--- templates/es/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/es/listinfo.html	2018-01-29 15:08:57 +0000
@@ -115,6 +115,7 @@
 	    <MM-Digest-Radio-Button>  S&iacute;
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/et/listinfo.html'
--- templates/et/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/et/listinfo.html	2018-01-29 15:08:57 +0000
@@ -105,6 +105,7 @@
 	    <MM-Digest-Radio-Button>  Jah
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/eu/listinfo.html'
--- templates/eu/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/eu/listinfo.html	2018-01-29 15:08:57 +0000
@@ -113,6 +113,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/fa/listinfo.html'
--- templates/fa/listinfo.html	2013-07-18 22:14:15 +0000
+++ templates/fa/listinfo.html	2018-01-29 15:08:57 +0000
@@ -105,6 +105,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/fi/listinfo.html'
--- templates/fi/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/fi/listinfo.html	2018-01-29 15:08:57 +0000
@@ -118,6 +118,7 @@
 	    <MM-Digest-Radio-Button>  Kyll&auml;
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/fr/listinfo.html'
--- templates/fr/listinfo.html	2014-02-04 01:01:49 +0000
+++ templates/fr/listinfo.html	2018-01-29 15:08:57 +0000
@@ -118,6 +118,7 @@
 	</td>
        </tr>
 	<mm-digest-question-end>
+       <mm-recaptcha-ui>
        <tr>
  	<td colspan="3"> 	  
               <center><MM-Subscribe-Button></center>

=== modified file 'templates/gl/listinfo.html'
--- templates/gl/listinfo.html	2016-01-10 03:33:25 +0000
+++ templates/gl/listinfo.html	2018-01-29 15:08:57 +0000
@@ -114,6 +114,7 @@
 	    <MM-Digest-Radio-Button>  Si
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/he/listinfo.html'
--- templates/he/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/he/listinfo.html	2018-01-29 15:08:57 +0000
@@ -110,6 +110,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/hr/listinfo.html'
--- templates/hr/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/hr/listinfo.html	2018-01-29 15:08:57 +0000
@@ -112,6 +112,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/hu/listinfo.html'
--- templates/hu/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/hu/listinfo.html	2018-01-29 15:08:57 +0000
@@ -111,6 +111,7 @@
       </tr>
       <tr>
     <mm-digest-question-end>
+    <mm-recaptcha-ui>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>
     </td>

=== modified file 'templates/ia/listinfo.html'
--- templates/ia/listinfo.html	2015-02-18 21:30:11 +0000
+++ templates/ia/listinfo.html	2018-01-29 15:08:57 +0000
@@ -103,6 +103,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/it/listinfo.html'
--- templates/it/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/it/listinfo.html	2018-01-29 15:08:57 +0000
@@ -123,6 +123,7 @@
 	</TD>
 	</tr>
 	<mm-digest-question-end>
+	<mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/ja/listinfo.html'
--- templates/ja/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/ja/listinfo.html	2018-01-29 15:08:57 +0000
@@ -115,6 +115,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/ko/listinfo.html'
--- templates/ko/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/ko/listinfo.html	2018-01-29 15:08:57 +0000
@@ -110,6 +110,7 @@
 	    <MM-Digest-Radio-Button>  ��
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/lt/listinfo.html'
--- templates/lt/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/lt/listinfo.html	2018-01-29 15:08:57 +0000
@@ -111,6 +111,7 @@
 	    <MM-Digest-Radio-Button>  Taip
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/nl/listinfo.html'
--- templates/nl/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/nl/listinfo.html	2018-01-29 15:08:57 +0000
@@ -106,6 +106,7 @@
 	    <MM-Digest-Radio-Button>  Ja
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/no/listinfo.html'
--- templates/no/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/no/listinfo.html	2018-01-29 15:08:57 +0000
@@ -108,6 +108,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/pl/listinfo.html'
--- templates/pl/listinfo.html	2017-01-18 06:49:29 +0000
+++ templates/pl/listinfo.html	2018-01-29 15:08:57 +0000
@@ -113,6 +113,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/pt/listinfo.html'
--- templates/pt/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/pt/listinfo.html	2018-01-29 15:08:57 +0000
@@ -114,6 +114,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/pt_BR/listinfo.html'
--- templates/pt_BR/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/pt_BR/listinfo.html	2018-01-29 15:08:57 +0000
@@ -113,6 +113,7 @@
 	    <MM-Digest-Radio-Button>  Sim
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/ro/listinfo.html'
--- templates/ro/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/ro/listinfo.html	2018-01-29 15:08:57 +0000
@@ -109,6 +109,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/ru/listinfo.html'
--- templates/ru/listinfo.html	2015-02-05 21:15:37 +0000
+++ templates/ru/listinfo.html	2018-01-29 15:08:57 +0000
@@ -100,6 +100,7 @@
         </TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
         <td colspan="3">
           <center><MM-Subscribe-Button></center>

=== modified file 'templates/sk/listinfo.html'
--- templates/sk/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/sk/listinfo.html	2018-01-29 15:08:57 +0000
@@ -117,6 +117,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/sl/listinfo.html'
--- templates/sl/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/sl/listinfo.html	2018-01-29 15:08:57 +0000
@@ -112,6 +112,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/sr/listinfo.html'
--- templates/sr/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/sr/listinfo.html	2018-01-29 15:08:57 +0000
@@ -97,6 +97,7 @@
             <td><MM-Undigest-Radio-Button> Не<MM-Digest-Radio-Button> Да</TD>
           </tr>
           <mm-digest-question-end> 
+          <mm-recaptcha-ui>
           <tr> 
             <td colspan="3"> <center>
                 <MM-Subscribe-Button></center> 

=== modified file 'templates/sv/listinfo.html'
--- templates/sv/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/sv/listinfo.html	2018-01-29 15:08:57 +0000
@@ -94,6 +94,7 @@
 									<td><MM-Undigest-Radio-Button> Nej 	    <MM-Digest-Radio-Button> Ja	</TD>
 								</tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/tr/listinfo.html'
--- templates/tr/listinfo.html	2016-11-14 07:13:01 +0000
+++ templates/tr/listinfo.html	2018-01-29 15:08:57 +0000
@@ -115,6 +115,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/uk/listinfo.html'
--- templates/uk/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/uk/listinfo.html	2018-01-29 15:08:57 +0000
@@ -111,6 +111,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/vi/listinfo.html'
--- templates/vi/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/vi/listinfo.html	2018-01-29 15:08:57 +0000
@@ -102,6 +102,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/zh_CN/listinfo.html'
--- templates/zh_CN/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/zh_CN/listinfo.html	2018-01-29 15:08:57 +0000
@@ -107,6 +107,7 @@
 	</TD>
       </tr>
       <mm-digest-question-end>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

=== modified file 'templates/zh_TW/listinfo.html'
--- templates/zh_TW/listinfo.html	2010-01-28 23:06:44 +0000
+++ templates/zh_TW/listinfo.html	2018-01-29 15:08:57 +0000
@@ -98,6 +98,7 @@
 	    <MM-Digest-Radio-Button>  Yes
 	</TD>
       </tr>
+      <mm-recaptcha-ui>
       <tr>
 	<td colspan="3">
 	  <center><MM-Subscribe-Button></center>

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

Reply via email to