diff --git a/mail_autogenerated_header/README.rst b/mail_autogenerated_header/README.rst index 7d27426fc5..c54a17c65e 100644 --- a/mail_autogenerated_header/README.rst +++ b/mail_autogenerated_header/README.rst @@ -17,22 +17,27 @@ Autogenerated headers :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/mail_autogenerated_header + :target: https://github.com/OCA/social/tree/17.0/mail_autogenerated_header :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-mail_autogenerated_header + :target: https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_autogenerated_header :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/social&target_branch=12.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=17.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -This module was written to mark Odoo's emails as being autogenerated according to `RFC 3834 `_, section 5. This allows receiving mail servers to act accordingly by for example not sending a vacation autoreply. +This module was written to mark Odoo's emails as being autogenerated +according to `RFC 3834 `__, section +5. This allows receiving mail servers to act accordingly by for example +not sending a vacation autoreply. -On the receiving side, this module drops all notifications for autogenerated incoming e-mails. +On the receiving side, this module drops all notifications for +autogenerated incoming e-mails. -The combination of both avoids possible mail loops with misconfigured or broken email servers on the opposite side. +The combination of both avoids possible mail loops with misconfigured or +broken email servers on the opposite side. **Table of contents** @@ -43,10 +48,10 @@ Usage ===== There's nothing the user has to do. Developers can set the context flag -``mail_autogenerated_header_disable`` in calls to ``send_email`` in order to -suppress adding any headers at all, and override -``_message_route_process_autoreply`` to fine tune dropping autogenerated mails -per model. +``mail_autogenerated_header_disable`` in calls to ``send_email`` in +order to suppress adding any headers at all, and override +``_message_route_process_autoreply`` to fine tune dropping autogenerated +mails per model. Bug Tracker =========== @@ -54,7 +59,7 @@ 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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -62,18 +67,19 @@ Credits ======= Authors -~~~~~~~ +------- * Hunki Enterprises BV * Therp BV Contributors -~~~~~~~~~~~~ +------------ -* Holger Brunn (https://hunki-enterprises.com) +- Holger Brunn + (https://hunki-enterprises.com) Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -85,6 +91,6 @@ 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. +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/mail_autogenerated_header/__manifest__.py b/mail_autogenerated_header/__manifest__.py index 69b104fc6c..2cbce4df12 100644 --- a/mail_autogenerated_header/__manifest__.py +++ b/mail_autogenerated_header/__manifest__.py @@ -10,6 +10,6 @@ "category": "Tools", "summary": "Add headers to Odoo's mails indicating they are autogenerated", "depends": [ - 'mail', + "mail", ], } diff --git a/mail_autogenerated_header/models/ir_mail_server.py b/mail_autogenerated_header/models/ir_mail_server.py index badde44085..af99da88be 100644 --- a/mail_autogenerated_header/models/ir_mail_server.py +++ b/mail_autogenerated_header/models/ir_mail_server.py @@ -5,51 +5,77 @@ class IrMailServer(models.Model): - _inherit = 'ir.mail_server' + _inherit = "ir.mail_server" @api.model def send_email( - self, message, mail_server_id=None, smtp_server=None, smtp_port=None, - smtp_user=None, smtp_password=None, smtp_encryption=None, - smtp_debug=False, smtp_session=None, + self, + message, + mail_server_id=None, + smtp_server=None, + smtp_port=None, + smtp_user=None, + smtp_password=None, + smtp_encryption=None, + smtp_debug=False, + smtp_session=None, ): - """ Inject autogenerated header for autogoing mails """ + """Inject autogenerated header for autogoing mails""" - if not self.env.context.get('mail_autogenerated_header_disable') and\ - self._send_email_set_autogenerated( - message, mail_server_id=mail_server_id, - smtp_server=smtp_server, smtp_port=smtp_port, - smtp_user=smtp_user, smtp_password=smtp_password, - smtp_encryption=smtp_encryption, smtp_debug=smtp_debug, - smtp_session=smtp_session, - ): + if not self.env.context.get( + "mail_autogenerated_header_disable" + ) and self._send_email_set_autogenerated( + message, + mail_server_id=mail_server_id, + smtp_server=smtp_server, + smtp_port=smtp_port, + smtp_user=smtp_user, + smtp_password=smtp_password, + smtp_encryption=smtp_encryption, + smtp_debug=smtp_debug, + smtp_session=smtp_session, + ): # MS Exchange's broken version as of # http://blogs.technet.com/b/exchange/archive/2006/10/06/ # 3395024.aspx - message['Precedence'] = 'bulk' - message['X-Auto-Response-Suppress'] = 'OOF' + message["Precedence"] = "bulk" + message["X-Auto-Response-Suppress"] = "OOF" # The right way to do it as of # https://tools.ietf.org/html/rfc3834 - message['Auto-Submitted'] = 'auto-generated' + message["Auto-Submitted"] = "auto-generated" return super(IrMailServer, self).send_email( - message, mail_server_id=mail_server_id, smtp_server=smtp_server, - smtp_port=smtp_port, smtp_user=smtp_user, - smtp_password=smtp_password, smtp_encryption=smtp_encryption, - smtp_debug=smtp_debug, smtp_session=smtp_session, + message, + mail_server_id=mail_server_id, + smtp_server=smtp_server, + smtp_port=smtp_port, + smtp_user=smtp_user, + smtp_password=smtp_password, + smtp_encryption=smtp_encryption, + smtp_debug=smtp_debug, + smtp_session=smtp_session, ) @api.model def _send_email_set_autogenerated( - self, message, mail_server_id=None, smtp_server=None, smtp_port=None, - smtp_user=None, smtp_password=None, smtp_encryption=None, - smtp_debug=False, smtp_session=None, + self, + message, + mail_server_id=None, + smtp_server=None, + smtp_port=None, + smtp_user=None, + smtp_password=None, + smtp_encryption=None, + smtp_debug=False, + smtp_session=None, ): """Determine if some mail should have the autogenerated headers""" - mail = self.env['mail.mail'].search([ - ('message_id', '=', message['Message-Id']), - ]) + mail = self.env["mail.mail"].search( + [ + ("message_id", "=", message["Message-Id"]), + ] + ) if not mail: return False - return mail.subtype_id != self.env.ref('mail.mt_comment') + return mail.subtype_id != self.env.ref("mail.mt_comment") diff --git a/mail_autogenerated_header/models/mail_thread.py b/mail_autogenerated_header/models/mail_thread.py index 0fc5c6a873..063ca410db 100644 --- a/mail_autogenerated_header/models/mail_thread.py +++ b/mail_autogenerated_header/models/mail_thread.py @@ -2,33 +2,39 @@ # Copyright 2022 Hunki Enterprises BV # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). import logging + from odoo import api, models + _logger = logging.getLogger(__name__) class MailThread(models.AbstractModel): - _inherit = 'mail.thread' + _inherit = "mail.thread" @api.model def message_route_process(self, message, message_dict, routes): - """ Set context key to suppress notification for autogenerated incoming - mails """ + """Set context key to suppress notification for autogenerated incoming + mails""" if self._message_route_process_autoreply(message, message_dict, routes): _logger.info( - 'Ignoring email %s from %s because it seems to be an auto ' - 'reply', message.get('Message-ID'), message.get('From'), + "Ignoring email %s from %s because it seems to be an auto " "reply", + message.get("Message-ID"), + message.get("From"), ) self = self.with_context(mail_autogenerated_header=message) return super(MailThread, self).message_route_process( - message, message_dict, routes, + message, + message_dict, + routes, ) @api.model def _message_route_process_autoreply(self, message, message_dict, routes): - """ Determine if some message is an autoreply """ + """Determine if some message is an autoreply""" return ( - message['Auto-Submitted'] and message['Auto-Submitted'] != 'no' or - message['X-Auto-Response-Suppress'] and set( - message['X-Auto-Response-Suppress'].split(', ') - ) & set('AutoReply', 'All') + message["Auto-Submitted"] + and message["Auto-Submitted"] != "no" + or message["X-Auto-Response-Suppress"] + and set(message["X-Auto-Response-Suppress"].split(", ")) + & set("AutoReply", "All") ) diff --git a/mail_autogenerated_header/models/res_partner.py b/mail_autogenerated_header/models/res_partner.py index ff276ca674..e905570f6f 100644 --- a/mail_autogenerated_header/models/res_partner.py +++ b/mail_autogenerated_header/models/res_partner.py @@ -4,20 +4,28 @@ class ResPartner(models.Model): - _inherit = 'res.partner' + _inherit = "res.partner" @api.model def _notify( - self, message, rdata, record, force_send=False, - send_after_commit=True, model_description=False, - mail_auto_delete=True, + self, + message, + rdata, + record, + force_send=False, + send_after_commit=True, + model_description=False, + mail_auto_delete=True, ): - """ Inhibit notifications if this is the notification for an incoming - autogenerated mail from another system """ - if self.env.context.get('mail_autogenerated_header'): + """Inhibit notifications if this is the notification for an incoming + autogenerated mail from another system""" + if self.env.context.get("mail_autogenerated_header"): return True return super()._notify( - message, rdata, record, force_send=force_send, + message, + rdata, + record, + force_send=force_send, send_after_commit=send_after_commit, model_description=model_description, mail_auto_delete=mail_auto_delete, diff --git a/mail_autogenerated_header/pyproject.toml b/mail_autogenerated_header/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/mail_autogenerated_header/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mail_autogenerated_header/readme/CONTRIBUTORS.md b/mail_autogenerated_header/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..577341c321 --- /dev/null +++ b/mail_autogenerated_header/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Holger Brunn \<\> + () diff --git a/mail_autogenerated_header/readme/CONTRIBUTORS.rst b/mail_autogenerated_header/readme/CONTRIBUTORS.rst deleted file mode 100644 index 33b6eb2c3f..0000000000 --- a/mail_autogenerated_header/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1 +0,0 @@ -* Holger Brunn (https://hunki-enterprises.com) diff --git a/mail_autogenerated_header/readme/DESCRIPTION.md b/mail_autogenerated_header/readme/DESCRIPTION.md new file mode 100644 index 0000000000..3e17a4d4f9 --- /dev/null +++ b/mail_autogenerated_header/readme/DESCRIPTION.md @@ -0,0 +1,10 @@ +This module was written to mark Odoo's emails as being autogenerated +according to [RFC 3834](https://tools.ietf.org/html/rfc3834), section 5. +This allows receiving mail servers to act accordingly by for example not +sending a vacation autoreply. + +On the receiving side, this module drops all notifications for +autogenerated incoming e-mails. + +The combination of both avoids possible mail loops with misconfigured or +broken email servers on the opposite side. diff --git a/mail_autogenerated_header/readme/DESCRIPTION.rst b/mail_autogenerated_header/readme/DESCRIPTION.rst deleted file mode 100644 index bda994624c..0000000000 --- a/mail_autogenerated_header/readme/DESCRIPTION.rst +++ /dev/null @@ -1,5 +0,0 @@ -This module was written to mark Odoo's emails as being autogenerated according to `RFC 3834 `_, section 5. This allows receiving mail servers to act accordingly by for example not sending a vacation autoreply. - -On the receiving side, this module drops all notifications for autogenerated incoming e-mails. - -The combination of both avoids possible mail loops with misconfigured or broken email servers on the opposite side. diff --git a/mail_autogenerated_header/readme/USAGE.md b/mail_autogenerated_header/readme/USAGE.md new file mode 100644 index 0000000000..34380206c6 --- /dev/null +++ b/mail_autogenerated_header/readme/USAGE.md @@ -0,0 +1,5 @@ +There's nothing the user has to do. Developers can set the context flag +`mail_autogenerated_header_disable` in calls to `send_email` in order to +suppress adding any headers at all, and override +`_message_route_process_autoreply` to fine tune dropping autogenerated +mails per model. diff --git a/mail_autogenerated_header/readme/USAGE.rst b/mail_autogenerated_header/readme/USAGE.rst deleted file mode 100644 index 8412aba96f..0000000000 --- a/mail_autogenerated_header/readme/USAGE.rst +++ /dev/null @@ -1,5 +0,0 @@ -There's nothing the user has to do. Developers can set the context flag -``mail_autogenerated_header_disable`` in calls to ``send_email`` in order to -suppress adding any headers at all, and override -``_message_route_process_autoreply`` to fine tune dropping autogenerated mails -per model. diff --git a/mail_autogenerated_header/static/description/index.html b/mail_autogenerated_header/static/description/index.html index 0ae3091627..f8dd3b852b 100644 --- a/mail_autogenerated_header/static/description/index.html +++ b/mail_autogenerated_header/static/description/index.html @@ -1,4 +1,3 @@ - @@ -9,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -369,10 +369,15 @@

Autogenerated headers

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:c85cef2766e4f4e18f525f38d82ccee67b9e934eee4ca3cccd9ae68783d11a26 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

-

This module was written to mark Odoo’s emails as being autogenerated according to RFC 3834, section 5. This allows receiving mail servers to act accordingly by for example not sending a vacation autoreply.

-

On the receiving side, this module drops all notifications for autogenerated incoming e-mails.

-

The combination of both avoids possible mail loops with misconfigured or broken email servers on the opposite side.

+

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

+

This module was written to mark Odoo’s emails as being autogenerated +according to RFC 3834, section +5. This allows receiving mail servers to act accordingly by for example +not sending a vacation autoreply.

+

On the receiving side, this module drops all notifications for +autogenerated incoming e-mails.

+

The combination of both avoids possible mail loops with misconfigured or +broken email servers on the opposite side.

Table of contents

    @@ -389,17 +394,17 @@

    Autogenerated headers

    Usage

    There’s nothing the user has to do. Developers can set the context flag -mail_autogenerated_header_disable in calls to send_email in order to -suppress adding any headers at all, and override -_message_route_process_autoreply to fine tune dropping autogenerated mails -per model.

    +mail_autogenerated_header_disable in calls to send_email in +order to suppress adding any headers at all, and override +_message_route_process_autoreply to fine tune dropping autogenerated +mails per model.

    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 to smash it by providing a detailed and welcomed -feedback.

    +feedback.

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

    @@ -414,17 +419,20 @@

    Authors

    Maintainers

    This module is maintained by the OCA.

    -Odoo Community Association + +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.

    +

    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/mail_autogenerated_header/tests/test_mail_autogenerated_header.py b/mail_autogenerated_header/tests/test_mail_autogenerated_header.py index 5754e87d73..f97b15468a 100644 --- a/mail_autogenerated_header/tests/test_mail_autogenerated_header.py +++ b/mail_autogenerated_header/tests/test_mail_autogenerated_header.py @@ -8,56 +8,65 @@ class TestMailAutogeneratedHeader(TransactionCase): def setUp(self): super().setUp() - self.mail = self.env['mail.mail'].create({ - 'subject': 'testmessage', - 'email_from': 'test@test.com', - 'email_to': 'test@test.com', - 'message_id': 'message_id', - }) - self.message = self.env['ir.mail_server'].build_email( - [self.mail.email_from], [self.mail.email_to], self.mail.subject, '', + self.mail = self.env["mail.mail"].create( + { + "subject": "testmessage", + "email_from": "test@test.com", + "email_to": "test@test.com", + "message_id": "message_id", + } + ) + self.message = self.env["ir.mail_server"].build_email( + [self.mail.email_from], + [self.mail.email_to], + self.mail.subject, + "", message_id=self.mail.message_id, ) def test_sending(self): - """ Test that sending a mail has the Auto-Submitted header """ - self.env['ir.mail_server'].send_email(self.message) - self.assertEqual(self.message['Auto-Submitted'], 'auto-generated') + """Test that sending a mail has the Auto-Submitted header""" + self.env["ir.mail_server"].send_email(self.message) + self.assertEqual(self.message["Auto-Submitted"], "auto-generated") def test_receiving(self): - """ Test that receiving mails with some auto submitted marker won't - cause new notifications being sent """ - demo_user = self.env.ref('base.user_demo') + """Test that receiving mails with some auto submitted marker won't + cause new notifications being sent""" + demo_user = self.env.ref("base.user_demo") self.message.replace_header( - 'Message-Id', generate_tracking_message_id(42), + "Message-Id", + generate_tracking_message_id(42), ) - partner_id = self.env['mail.thread'].message_process( - 'res.partner', self.message.as_string(), + partner_id = self.env["mail.thread"].message_process( + "res.partner", + self.message.as_string(), ) - partner = self.env['res.partner'].browse(partner_id) + partner = self.env["res.partner"].browse(partner_id) partner.message_subscribe(partner_ids=demo_user.partner_id.ids) reply = self.message - reply['References'] = self.message['Message-Id'] - reply.replace_header('Message-Id', 'message_id3') - thread_id = self.env['mail.thread'].message_process( - 'res.partner', reply.as_string(), + reply["References"] = self.message["Message-Id"] + reply.replace_header("Message-Id", "message_id3") + thread_id = self.env["mail.thread"].message_process( + "res.partner", + reply.as_string(), ) self.assertEqual(thread_id, partner.id) - notifications = self.env['mail.notification'].search([ - ('res_partner_id', '=', demo_user.partner_id.id) - ]) + notifications = self.env["mail.notification"].search( + [("res_partner_id", "=", demo_user.partner_id.id)] + ) # mail is not autogenerated, should have generated mails self.assertTrue(notifications.is_email) notifications.unlink() - reply.replace_header('Message-Id', 'message_id4') - reply['Auto-Submitted'] = 'auto-generated' - thread_id = self.env['mail.thread'].message_process( - 'res.partner', reply.as_string(), + reply.replace_header("Message-Id", "message_id4") + reply["Auto-Submitted"] = "auto-generated" + thread_id = self.env["mail.thread"].message_process( + "res.partner", + reply.as_string(), ) self.assertEqual(thread_id, partner.id) - notifications = self.env['mail.notification'].search([ - ('res_partner_id', '=', demo_user.partner_id.id) - ]) + notifications = self.env["mail.notification"].search( + [("res_partner_id", "=", demo_user.partner_id.id)] + ) # mail is autogenerated, shouldn't have generated mails self.assertFalse(notifications.is_email)