summaryrefslogtreecommitdiff
path: root/addons/mass_mailing/controllers/main.py
diff options
context:
space:
mode:
authorOlivier Dony <odo@odoo.com>2018-09-29 02:22:11 +0200
committerOlivier Dony <odo@odoo.com>2018-09-29 04:47:44 +0200
commit2ff9b379ef80ba6a8744fb9702a8088284372ddd (patch)
tree2808df888417675ffa8e93022aa890130e61d14b /addons/mass_mailing/controllers/main.py
parent2cee34fea2bccf3320f0d09969e300361995d428 (diff)
[FIX] mail: fix blacklist mechanism
Several quick fixes: - repair malformed SQL queries and injection problems - proper token comparisons (consteq) - better translatable terms (less context-lessplaceholders) - basic testing of case-(in)sensitivity of blacklist - safety check for non-implemented cases in search methods for computed field More testing and review is needed for case-sensitivity and email extraction from generic "addressing fields".
Diffstat (limited to 'addons/mass_mailing/controllers/main.py')
-rw-r--r--addons/mass_mailing/controllers/main.py50
1 files changed, 30 insertions, 20 deletions
diff --git a/addons/mass_mailing/controllers/main.py b/addons/mass_mailing/controllers/main.py
index 5909a3a6433..18b8a814dac 100644
--- a/addons/mass_mailing/controllers/main.py
+++ b/addons/mass_mailing/controllers/main.py
@@ -11,6 +11,17 @@ from odoo.tools import consteq
class MassMailController(http.Controller):
+ def _valid_unsubscribe_token(self, mailing_id, res_id, email, token):
+ if not (mailing_id and res_id and email and token):
+ return False
+ mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
+ return consteq(mailing._unsubscribe_token(res_id, email), token)
+
+ def _log_blacklist_action(self, blacklist_entry, mailing_id, description):
+ mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
+ model_display = mailing.mailing_model_id.display_name
+ blacklist_entry._message_log(description + " ({})".format(model_display))
+
@http.route(['/unsubscribe_from_list'], type='http', website=True, multilang=False, auth='public')
def unsubscribe_placeholder_link(self, **post):
"""Dummy route so placeholder is not prefixed by language, MUST have multilang=False"""
@@ -21,8 +32,7 @@ class MassMailController(http.Controller):
mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
if mailing.exists():
res_id = res_id and int(res_id)
- right_token = mailing._unsubscribe_token(res_id, email)
- if not consteq(str(token), right_token):
+ if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)):
raise exceptions.AccessDenied()
if mailing.mailing_model_real == 'mail.mass_mailing.contact':
@@ -50,26 +60,27 @@ class MassMailController(http.Controller):
'mailing_id': mailing_id,
'res_id': res_id,
'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param('mass_mailing.show_blacklist_buttons'),
- })
+ })
else:
blacklist_rec = request.env['mail.blacklist'].sudo()._add(email)
- blacklist_rec._message_log(_("""The %s asked to not be contacted anymore
- using an unsubscribe link.""" % request.env['ir.model']._get(mailing.mailing_model_real).display_name))
+ self._log_blacklist_action(
+ blacklist_rec, mailing_id,
+ _("""Requested blacklisting via unsubscribe link."""))
return request.render('mass_mailing.page_unsubscribed', {
'email': email,
'mailing_id': mailing_id,
'res_id': res_id,
'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param(
'mass_mailing.show_blacklist_buttons'),
- })
+ })
return request.redirect('/web')
@http.route('/mail/mailing/unsubscribe', type='json', auth='none')
def unsubscribe(self, mailing_id, opt_in_ids, opt_out_ids, email, res_id, token):
mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
- if mailing._unsubscribe_token(res_id, email) != token:
- return 'unauthorized'
if mailing.exists():
+ if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
+ return 'unauthorized'
mailing.update_opt_out(email, opt_in_ids, False)
mailing.update_opt_out(email, opt_out_ids, True)
return True
@@ -96,8 +107,7 @@ class MassMailController(http.Controller):
@http.route('/mailing/blacklist/check', type='json', auth='none')
def blacklist_check(self, mailing_id, res_id, email, token):
- mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
- if mailing._unsubscribe_token(res_id, email) != token:
+ if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
return 'unauthorized'
if email:
record = request.env['mail.blacklist'].sudo().with_context(active_test=False).search([('email', '=ilike', email)])
@@ -108,34 +118,34 @@ class MassMailController(http.Controller):
@http.route('/mailing/blacklist/add', type='json', auth='none')
def blacklist_add(self, mailing_id, res_id, email, token):
- mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
- if mailing._unsubscribe_token(res_id, email) != token:
+ if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
return 'unauthorized'
if email:
blacklist_rec = request.env['mail.blacklist'].sudo()._add(email)
- blacklist_rec._message_log(_("""The %s asked to not be contacted anymore
- using the unsubscription page.""" % request.env['ir.model']._get(mailing.mailing_model_real).display_name))
+ self._log_blacklist_action(
+ blacklist_rec, mailing_id,
+ _("""Requested blacklisting via unsubscription page."""))
return True
return 'error'
@http.route('/mailing/blacklist/remove', type='json', auth='none')
def blacklist_remove(self, mailing_id, res_id, email, token):
- mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
- if mailing._unsubscribe_token(res_id, email) != token:
+ if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
return 'unauthorized'
if email:
blacklist_rec = request.env['mail.blacklist'].sudo()._remove(email)
- blacklist_rec._message_log(_("""The %s asked to be removed from the blacklist
- using the unsubscription page.""" % request.env['ir.model']._get(mailing.mailing_model_real).display_name))
+ self._log_blacklist_action(
+ blacklist_rec, mailing_id,
+ _("""Requested de-blacklisting via unsubscription page."""))
return True
return 'error'
@http.route('/mailing/feedback', type='json', auth='none')
def send_feedback(self, mailing_id, res_id, email, feedback, token):
mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
- if mailing._unsubscribe_token(res_id, email) != token:
- return 'unauthorized'
if mailing.exists() and email:
+ if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
+ return 'unauthorized'
model = request.env[mailing.mailing_model_real]
[email_field] = model._primary_email
records = model.sudo().search([(email_field, '=ilike', email)])