diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py index 7ee9d69087..55e2085a3d 100644 --- a/addons/hr_timesheet/models/hr_timesheet.py +++ b/addons/hr_timesheet/models/hr_timesheet.py @@ -170,13 +170,23 @@ class AccountAnalyticLine(models.Model): if self.env.user.has_group('hr_timesheet.group_hr_timesheet_user'): # Then, he is internal user, and we take the domain for this current user return self.env['ir.rule']._compute_domain(self._name) - return ['&', + return [ + '|', + '&', '|', '|', '|', - ('task_id.project_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id]), - ('task_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id]), - ('task_id.project_id.allowed_portal_user_ids', 'child_of', [self.env.user.id]), - ('task_id.allowed_user_ids', 'in', [self.env.user.id]), - ('task_id.project_id.privacy_visibility', '=', 'portal')] + ('task_id.project_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id]), + ('task_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id]), + ('task_id.project_id.allowed_portal_user_ids', 'child_of', [self.env.user.id]), + ('task_id.allowed_user_ids', 'in', [self.env.user.id]), + ('task_id.project_id.privacy_visibility', '=', 'portal'), + '&', + ('task_id', '=', False), + '&', + '|', + ('project_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id]), + ('project_id.allowed_portal_user_ids', 'child_of', [self.env.user.id]), + ('project_id.privacy_visibility', '=', 'portal') + ] def _timesheet_preprocess(self, vals): """ Deduce other field values from the one given. diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 3dd195b7ed..5cb7d3939a 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1288,25 +1288,27 @@ class MailThread(models.AbstractModel): filename = part.get_filename() # I may not properly handle all charsets encoding = part.get_content_charset() # None if attachment + content = part.get_content() + info = {'encoding': encoding} # 0) Inline Attachments -> attachments, with a third part in the tuple to match cid / attachment if filename and part.get('content-id'): - inner_cid = part.get('content-id').strip('><') - attachments.append(self._Attachment(filename, part.get_content(), {'cid': inner_cid})) + info['cid'] = part.get('content-id').strip('><') + attachments.append(self._Attachment(filename, content, info)) continue # 1) Explicit Attachments -> attachments if filename or part.get('content-disposition', '').strip().startswith('attachment'): - attachments.append(self._Attachment(filename or 'attachment', part.get_content(), {})) + attachments.append(self._Attachment(filename or 'attachment', content, info)) continue # 2) text/plain ->
if part.get_content_type() == 'text/plain' and (not alternative or not body): - body = tools.append_content_to_html(body, tools.ustr(part.get_content(), + body = tools.append_content_to_html(body, tools.ustr(content, encoding, errors='replace'), preserve=True) # 3) text/html -> raw elif part.get_content_type() == 'text/html': # mutlipart/alternative have one text and a html part, keep only the second # mixed allows several html parts, append html content append_content = not alternative or (html and mixed) - html = tools.ustr(part.get_content(), encoding, errors='replace') + html = tools.ustr(content, encoding, errors='replace') if not append_content: body = html else: @@ -1315,7 +1317,7 @@ class MailThread(models.AbstractModel): body = tools.html_sanitize(body, sanitize_tags=False, strip_classes=True) # 4) Anything else -> attachment else: - attachments.append(self._Attachment(filename or 'attachment', part.get_content(), {})) + attachments.append(self._Attachment(filename or 'attachment', content, info)) return self._message_parse_extract_payload_postprocess(message, {'body': body, 'attachments': attachments}) @@ -1735,13 +1737,15 @@ class MailThread(models.AbstractModel): cid = False if len(attachment) == 2: name, content = attachment + info = {} elif len(attachment) == 3: name, content, info = attachment cid = info and info.get('cid') else: continue if isinstance(content, str): - content = content.encode('utf-8') + encoding = info and info.get('encoding') + content = content.encode(encoding or 'utf-8') elif isinstance(content, EmailMessage): content = content.as_bytes() elif content is None: diff --git a/addons/test_mail/data/test_mail_data.py b/addons/test_mail/data/test_mail_data.py index 221c86953f..0e8a882e8e 100644 --- a/addons/test_mail/data/test_mail_data.py +++ b/addons/test_mail/data/test_mail_data.py @@ -214,6 +214,39 @@ Content-Type: text/html; --Apple-Mail=_9331E12B-8BD2-4EC7-B53E-01F3FBEC9227-- """ +MAIL_FILE_ENCODING = """MIME-Version: 1.0 +Date: Sun, 26 Mar 2023 05:23:22 +0200 +Message-ID: {msg_id} +Subject: {subject} +From: "Sylvie Lelitre"