diff options
| author | Olivier Dony <odo@odoo.com> | 2018-09-29 02:22:11 +0200 |
|---|---|---|
| committer | Olivier Dony <odo@odoo.com> | 2018-09-29 04:47:44 +0200 |
| commit | 2ff9b379ef80ba6a8744fb9702a8088284372ddd (patch) | |
| tree | 2808df888417675ffa8e93022aa890130e61d14b /addons/mass_mailing/controllers/main.py | |
| parent | 2cee34fea2bccf3320f0d09969e300361995d428 (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.py | 50 |
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)]) |
