Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions mail_restrict_access_button/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
===========================
Mail Restrict Access Button
===========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:df4530293527760b0a34870365e162d80fa49666e0fe945235bda915f8937888
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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%2Fmail-lightgray.png?logo=github
:target: https://github.com/OCA/mail/tree/18.0/mail_restrict_access_button
:alt: OCA/mail
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_restrict_access_button
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/mail&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

Odoo notification emails sent to non-internal recipients can include an
access button, granting access to the Odoo instance and the related
document without logging in.

This module restricts that access button so it is only shown to
recipients who have a user account (internal users or portal users) and
never to unregistered external partners. These external recipients will
still receive the email, but the button will be removed.

This logic applies dynamically across all recipient groups, including
mixed ones (portal_customer) that contain both types of contacts.

A registered recipient in a mixed group keeps the button (and the
group), while an unregistered one in that same context is automatically
moved to the next buttonless group or the fallback group (buttonless
too).

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/mail/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/mail/issues/new?body=module:%20mail_restrict_access_button%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
-------

* ForgeFlow

Contributors
------------

- Laura Cazorla <<laura.cazorla@forgeflow.com>>

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/mail <https://github.com/OCA/mail/tree/18.0/mail_restrict_access_button>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions mail_restrict_access_button/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
15 changes: 15 additions & 0 deletions mail_restrict_access_button/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2026 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Mail Restrict Access Button",
"version": "18.0.1.0.0",
"category": "Discuss",
"license": "AGPL-3",
"summary": "Show the notification access button only to recipients with "
"a user account (internal or portal), never to unregistered partners.",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/mail",
"depends": ["mail"],
"installable": True,
}
1 change: 1 addition & 0 deletions mail_restrict_access_button/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import mail_thread
39 changes: 39 additions & 0 deletions mail_restrict_access_button/models/mail_thread.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2026 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import models


class MailThread(models.AbstractModel):
_inherit = "mail.thread"

def _notify_get_recipients_groups_fillup(
self, groups, model_description, msg_vals=None
):
groups = groups + [
[
"unregistered_external",
lambda recipient: recipient["type"] == "customer",
{"has_button_access": False},
]
]
groups = super()._notify_get_recipients_groups_fillup(
groups, model_description, msg_vals=msg_vals
)
for index, (name, matches_recipient, group_data) in enumerate(groups):
if group_data.get("has_button_access") and group_data.get("active"):
groups[index] = [
name,
self._without_unregistered(matches_recipient),
group_data,
]
return groups

@staticmethod
def _without_unregistered(matches_recipient):
# Wrap a group's matching conditions so it never matches unregistered
# external partners (without user account)
def predicate(recipient):
return matches_recipient(recipient) and recipient["type"] != "customer"

return predicate
3 changes: 3 additions & 0 deletions mail_restrict_access_button/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
1 change: 1 addition & 0 deletions mail_restrict_access_button/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Laura Cazorla \<\<<laura.cazorla@forgeflow.com>\>\>
16 changes: 16 additions & 0 deletions mail_restrict_access_button/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Odoo notification emails sent to non-internal recipients can include an
access button, granting access to the Odoo instance and the related
document without logging in.

This module restricts that access button so it is only shown to
recipients who have a user account (internal users or portal users) and
never to unregistered external partners. These external recipients will
still receive the email, but the button will be removed.

This logic applies dynamically across all recipient groups, including
mixed ones (portal_customer) that contain both types of contacts.

A registered recipient in a mixed group keeps the button (and the
group), while an unregistered one in that same context is automatically
moved to the next buttonless group or the fallback group (buttonless
too).
Loading
Loading