Merge lp:~jks/mailman/hcaptcha into lp:mailman/2.1

Proposed by Jouni K. Seppänen
Status: Needs review
Proposed branch: lp:~jks/mailman/hcaptcha
Merge into: lp:mailman/2.1
Diff against target: 125 lines (+59/-11)
3 files modified
Mailman/Cgi/listinfo.py (+13/-3)
Mailman/Cgi/subscribe.py (+40/-8)
Mailman/Defaults.py.in (+6/-0)
To merge this branch: bzr merge lp:~jks/mailman/hcaptcha
Reviewer Review Type Date Requested Status
Jim Popovitch (community) Approve
Mark Sapiro process Disapprove
Review via email: mp+389691@code.launchpad.net

Description of the change

I noticed that a Mailman 2.1 site I run was being used for sending subscribe confirmation messages to people. I didn't want to implement reCaptcha because of privacy concerns, and hCaptcha seems to be almost a drop-in replacement that at least promises to respect user privacy. This change allows using hCaptcha instead of reCaptcha for guarding the subscription form.

When testing, the dummy keys from https://docs.hcaptcha.com/#localdev may be useful:

Dummy Site Key:10000000-ffff-ffff-ffff-000000000001
Dummy Secret Key:0x0000000000000000000000000000000000000000

To post a comment you must log in.
Revision history for this message
Mark Sapiro (msapiro) wrote :

Mailman 2.1 is end of life. No new features are being implemented.

review: Disapprove (process)
Revision history for this message
Jim Popovitch (jimpop) wrote :

If it has life, let it live....

If you love some(thing) set it free...

Revision history for this message
Jim Popovitch (jimpop) wrote :

BTW, python2 is fully supported until 2025 in Ubuntu 20.04 LTS (Focal)

https://lists.ubuntu.com/archives/ubuntu-announce/2020-April/000256.html

Revision history for this message
Mark Sapiro (msapiro) wrote :

I never said people weren't free to make their own forks. I just said I and the GNU Mailman project weren't going to do it. It's GPL'd. Have at it.

Revision history for this message
Jim Popovitch (jimpop) wrote :

If you just want to step aside and move on, then do it.

The question that never gets answered is: There are plenty of people involved with the project, how come you get to decide it dies? Let it die due to inactivity, sure.

Revision history for this message
Mark Sapiro (msapiro) wrote :

@jimpop For the last several years the only member of the Gnu Mailman project supporting the actual Mailman 2.1 code base has been me. I get to decide what I am willing to do. I'm not trying to kill Mailman 2.1. I have said I will accept i18n updates and fix security issues and critical bugs. I still actively support Mailman 2.1 users on the <email address hidden> list, but I am not implementing new features. That's all.

Revision history for this message
Jim Popovitch (jimpop) wrote :

So let me, jks, and anyone else who wants to jump in, maintain new features.

Revision history for this message
Mark Sapiro (msapiro) wrote :

I assume you aren't just asking permission to create and maintain your own branch on Launchpad and add it to your PPA, since you don't need my permission/approval to do that, so I guess you are asking for commit permission on https://code.launchpad.net/~mailman-coders/mailman/2.1 and the ability to add new releases to https://launchpad.net/mailman/2.1/, https://ftp.gnu.org/gnu/mailman/ and https://sourceforge.net/projects/mailman/ and perhaps the ability to update
http://www.list.org, https://www.gnu.org/software/mailman and http://mailman.sourceforge.net/.

If that is the case, I suggest you start by making a proposal to <email address hidden>.

Revision history for this message
Jouni K. Seppänen (jks) wrote :

Hey, I just needed to patch my own installation of Mailman and thought that the patch would be useful to others; I didn't propose to take on the burden of maintaining Mailman. Apparently this patch wasn't welcome, which is certainly fair enough.

Perhaps eventually I will find the time and energy to attempt a migration to Mailman 3 and figure out if it already has hCaptcha support or similar protection against subscription spam. Until such time, it seems I'll have to be running a patched version, and perhaps others in a similar situation can find this patch here.

Revision history for this message
Jim Popovitch (jimpop) wrote :

> I assume you aren't just asking permission to create and maintain your own
> branch on Launchpad and add it to your PPA, since you don't need my
> permission/approval to do that, so I guess you are asking for commit
> permission on https://code.launchpad.net/~mailman-coders/mailman/2.1 and the
> ability to add new releases to https://launchpad.net/mailman/2.1/,
> https://ftp.gnu.org/gnu/mailman/ and https://sourceforge.net/projects/mailman/
> and perhaps the ability to update
> http://www.list.org, https://www.gnu.org/software/mailman and
> http://mailman.sourceforge.net/.

All that would be wonderful, but that's overkill. What is needed is the ability to approve new features and to commit them into the original and common code base that has been in place for decades now. Sure, anyone can do that in their own fork, but the mm2 project is where it should be done. I understand that your personal opinion is that you don't want to do that. No one should be upset or offended by you deciding that you don't want to do something; people should applaud that.

> If that is the case, I suggest you start by making a proposal to mailman-
> <email address hidden>.

Noted. I don't see a need for any great changes other than one or two additional people to test and approve new features that come up once or twice a year. I'll make a post on the list to ask for one or two others to join me in coming up with a proposal. Thanks.

review: Approve

Unmerged revisions

1861. By Jouni K. Seppänen

Allow using hCaptcha in addition to reCaptcha

hCaptcha is allegedly better for user privacy.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Mailman/Cgi/listinfo.py'
--- Mailman/Cgi/listinfo.py 2019-06-19 23:56:49 +0000
+++ Mailman/Cgi/listinfo.py 2020-08-23 10:21:44 +0000
@@ -263,15 +263,25 @@
263 replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname', size=30)263 replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname', size=30)
264 # If reCAPTCHA is enabled, display its user interface264 # If reCAPTCHA is enabled, display its user interface
265 if mm_cfg.RECAPTCHA_SITE_KEY:265 if mm_cfg.RECAPTCHA_SITE_KEY:
266 captcha_api = 'https://www.google.com/recaptcha/api.js?hl=%s' % lang
267 div_class = 'g-recaptcha'
268 sitekey = mm_cfg.RECAPTCHA_SITE_KEY
269 elif mm_cfg.HCAPTCHA_SITE_KEY:
270 captcha_api = 'https://hcaptcha.com/1/api.js?hl=%s' % lang
271 div_class = 'h-captcha'
272 sitekey = mm_cfg.HCAPTCHA_SITE_KEY
273 else:
274 captcha_api = None
275 if captcha_api is not None:
266 noscript = _('This form requires JavaScript.')276 noscript = _('This form requires JavaScript.')
267 replacements['<mm-recaptcha-ui>'] = (277 replacements['<mm-recaptcha-ui>'] = (
268 """<tr><td>&nbsp;</td><td>278 """<tr><td>&nbsp;</td><td>
269 <noscript>%s</noscript>279 <noscript>%s</noscript>
270 <script src="https://www.google.com/recaptcha/api.js?hl=%s">280 <script src="%s">
271 </script>281 </script>
272 <div class="g-recaptcha" data-sitekey="%s"></div>282 <div class="%s" data-sitekey="%s"></div>
273 </td></tr>"""283 </td></tr>"""
274 % (noscript, lang, mm_cfg.RECAPTCHA_SITE_KEY))284 % (noscript, captcha_api, div_class, sitekey))
275 else:285 else:
276 replacements['<mm-recaptcha-ui>'] = ''286 replacements['<mm-recaptcha-ui>'] = ''
277287
278288
=== modified file 'Mailman/Cgi/subscribe.py'
--- Mailman/Cgi/subscribe.py 2020-06-10 22:04:26 +0000
+++ Mailman/Cgi/subscribe.py 2020-08-23 10:21:44 +0000
@@ -39,6 +39,25 @@
39SLASH = '/'39SLASH = '/'
40ERRORSEP = '\n\n<p>'40ERRORSEP = '\n\n<p>'
41COMMASPACE = ', '41COMMASPACE = ', '
42CAPTCHA = {
43 'recaptcha': {
44 'name': 'reCAPTCHA',
45 'verify': 'https://www.google.com/recaptcha/api/siteverify',
46 'secret_key': mm_cfg.RECAPTCHA_SECRET_KEY,
47 'site_key': mm_cfg.RECAPTCHA_SITE_KEY,
48 'value': 'g-recaptcha-response',
49 'include_site_key': False
50 },
51 'hcaptcha': {
52 'name': 'hCAPTCHA',
53 'verify': 'https://hcaptcha.com/siteverify',
54 'secret_key': mm_cfg.HCAPTCHA_SECRET_KEY,
55 'site_key': mm_cfg.HCAPTCHA_SITE_KEY,
56 'value': 'h-captcha-response',
57 'include_site_key': True
58 },
59}
60
4261
43# Set up i18n62# Set up i18n
44_ = i18n._63_ = i18n._
@@ -136,24 +155,37 @@
136 os.environ.get('REMOTE_ADDR',155 os.environ.get('REMOTE_ADDR',
137 'unidentified origin')))156 'unidentified origin')))
138157
139 # Check reCAPTCHA submission, if enabled158 # Check reCAPTCHA/hCAPTCHA submission, if enabled
140 if mm_cfg.RECAPTCHA_SECRET_KEY:159 if mm_cfg.RECAPTCHA_SECRET_KEY:
160 captcha = CAPTCHA['recaptcha']
161 elif mm_cfg.HCAPTCHA_SECRET_KEY:
162 captcha = CAPTCHA['hcaptcha']
163 else:
164 captcha = None
165
166 if captcha is not None:
167 name = captcha['name']
168 data = {
169 'secret': captcha['secret_key'],
170 'response': cgidata.getvalue(captcha['value'], ''),
171 'remoteip': remote
172 }
173 if captcha['include_site_key']:
174 data['sitekey'] = captcha['site_key']
141 request = urllib2.Request(175 request = urllib2.Request(
142 url = 'https://www.google.com/recaptcha/api/siteverify',176 url = captcha['verify'],
143 data = urllib.urlencode({177 data = urllib.urlencode(data)
144 'secret': mm_cfg.RECAPTCHA_SECRET_KEY,178 )
145 'response': cgidata.getvalue('g-recaptcha-response', ''),
146 'remoteip': remote}))
147 try:179 try:
148 httpresp = urllib2.urlopen(request)180 httpresp = urllib2.urlopen(request)
149 captcha_response = json.load(httpresp)181 captcha_response = json.load(httpresp)
150 httpresp.close()182 httpresp.close()
151 if not captcha_response['success']:183 if not captcha_response['success']:
152 e_codes = COMMASPACE.join(captcha_response['error-codes'])184 e_codes = COMMASPACE.join(captcha_response['error-codes'])
153 results.append(_('reCAPTCHA validation failed: %(e_codes)s'))185 results.append(_('%(name)s validation failed: %(e_codes)s'))
154 except urllib2.URLError, e:186 except urllib2.URLError, e:
155 e_reason = e.reason187 e_reason = e.reason
156 results.append(_('reCAPTCHA could not be validated: %(e_reason)s'))188 results.append(_('%(name)s could not be validated: %(e_reason)s'))
157189
158 # Are we checking the hidden data?190 # Are we checking the hidden data?
159 if mm_cfg.SUBSCRIBE_FORM_SECRET:191 if mm_cfg.SUBSCRIBE_FORM_SECRET:
160192
=== modified file 'Mailman/Defaults.py.in'
--- Mailman/Defaults.py.in 2020-06-10 22:04:26 +0000
+++ Mailman/Defaults.py.in 2020-08-23 10:21:44 +0000
@@ -156,6 +156,12 @@
156RECAPTCHA_SITE_KEY = None156RECAPTCHA_SITE_KEY = None
157RECAPTCHA_SECRET_KEY = None157RECAPTCHA_SECRET_KEY = None
158158
159# Use hCAPTCHA to protect the subscription form from spam bots, as an
160# alternative to the Google reCAPTCHA (at most one of the two can be enabled).
161# Obtain the following keys from https://www.hcaptcha.com
162HCAPTCHA_SITE_KEY = None
163HCAPTCHA_SECRET_KEY = None
164
159# Installation wide ban list. This is a list of email addresses and regexp165# Installation wide ban list. This is a list of email addresses and regexp
160# patterns (beginning with ^) which are not allowed to subscribe to any lists166# patterns (beginning with ^) which are not allowed to subscribe to any lists
161# in the installation. This supplements the individual list's ban_list.167# in the installation. This supplements the individual list's ban_list.