Files
odoo_source/addons/mass_mailing/wizard/mailing_contact_import.py
T
Pierre-Yves Dufays aa0d8789d4 [FIX] mass_mailing: fix email import by skipping invalid lines
When importing email in mass mailing through the form (not with an excel file),
incorrect email lines were concatenated with the following next valid email
line, resulting to an incorrect import.
This solves the problem by ignoring incorrect email lines.

Technical note: the test test_mailing_contact_import has been slightly modified
to include invalid lines in the text to import, not only at the end but also at
the beginning and in the middle (the test fails before the fix and not after).

Task-2924241

X-original-commit: bd4a933f2b3259c3482b811227de0e06c7018969
Part-of: odoo/odoo#97560
2022-08-08 21:02:55 +02:00

127 lines
4.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, tools, _
from odoo.tools.misc import clean_context
class MailingContactImport(models.TransientModel):
_name = 'mailing.contact.import'
_description = 'Mailing Contact Import'
mailing_list_ids = fields.Many2many('mailing.list', string='Lists')
contact_list = fields.Text('Contact List', help='Contact list that will be imported, one contact per line')
def action_import(self):
"""Import each lines of "contact_list" as a new contact."""
self.ensure_one()
contacts = tools.email_split_tuples(', '.join(self.contact_list.splitlines()))
if not contacts:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': _('No valid email address found.'),
'next': {'type': 'ir.actions.act_window_close'},
'sticky': False,
'type': 'warning',
}
}
if len(contacts) > 5000:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': _('You have to much emails, please upload a file.'),
'type': 'warning',
'sticky': False,
'next': self.action_open_base_import(),
}
}
all_emails = list({values[1].lower() for values in contacts})
existing_contacts = self.env['mailing.contact'].search([
('email_normalized', 'in', all_emails),
('list_ids', 'in', self.mailing_list_ids.ids),
])
existing_contacts = {
contact.email_normalized: contact
for contact in existing_contacts
}
# Remove duplicated record, keep only the first non-empty name for each email address
unique_contacts = {}
for name, email in contacts:
email = email.lower()
if unique_contacts.get(email, {}).get('name'):
continue
if email in existing_contacts and not self.mailing_list_ids < existing_contacts[email].list_ids:
existing_contacts[email].list_ids |= self.mailing_list_ids
if email not in existing_contacts:
unique_contacts[email] = {
'name': name,
'list_ids': self.mailing_list_ids.ids,
}
if not unique_contacts:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': _('No contacts were imported. All email addresses are already in the mailing list.'),
'next': {'type': 'ir.actions.act_window_close'},
'sticky': False,
'type': 'warning',
}
}
new_contacts = self.env['mailing.contact'].with_context(clean_context(self.env.context)).create([
{
'email': email,
**values,
}
for email, values in unique_contacts.items()
])
ignored = len(contacts) - len(unique_contacts)
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': (
_('%i Contacts have been imported.', len(unique_contacts))
+ (_(' %i duplicates have been ignored.', ignored) if ignored else '')
),
'type': 'success',
'sticky': False,
'next': {
'context': self.env.context,
'domain': [('id', 'in', new_contacts.ids)],
'name': _('New contacts imported'),
'res_model': 'mailing.contact',
'type': 'ir.actions.act_window',
'view_mode': 'list',
'views': [[False, 'list'], [False, 'form']],
},
}
}
def action_open_base_import(self):
"""Open the base import wizard to import mailing list contacts with a xlsx file."""
self.ensure_one()
return {
'type': 'ir.actions.client',
'tag': 'import',
'name': _('Import Mailing Contacts'),
'params': {
'context': self.env.context,
'model': 'mailing.contact',
}
}