From 7d3a8f5f909ad7e3eb17070c6517dd7976873142 Mon Sep 17 00:00:00 2001 From: Lik - Alwinen Date: Sat, 21 Dec 2024 04:06:06 +0100 Subject: [PATCH] [FIX] mail_send_copy: work with existing BCC+adding tests [FIX] mail_send_copy: work with existing BCC+adding tests2 [IMP] improve code for OCA convention [IMP] mail_send_copy: add test for sending email with bcc --- mail_send_copy/models/ir_mail_server.py | 21 +++- mail_send_copy/static/description/index.html | 12 ++- mail_send_copy/tests/__init__.py | 1 + mail_send_copy/tests/test_mail_send_copy.py | 105 +++++++++++++++++++ 4 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 mail_send_copy/tests/__init__.py create mode 100644 mail_send_copy/tests/test_mail_send_copy.py diff --git a/mail_send_copy/models/ir_mail_server.py b/mail_send_copy/models/ir_mail_server.py index 3ae8cee11c..358e104567 100644 --- a/mail_send_copy/models/ir_mail_server.py +++ b/mail_send_copy/models/ir_mail_server.py @@ -2,10 +2,13 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging from email.utils import COMMASPACE from odoo import api, models +_logger = logging.getLogger(__name__) + class IrMailServer(models.Model): _inherit = "ir.mail_server" @@ -14,8 +17,20 @@ class IrMailServer(models.Model): def send_email(self, message, *args, **kwargs): do_not_send_copy = self.env.context.get("do_not_send_copy", False) if not do_not_send_copy: - if message["Bcc"]: - message["Bcc"] = message["Bcc"].join(COMMASPACE, message["From"]) + # Get existing Bcc recipients (if any) + bcc = message.get("Bcc", "") + from_addr = message.get("From", "") + + # Combine existing Bcc with From address + if bcc: + all_bcc = COMMASPACE.join([bcc, from_addr]) else: - message["Bcc"] = message["From"] + all_bcc = from_addr + + # Set the combined Bcc + if "Bcc" in message: + message.replace_header("Bcc", all_bcc) + else: + message.add_header("Bcc", all_bcc) + return super().send_email(message, *args, **kwargs) diff --git a/mail_send_copy/static/description/index.html b/mail_send_copy/static/description/index.html index 80be32a541..0f89009b0d 100644 --- a/mail_send_copy/static/description/index.html +++ b/mail_send_copy/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 { @@ -431,7 +431,9 @@

Contributors

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.

diff --git a/mail_send_copy/tests/__init__.py b/mail_send_copy/tests/__init__.py new file mode 100644 index 0000000000..9780ffc8ba --- /dev/null +++ b/mail_send_copy/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mail_send_copy diff --git a/mail_send_copy/tests/test_mail_send_copy.py b/mail_send_copy/tests/test_mail_send_copy.py new file mode 100644 index 0000000000..37cfad62e3 --- /dev/null +++ b/mail_send_copy/tests/test_mail_send_copy.py @@ -0,0 +1,105 @@ +# Copyright from 2024: Alwinen GmbH (https://www.alwinen.de) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +# TODO: find a way to test sending email with existing BCC + +from unittest.mock import patch + +from odoo.tests import tagged + +from odoo.addons.mail.tests.test_mail_composer import TestMailComposer + + +class TestMailSendCopy(TestMailComposer): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context={"testing": True}) + + # Create test partner + cls.partner = cls.env["res.partner"].create( + { + "name": "Test Partner", + "email": "test@example.com", + } + ) + + def test_send_email_with_copy(self): + """Test that sender is added to BCC when sending email""" + composer = self.env["mail.compose.message"].create( + { + "partner_ids": [(6, 0, [self.partner.id])], + "subject": "Test Subject", + "body": "

Test Body

", + "email_from": "sender@example.com", + } + ) + + # Mock the send_email method + with patch( + "odoo.addons.base.models.ir_mail_server.IrMailServer.send_email" + ) as mock_send_email: + composer._action_send_mail() + # Verify that send_email was called + self.assertTrue(mock_send_email.called) + # Get the arguments passed to send_email + call_args = mock_send_email.call_args[0] + # The message is the first argument + message = call_args[0] + # Check BCC in the email message + self.assertIn("sender@example.com", message["Bcc"]) + + def test_send_email_without_copy(self): + """Test that sender is not added to BCC when do_not_send_copy is True""" + composer = ( + self.env["mail.compose.message"] + .with_context(do_not_send_copy=True) + .create( + { + "partner_ids": [(6, 0, [self.partner.id])], + "subject": "Test Subject No Copy", + "body": "

Test Body

", + "email_from": "sender@example.com", + } + ) + ) + + with patch( + "odoo.addons.base.models.ir_mail_server.IrMailServer.send_email" + ) as mock_send_email: + composer._action_send_mail() + self.assertTrue(mock_send_email.called) + message = mock_send_email.call_args[0][0] + self.assertNotIn("Bcc", message) + + +# Code contributed by @trisdoan +@tagged("post_install", "-at_install") +class TestMailSendWithBcc(TestMailSendCopy): + def test_send_email_with_existing_bcc(self): + if not self.env["ir.module.module"].search( + [("name", "=", "mail_composer_cc_bcc"), ("state", "=", "installed")] + ): + self.skipTest("mail_composer_cc_bcc module is required for this test") + + partner_bcc = self.env.ref("base.res_partner_main2") + composer = self.env["mail.compose.message"].create( + { + "partner_ids": [(6, 0, [self.partner.id])], + "subject": "Test Subject", + "body": "

Test Body

", + "email_from": "sender@example.com", + } + ) + composer.partner_bcc_ids = partner_bcc + + with patch( + "odoo.addons.base.models.ir_mail_server.IrMailServer.send_email" + ) as mock_send_email: + composer._action_send_mail() + # Verify that send_email was called + self.assertTrue(mock_send_email.called) + call_args = mock_send_email.call_args[0] + message = call_args[0] + # Check existing BCC in the email message + self.assertIn("dwayne.newman28@example.com", message["Bcc"])