From 77a38af50d76780ea44b20a3f2459aa78f0524f0 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Fri, 19 Jun 2020 12:47:06 +0200 Subject: [PATCH] [ADD] mass_mailing_custom_unsubscribe_event: Allow to unsubscribe discretely from an event This addon extends the unsubscription process for allowing to unsubscribe only for an event. Standard process includes the mail in the general blacklist instead, which can be very unconvenient. This includes also the needed changes in the base module `mass_mailing_custom_unsubscribe`. --- mass_mailing_custom_unsubscribe/README.rst | 13 + .../__manifest__.py | 1 + .../controllers/main.py | 47 +- .../models/mail_mass_mailing.py | 43 +- .../readme/CONFIGURE.rst | 9 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 3 + .../static/description/index.html | 12 + .../README.rst | 91 ++++ .../__init__.py | 3 + .../__manifest__.py | 19 + .../models/__init__.py | 3 + .../models/event_registration.py | 14 + .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 5 + .../readme/USAGE.rst | 8 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 439 ++++++++++++++++++ .../views/event_registration_views.xml | 18 + 19 files changed, 716 insertions(+), 16 deletions(-) create mode 100644 mass_mailing_custom_unsubscribe_event/README.rst create mode 100644 mass_mailing_custom_unsubscribe_event/__init__.py create mode 100644 mass_mailing_custom_unsubscribe_event/__manifest__.py create mode 100644 mass_mailing_custom_unsubscribe_event/models/__init__.py create mode 100644 mass_mailing_custom_unsubscribe_event/models/event_registration.py create mode 100644 mass_mailing_custom_unsubscribe_event/readme/CONTRIBUTORS.rst create mode 100644 mass_mailing_custom_unsubscribe_event/readme/DESCRIPTION.rst create mode 100644 mass_mailing_custom_unsubscribe_event/readme/USAGE.rst create mode 100644 mass_mailing_custom_unsubscribe_event/static/description/icon.png create mode 100644 mass_mailing_custom_unsubscribe_event/static/description/index.html create mode 100644 mass_mailing_custom_unsubscribe_event/views/event_registration_views.xml diff --git a/mass_mailing_custom_unsubscribe/README.rst b/mass_mailing_custom_unsubscribe/README.rst index 4a1129d40..e585b58ee 100644 --- a/mass_mailing_custom_unsubscribe/README.rst +++ b/mass_mailing_custom_unsubscribe/README.rst @@ -33,6 +33,9 @@ This addon extends the unsubscription form to let you: mass mailing. - Provide proof on why you are sending mass mailings to a given contact, as required by the GDPR in Europe. +- Handle discrete unsubscriptions from other recipients that are not a mailing + list. On standard module, unsubscriptions from these recipients directly + include that mail on the general blacklist. **Table of contents** @@ -50,6 +53,15 @@ they are going to unsubscribe. To do it: #. If *Details required* is enabled, they will have to fill a text area to continue. +For having discrete unsubscriptions from other recipients than the mailing +lists, you need to add a glue module that adds 2 fields in the associated +model: + +- `opt_out`. +- Either `email` or `email_from`. + +See `mass_mailing_custom_unsubscribe_event` for an example. + Usage ===== @@ -98,6 +110,7 @@ Contributors * Jairo Llopis * David Vidal * Ernesto Tejeda + * Pedro M. Baeza Maintainers ~~~~~~~~~~~ diff --git a/mass_mailing_custom_unsubscribe/__manifest__.py b/mass_mailing_custom_unsubscribe/__manifest__.py index 15bd9835b..48cba81e2 100644 --- a/mass_mailing_custom_unsubscribe/__manifest__.py +++ b/mass_mailing_custom_unsubscribe/__manifest__.py @@ -1,5 +1,6 @@ # Copyright 2016 Jairo Llopis # Copyright 2018 David Vidal +# Copyright 2020 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'Customizable unsubscription process on mass mailing emails', diff --git a/mass_mailing_custom_unsubscribe/controllers/main.py b/mass_mailing_custom_unsubscribe/controllers/main.py index a4b62a159..5b5fc813a 100644 --- a/mass_mailing_custom_unsubscribe/controllers/main.py +++ b/mass_mailing_custom_unsubscribe/controllers/main.py @@ -1,5 +1,6 @@ # Copyright 2015 Antiun Ingeniería S.L. (http://www.antiun.com) # Copyright 2016 Jairo Llopis +# Copyright 2020 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import logging @@ -43,6 +44,7 @@ class CustomUnsubscribe(MassMailController): "Called `mailing()` with: %r", (mailing_id, email, res_id, token, post)) reasons = request.env["mail.unsubscription.reason"].search([]) + res_id = res_id and int(res_id) try: # Check if we already have a reason for unsubscription reason_id = int(post["reason_id"]) @@ -53,23 +55,38 @@ class CustomUnsubscribe(MassMailController): # Unsubscribe, saving reason and details by context details = post.get("details", False) self._add_extra_context(mailing_id, res_id, reason_id, details) - # You could get a DetailsRequiredError here, but only if HTML5 - # validation fails, which should not happen in modern browsers - result = super().mailing( - mailing_id, email, res_id, token=token, **post) - result.qcontext.update({"reasons": reasons}) - # update list_ids taking into account not_cross_unsubscriptable - # field mailing_obj = request.env['mail.mass_mailing'] - mailing = mailing_obj.sudo().browse(mailing_id) - if mailing.mailing_model_real == 'mail.mass_mailing.contact': - result.qcontext.update({ - "list_ids": result.qcontext["list_ids"].filtered( - lambda mailing_list: - not mailing_list.not_cross_unsubscriptable or - mailing_list in mailing.contact_list_ids - ) + mass_mailing = mailing_obj.sudo().browse(mailing_id) + model = mass_mailing.mailing_model_real + if "opt_out" in request.env[model]._fields: + mass_mailing.update_opt_out_other(email, [res_id], True) + result = 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" + ), }) + result.qcontext.update({"reasons": reasons}) + else: + # You could get a DetailsRequiredError here, but only if HTML5 + # validation fails, which should not happen in modern browsers + result = super().mailing( + mailing_id, email, res_id, token=token, **post) + if model == "mail.mass_mailing.contact": + # update list_ids taking into account + # not_cross_unsubscriptable field + result.qcontext.update({ + "reasons": reasons, + "list_ids": result.qcontext["list_ids"].filtered( + lambda mailing_list: + not mailing_list.not_cross_unsubscriptable or + mailing_list in mass_mailing.contact_list_ids + ) + }) return result @route() diff --git a/mass_mailing_custom_unsubscribe/models/mail_mass_mailing.py b/mass_mailing_custom_unsubscribe/models/mail_mass_mailing.py index f992702e6..0fd71a228 100644 --- a/mass_mailing_custom_unsubscribe/models/mail_mass_mailing.py +++ b/mass_mailing_custom_unsubscribe/models/mail_mass_mailing.py @@ -1,7 +1,9 @@ # Copyright 2016 Jairo Llopis +# Copyright 2020 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models +from odoo import models, tools +from odoo.tools.safe_eval import safe_eval from itertools import groupby @@ -31,3 +33,42 @@ class MailMassMailing(models.Model): "action": action, }) return super().update_opt_out(email, list_ids, value) + + def update_opt_out_other(self, email, res_ids, value): + """Method for changing unsubscription for models with opt_out field.""" + model = self.env[self.mailing_model_real].with_context( + active_test=False) + action = "unsubscription" if value else "subscription" + if 'opt_out' in model._fields: + email_fname = 'email_from' + if 'email' in model._fields: + email_fname = 'email' + records = model.search([ + ('id', 'in', res_ids), (email_fname, 'ilike', email)]) + records.write({'opt_out': value}) + for res_id in res_ids: + self.env["mail.unsubscription"].create({ + "email": email, + "mass_mailing_id": self.id, + "unsubscriber_id": "%s,%d" % ( + self.mailing_model_real, res_id), + "action": action, + }) + + def _get_opt_out_list(self): + """Handle models with opt_out field for excluding them.""" + self.ensure_one() + model = self.env[self.mailing_model_real].with_context( + active_test=False) + if (self.mailing_model_real != "mail.mass_mailing.contact" and + 'opt_out' in model._fields): + email_fname = 'email_from' + if 'email' in model._fields: + email_fname = 'email' + domain = safe_eval(self.mailing_domain) + domain = [('opt_out', '=', True)] + domain + recs = self.env[self.mailing_model_real].search(domain) + normalized_email = ( + tools.email_split(c[email_fname]) for c in recs) + return set(e[0].lower() for e in normalized_email if e) + return super()._get_opt_out_list() diff --git a/mass_mailing_custom_unsubscribe/readme/CONFIGURE.rst b/mass_mailing_custom_unsubscribe/readme/CONFIGURE.rst index e793672e5..f9ce968b7 100644 --- a/mass_mailing_custom_unsubscribe/readme/CONFIGURE.rst +++ b/mass_mailing_custom_unsubscribe/readme/CONFIGURE.rst @@ -5,3 +5,12 @@ they are going to unsubscribe. To do it: #. Create / edit / remove / sort as usual. #. If *Details required* is enabled, they will have to fill a text area to continue. + +For having discrete unsubscriptions from other recipients than the mailing +lists, you need to add a glue module that adds 2 fields in the associated +model: + +- `opt_out`. +- Either `email` or `email_from`. + +See `mass_mailing_custom_unsubscribe_event` for an example. diff --git a/mass_mailing_custom_unsubscribe/readme/CONTRIBUTORS.rst b/mass_mailing_custom_unsubscribe/readme/CONTRIBUTORS.rst index b4d6ec4a9..c2d056141 100644 --- a/mass_mailing_custom_unsubscribe/readme/CONTRIBUTORS.rst +++ b/mass_mailing_custom_unsubscribe/readme/CONTRIBUTORS.rst @@ -5,3 +5,4 @@ * Jairo Llopis * David Vidal * Ernesto Tejeda + * Pedro M. Baeza diff --git a/mass_mailing_custom_unsubscribe/readme/DESCRIPTION.rst b/mass_mailing_custom_unsubscribe/readme/DESCRIPTION.rst index 6806342ba..c289fc035 100644 --- a/mass_mailing_custom_unsubscribe/readme/DESCRIPTION.rst +++ b/mass_mailing_custom_unsubscribe/readme/DESCRIPTION.rst @@ -6,3 +6,6 @@ This addon extends the unsubscription form to let you: mass mailing. - Provide proof on why you are sending mass mailings to a given contact, as required by the GDPR in Europe. +- Handle discrete unsubscriptions from other recipients that are not a mailing + list. On standard module, unsubscriptions from these recipients directly + include that mail on the general blacklist. diff --git a/mass_mailing_custom_unsubscribe/static/description/index.html b/mass_mailing_custom_unsubscribe/static/description/index.html index d6c165868..415a40c13 100644 --- a/mass_mailing_custom_unsubscribe/static/description/index.html +++ b/mass_mailing_custom_unsubscribe/static/description/index.html @@ -376,6 +376,9 @@ from a different one. mass mailing.
  • Provide proof on why you are sending mass mailings to a given contact, as required by the GDPR in Europe.
  • +
  • Handle discrete unsubscriptions from other recipients that are not a mailing +list. On standard module, unsubscriptions from these recipients directly +include that mail on the general blacklist.
  • Table of contents

    @@ -402,6 +405,14 @@ they are going to unsubscribe. To do it:

  • If Details required is enabled, they will have to fill a text area to continue.
  • +

    For having discrete unsubscriptions from other recipients than the mailing +lists, you need to add a glue module that adds 2 fields in the associated +model:

    +
      +
    • opt_out.
    • +
    • Either email or email_from.
    • +
    +

    See mass_mailing_custom_unsubscribe_event for an example.

    Usage

    @@ -449,6 +460,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
  • Jairo Llopis
  • David Vidal
  • Ernesto Tejeda
  • +
  • Pedro M. Baeza
  • diff --git a/mass_mailing_custom_unsubscribe_event/README.rst b/mass_mailing_custom_unsubscribe_event/README.rst new file mode 100644 index 000000000..10ecb4314 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/README.rst @@ -0,0 +1,91 @@ +============================================= +Allow to unsubscribe discretely from an event +============================================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github + :target: https://github.com/OCA/social/tree/12.0/mass_mailing_custom_unsubscribe_event + :alt: OCA/social +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/social-12-0/social-12-0-mass_mailing_custom_unsubscribe_event + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/205/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon extends the unsubscription process for allowing to unsubscribe +only for an event. + +Standard process includes the mail in the general blacklist instead, which +can be very unconvenient. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +#. Go to *Email Marketing > Mailings > Create*. +#. Select "Event Registration" in *Recipients* field. +#. Edit your mass mailing at wish, but remember to add a snippet from + *Footers*, so people have an *Unsubscribe* link. +#. Send it. +#. If somebody gets unsubscribed, it will get unsubscribed only for that + event, but including that mail in other event, the registree will still + receive mailings. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * Pedro M. Baeza + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/social `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mass_mailing_custom_unsubscribe_event/__init__.py b/mass_mailing_custom_unsubscribe_event/__init__.py new file mode 100644 index 000000000..69f7babdf --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/mass_mailing_custom_unsubscribe_event/__manifest__.py b/mass_mailing_custom_unsubscribe_event/__manifest__.py new file mode 100644 index 000000000..c132fa912 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2020 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Allow to unsubscribe discretely from an event", + "category": "Marketing", + "version": "12.0.1.0.0", + "depends": [ + "event", + "mass_mailing_custom_unsubscribe", + ], + "author": "Tecnativa, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/social", + "data": [ + "views/event_registration_views.xml", + ], + "license": "AGPL-3", + "installable": True, + "auto_install": True, +} diff --git a/mass_mailing_custom_unsubscribe_event/models/__init__.py b/mass_mailing_custom_unsubscribe_event/models/__init__.py new file mode 100644 index 000000000..950934286 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import event_registration diff --git a/mass_mailing_custom_unsubscribe_event/models/event_registration.py b/mass_mailing_custom_unsubscribe_event/models/event_registration.py new file mode 100644 index 000000000..1fd67a4d6 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/models/event_registration.py @@ -0,0 +1,14 @@ +# Copyright 2020 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class EventRegistration(models.Model): + _inherit = 'event.registration' + + opt_out = fields.Boolean( + string='Opt-Out', + help="If opt-out is checked, this registree has refused to receive " + "emails for mass mailing and marketing campaign.") + # No need of email field, as it already exists diff --git a/mass_mailing_custom_unsubscribe_event/readme/CONTRIBUTORS.rst b/mass_mailing_custom_unsubscribe_event/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..2d4d7a884 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Tecnativa `_: + + * Pedro M. Baeza diff --git a/mass_mailing_custom_unsubscribe_event/readme/DESCRIPTION.rst b/mass_mailing_custom_unsubscribe_event/readme/DESCRIPTION.rst new file mode 100644 index 000000000..307efe31c --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/readme/DESCRIPTION.rst @@ -0,0 +1,5 @@ +This addon extends the unsubscription process for allowing to unsubscribe +only for an event. + +Standard process includes the mail in the general blacklist instead, which +can be very unconvenient. diff --git a/mass_mailing_custom_unsubscribe_event/readme/USAGE.rst b/mass_mailing_custom_unsubscribe_event/readme/USAGE.rst new file mode 100644 index 000000000..552d294ec --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/readme/USAGE.rst @@ -0,0 +1,8 @@ +#. Go to *Email Marketing > Mailings > Create*. +#. Select "Event Registration" in *Recipients* field. +#. Edit your mass mailing at wish, but remember to add a snippet from + *Footers*, so people have an *Unsubscribe* link. +#. Send it. +#. If somebody gets unsubscribed, it will get unsubscribed only for that + event, but including that mail in other event, the registree will still + receive mailings. diff --git a/mass_mailing_custom_unsubscribe_event/static/description/icon.png b/mass_mailing_custom_unsubscribe_event/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/mass_mailing_custom_unsubscribe_event/static/description/index.html b/mass_mailing_custom_unsubscribe_event/static/description/index.html new file mode 100644 index 000000000..66899cbe1 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/static/description/index.html @@ -0,0 +1,439 @@ + + + + + + +Allow to unsubscribe discretely from an event + + + +
    +

    Allow to unsubscribe discretely from an event

    + + +

    Beta License: AGPL-3 OCA/social Translate me on Weblate Try me on Runbot

    +

    This addon extends the unsubscription process for allowing to unsubscribe +only for an event.

    +

    Standard process includes the mail in the general blacklist instead, which +can be very unconvenient.

    +

    Table of contents

    + +
    +

    Usage

    +
      +
    1. Go to Email Marketing > Mailings > Create.
    2. +
    3. Select “Event Registration” in Recipients field.
    4. +
    5. Edit your mass mailing at wish, but remember to add a snippet from +Footers, so people have an Unsubscribe link.
    6. +
    7. Send it.
    8. +
    9. If somebody gets unsubscribed, it will get unsubscribed only for that +event, but including that mail in other event, the registree will still +receive mailings.
    10. +
    +
    +
    +

    Bug Tracker

    +

    Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

    +

    Do not contact contributors directly about support or help with technical issues.

    +
    +
    +

    Credits

    +
    +

    Authors

    +
      +
    • Tecnativa
    • +
    +
    +
    +

    Contributors

    + +
    +
    +

    Maintainers

    +

    This module is maintained by the OCA.

    +Odoo Community Association +

    OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

    +

    This module is part of the OCA/social project on GitHub.

    +

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    +
    +
    +
    + + diff --git a/mass_mailing_custom_unsubscribe_event/views/event_registration_views.xml b/mass_mailing_custom_unsubscribe_event/views/event_registration_views.xml new file mode 100644 index 000000000..e754a1d33 --- /dev/null +++ b/mass_mailing_custom_unsubscribe_event/views/event_registration_views.xml @@ -0,0 +1,18 @@ + + + + + + + event.registration.form - Add opt_out + event.registration + + + + + + + + +