[19.0] mail_composer_cc_bcc: Migration to 19.0 - #104
Conversation
…ents when no cc or bcc
Currently translated at 83.3% (15 of 18 strings) Translation: social-16.0/social-16.0-mail_composer_cc_bcc Translate-URL: https://translation.odoo-community.org/projects/social-16-0/social-16-0-mail_composer_cc_bcc/es/
Currently translated at 100.0% (18 of 18 strings) Translation: social-16.0/social-16.0-mail_composer_cc_bcc Translate-URL: https://translation.odoo-community.org/projects/social-16-0/social-16-0-mail_composer_cc_bcc/es/
Currently translated at 100.0% (18 of 18 strings) Translation: social-16.0/social-16.0-mail_composer_cc_bcc Translate-URL: https://translation.odoo-community.org/projects/social-16-0/social-16-0-mail_composer_cc_bcc/it/
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: social-17.0/social-17.0-mail_composer_cc_bcc Translate-URL: https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_composer_cc_bcc/
Currently translated at 100.0% (17 of 17 strings) Translation: social-17.0/social-17.0-mail_composer_cc_bcc Translate-URL: https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_composer_cc_bcc/it/
…onstraint "unique_mail_message_id_res_partner_id_if_set" when adding the same user to CC field that is already set as a follower
### This changes 1. Refactor _generate_template_recipients 2. Fix invalid-email-address for Bcc - In standard, Bcc key in dict message was stripped in https://github.com/odoo/odoo/blob/4394940a09900aa5b42cbc05355880598608d1b6/odoo/addons/base/models/ir_mail_server.py#L676 - Duplicate the key to retain for later assertion
c0cbcf5 to
60c3aa7
Compare
b2a4020 to
3877021
Compare
|
@etobella Can you please merge? |
|
LGTM |
|
When merge? any ETA? thx |
|
/ocabot migration mail_composer_cc_bcc |
| class IrMailServer(models.Model): | ||
| _inherit = "ir.mail_server" | ||
|
|
||
| def _prepare_email_message(self, message, smtp_session): |
There was a problem hiding this comment.
Method was renamed: odoo/odoo@e147c778ebbd0#diff-e46e2629963b0ad64aed7a7b02f49caea5bfacd952b77abcb2954f2437c9222aL668-R646. This implies a missing test.
|
When merge? |
|
@giusybloomup When the code is fixed |
NICO-SOLUTIONS
left a comment
There was a problem hiding this comment.
Reviewing prepare_email_message_ override and updated hash
| class IrMailServer(models.Model): | ||
| _inherit = "ir.mail_server" | ||
|
|
||
| def _prepare_email_message(self, message, smtp_session): |
There was a problem hiding this comment.
| def _prepare_email_message(self, message, smtp_session): | |
| def _prepare_email_message__(self, message, smtp_session): |
There was a problem hiding this comment.
An extra double underscore was added to the method
| ) | ||
|
|
||
| VALID_HASHES = { | ||
| "mail.composer:_compute_partner_ids": ["4e49f0d6c53f41ac24b02176e97b600a"], |
There was a problem hiding this comment.
| "mail.composer:_compute_partner_ids": ["4e49f0d6c53f41ac24b02176e97b600a"], | |
| "mail.composer:_compute_partner_ids": ["c3903ab78bf2e5d9aba078ac2689d974"], |
There was a problem hiding this comment.
Updated hash to match the current upstream _compute_partner_ids
| if x_odoo_bcc_value: | ||
| message["Bcc"] = x_odoo_bcc_value | ||
|
|
||
| smtp_from, smtp_to_list, message = super()._prepare_email_message( |
There was a problem hiding this comment.
| smtp_from, smtp_to_list, message = super()._prepare_email_message( | |
| smtp_from, smtp_to_list, message = super()._prepare_email_message__( |
There was a problem hiding this comment.
Call updated prepare_email_message_ method with extra double underscore
There was a problem hiding this comment.
Hi,
Bcc mails doesn't works, even after renaming this method.
There was a problem hiding this comment.
Could you be a bit more specific? Please describe what happens, what you expected, and what you’ve already tried.
There was a problem hiding this comment.
Sorry, it seems to be working, but it's sending multiple emails.
There are three identicals emails sent to acme_corp and brandon freeman, but not colleen diaz

Furthermore, the X-Odoo-Bcc header should be removed before sending. Recipients should not be able to identify hidden recipients simply by reading the header.

See odoo/odoo@2445f9e
There was a problem hiding this comment.
@Linekio
I just quickly looked over the code again, and I think you are raising a valid concern.
The X-Odoo-Bcc handling seems questionable: the code reintroduces the value as a Bcc email header (message["Bcc"] = x_odoo_bcc_value) before sending. This looks like it could reintroduce the BCC leak that was fixed in Odoo core.
The smtp_to_list = [smtp_to] handling also looks suspicious. Combined with mutating recipients via pop(0), this could be related to the reported duplicate emails.
@cyrilmanuel
Could you please have another look at this part? It seems the implementation may need another pass to align with Odoo's current BCC handling (BCC should remain only part of the SMTP recipient list and should not be exposed in the outgoing message headers).
|
@Borruso if this looks good to you, then you weren't looking very closely |
skanndar
left a comment
There was a problem hiding this comment.
I tested this branch on a clean 19.0 database and the Bcc feature does not work at all: the Bcc recipients never receive the email. Reproduction and root cause below — sorry for the late review, and thanks for keeping this module alive.
Setup: official odoo:19 image (build 19.0.20260723), fresh database, only this module installed. The SMTP session is replaced by a stub recording exactly what Odoo hands to the server (send_message(message, smtp_from, smtp_to_list)), so the envelope and the headers below are the real ones.
Scenario: composer on a record, To = to@example.com, Cc = cc1@example.com, Bcc = bcc1@example.com + bcc2@example.com.
Result: 3 emails handed to the server, with envelopes [cc1@], [to@], [cc1@]. Neither Bcc address ever appears in an envelope, and cc1@ gets two copies.
1. The ir.mail_server override never runs on 19.0. It defines _prepare_email_message, but 19.0 renamed that method to _prepare_email_message__ (odoo/addons/base/models/ir_mail_server.py). Nothing calls the old name any more, so neither the X-Odoo-Bcc → Bcc translation nor the context['recipients'] envelope restriction ever happen. Without a Bcc header, _prepare_smtp_to_list() — which builds the envelope from To/Cc/Bcc — simply never yields the Bcc addresses, hence the silent loss.
On 19.0 the envelope is already restricted by the send_validated_to context key that MailMail._send() fills with the normalized recipient of each email, so the override can be dropped in favour of setting a real Bcc header on the Bcc recipient's own email only. _alter_message__() strips that header right after building the envelope, so it is never transmitted.
2. The headers dict is shared by every email of the batch. In _prepare_outgoing_list(), m["headers"].update({"X-Odoo-Bcc": ...}) mutates the same dict instance that all the other emails received, so after the loop every email carries the last Bcc address. In my run all four prepared emails ended up with X-Odoo-Bcc: "B2" <bcc2@example.com>. Copying instead of mutating fixes it:
m["headers"] = {**m["headers"], "Bcc": m["email_to"][0]}3. X-Msg-To-Add (new in 19.0) puts the Cc and Bcc addresses into the To header, once delivery works. MailThread._notify_by_email_get_headers() adds every external recipient to X-Msg-To-Add, and IrMailServer._alter_message__() merges that header into To at send time to enable Reply-All. It does not show up on this branch because the Bcc emails are never sent — but as soon as point 1 is fixed it does. I verified it A/B on a fixed version: dropping the header, each email carries the intended To/Cc; keeping it, every recipient (including the plain To one) receives To: to@…, cc1@…, bcc1@…, bcc2@…. Since this module builds the whole To/Cc itself, dropping it in _prepare_outgoing_list() looks like the right call:
headers = {k: v for k, v in m["headers"].items() if k != "X-Msg-To-Add"}A related detail: when mail.email_to is empty Odoo builds an extra Cc-only email, which is a duplicate here (this is what #233 addresses on 18.0) — that is where the second copy to cc1@ comes from.
Points 1 and 2 apply to #163 and #189 as well, since all three migrations carry the same code.
I have a 19.0 version with the three fixes and tests covering them running on a real database. Happy to push it here as commits, or to open it wherever you prefer — whatever helps this land.
|
@skanndar |
|
Thanks @NICO-SOLUTIONS — pushed: camptocamp#2, against the branch of this PR. It is built on top of @Borruso's camptocamp#1 (his commit is included unchanged: renaming the override to
Plus two tests that fail before and pass after, and the existing suite green. The reproduction is the same setup as my review: official Happy to rebase onto this branch alone if you prefer #1 to be merged separately first. |


No description provided.