From f4550d77238cc36dbcbc100116cc63df2b4a1750 Mon Sep 17 00:00:00 2001 From: xtremxpert Date: Tue, 28 Jan 2025 09:41:50 -0500 Subject: [PATCH] fix merge --- .../models/ir_attachment.py | 133 +++++++++++++++--- 1 file changed, 117 insertions(+), 16 deletions(-) diff --git a/msg_attachments_to_mail_message/models/ir_attachment.py b/msg_attachments_to_mail_message/models/ir_attachment.py index 5de8680..4b5242b 100644 --- a/msg_attachments_to_mail_message/models/ir_attachment.py +++ b/msg_attachments_to_mail_message/models/ir_attachment.py @@ -24,7 +24,12 @@ class IrAttachment(models.Model): mail_message_id = fields.Many2one("mail.message", string="Created Mail Message") def _is_msg_file(self): - """Check if the attachment is an MSG file and validate size.""" + """ + Check if the attachment is an MSG file and validate size. + + Returns: + bool: True if the attachment is an MSG file, False otherwise. + """ self.ensure_one() # Check if it's an MSG file @@ -56,14 +61,30 @@ class IrAttachment(models.Model): return True def _clean_header_value(self, value): - """Clean header value by removing line breaks and extra whitespace.""" + """ + Clean header value by removing line breaks and extra whitespace. + + Args: + value (str): Header value to clean. + + Returns: + str: Cleaned header value. + """ if not value: return "" # Replace any combination of whitespace (including newlines) with a single space return " ".join(str(value).split()) def _msg_to_eml(self, msg_data): - """Convert MSG file data to EML format.""" + """ + Convert MSG file data to EML format. + + Args: + msg_data (bytes): MSG file data. + + Returns: + str: EML file data. + """ try: # Read the MSG file msg_file = extract_msg.Message(msg_data) @@ -75,8 +96,78 @@ class IrAttachment(models.Model): ) # Create email message - email_msg = MIMEMultipart("related") + email_msg = MIMEMultipart('related') + + # Clean and normalize email addresses + from_email = email_normalize(msg_file.sender) if msg_file.sender else False + to_emails = email_split(msg_file.to) if msg_file.to else [] + cc_emails = email_split(msg_file.cc) if msg_file.cc else [] + + # Vérifier si les adresses existent dans les partenaires + partner_model = self.env['res.partner'] + from_partners = partner_model.search([('email', '=ilike', from_email)]) if from_email else False + + # Get current record's partner if exists + current_partner = False + if self.res_model and self.res_id: + record = self.env[self.res_model].browse(self.res_id) + if hasattr(record, 'partner_id'): + current_partner = record.partner_id + if not from_partners: + if current_partner and from_email: + # Create new contact under the parent company + company = current_partner.commercial_partner_id + # Extract name from email if possible + display_name = msg_file.sender + if '<' in display_name and '>' in display_name: + display_name = display_name.split('<')[0].strip() + + from_partner = partner_model.create({ + 'name': display_name, + 'email': from_email, + 'parent_id': company.id, + 'company_id': company.company_id.id if company.company_id else self.env.company.id, + 'type': 'contact', + }) + _logger.info('Created new contact %s under company %s for email %s', + display_name, company.name, from_email) + else: + _logger.warning('Email sender not found in partners and no current partner to link to: %s - Message ignored', from_email) + self._notify_error('Unknown Sender', + _('The message cannot be imported because the sender (%s) does not exist in partners and no company to link to') % from_email) + return False + elif len(from_partners) > 1: + if current_partner: + # Chercher parmi les contacts liés à la compagnie de l'objet courant + company = current_partner.commercial_partner_id + company_contacts = from_partners.filtered(lambda p: p.commercial_partner_id == company) + + if company_contacts: + # Si on trouve des contacts liés à la compagnie, prendre le plus récent + from_partner = company_contacts.filtered('active').sorted('write_date', reverse=True)[0] if company_contacts.filtered('active') else company_contacts[0] + _logger.info('Plusieurs partenaires trouvés pour l\'email %s - Utilisation du contact %s lié à la compagnie %s', + from_email, from_partner.name, company.name) + else: + # Si aucun contact lié à la compagnie n'est trouvé, utiliser la logique précédente + company_partner = from_partners.filtered('is_company') + if len(company_partner) == 1: + from_partner = company_partner + else: + from_partner = from_partners.filtered('active').sorted('write_date', reverse=True)[0] if from_partners.filtered('active') else from_partners[0] + _logger.info('Plusieurs partenaires trouvés pour l\'email %s - Utilisation de %s (aucun contact lié à la compagnie actuelle)', + from_email, from_partner.name) + else: + # Si pas de partenaire courant, utiliser la logique précédente + company_partner = from_partners.filtered('is_company') + if len(company_partner) == 1: + from_partner = company_partner + else: + from_partner = from_partners.filtered('active').sorted('write_date', reverse=True)[0] if from_partners.filtered('active') else from_partners[0] + _logger.info('Plusieurs partenaires trouvés pour l\'email %s - Utilisation de %s', from_email, from_partner.name) + else: + from_partner = from_partners + # Add headers email_msg["Subject"] = ( self._clean_header_value(msg_file.subject) or "No Subject" @@ -194,7 +285,12 @@ class IrAttachment(models.Model): raise def process_msg_as_email(self): - """Convert MSG file to EML and process it using Odoo's mail module.""" + """ + Convert MSG file to EML and process it using Odoo's mail module. + + Returns: + bool: True if successful, False otherwise + """ self.ensure_one() _logger.debug( "Starting MSG processing for file: %s (model: %s, res_id: %s)", @@ -271,17 +367,22 @@ class IrAttachment(models.Model): return False def _notify_error(self, title, message): - """Show error notification to the user.""" - self.env["bus.bus"]._sendone( - self.env.user.partner_id, - "notification", - { - "type": "danger", - "title": title, - "message": message, - "sticky": True, - }, - ) + """ + Show error notification to the user. + + Args: + title (str): Title of the notification. + message (str): Message to display in the notification. + + Returns: + None + """ + self.env['bus.bus']._sendone(self.env.user.partner_id, 'notification', { + 'type': 'danger', + 'title': title, + 'message': message, + 'sticky': True, + }) @api.model_create_multi def create(self, vals_list):