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 000000000..3a0328b51 Binary files /dev/null and b/mass_mailing_custom_unsubscribe_event/static/description/icon.png differ 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 + + + + + + + + +