You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.6 KiB
190 lines
6.6 KiB
# -*- coding: utf-8 -*-
|
|
# Copyright 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
|
|
import logging
|
|
from openerp import api, fields, models, tools
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
BATCH_SIZE_DEFAULT = 500
|
|
|
|
|
|
class MailMassMailingSending(models.Model):
|
|
_name = 'mail.mass_mailing.sending'
|
|
|
|
state = fields.Selection([
|
|
('draft', "Draft"),
|
|
('enqueued', "Enqueued"),
|
|
('sending', "Sending"),
|
|
('sent', "Sent"),
|
|
('error', "Error"),
|
|
], string="State", required=True, copy=False, default='enqueued')
|
|
mass_mailing_id = fields.Many2one(
|
|
string="Mass mailing", comodel_name='mail.mass_mailing',
|
|
readonly=True, ondelete='cascade')
|
|
pending_count = fields.Integer(
|
|
string="Pending recipients", compute='_compute_pending_count')
|
|
sending_count = fields.Integer(
|
|
string="Mails to be sent", compute='_compute_sending_count')
|
|
sent_count = fields.Integer(
|
|
string="Sent mails", compute='_compute_sent_count')
|
|
failed_count = fields.Integer(
|
|
string="Failed mails", compute='_compute_failed_count')
|
|
error = fields.Char(string="Error message")
|
|
date_start = fields.Datetime(
|
|
string="Date start", default=fields.Datetime.now())
|
|
date_end = fields.Datetime(string="Date end")
|
|
|
|
@api.model
|
|
def batch_size_get(self):
|
|
m_param = self.env['ir.config_parameter']
|
|
batch_size = BATCH_SIZE_DEFAULT
|
|
batch_size_str = m_param.get_param(
|
|
'mail.mass_mailing.sending.batch_size')
|
|
if batch_size_str and batch_size_str.isdigit():
|
|
batch_size = int(batch_size_str)
|
|
return batch_size
|
|
|
|
@api.multi
|
|
def pending_emails(self):
|
|
return self.env['mail.mail.statistics'].search([
|
|
('mass_mailing_sending_id', 'in', self.ids),
|
|
('scheduled', '!=', False),
|
|
('sent', '=', False),
|
|
('exception', '=', False),
|
|
])
|
|
|
|
@api.multi
|
|
def get_recipient_batch(self, res_ids):
|
|
batch_size = self.batch_size_get()
|
|
already_enqueued = self.env['mail.mail.statistics'].search([
|
|
('mass_mailing_sending_id', 'in', self.ids),
|
|
])
|
|
set_ids = set(res_ids)
|
|
new_ids = list(
|
|
set_ids - set(already_enqueued.mapped('res_id')))
|
|
if not self.env.context.get('sending_avoid_batch', False):
|
|
new_ids = new_ids[:batch_size]
|
|
if set(new_ids) != set_ids:
|
|
return new_ids
|
|
return res_ids
|
|
|
|
@api.multi
|
|
def pending_recipients(self):
|
|
self.ensure_one()
|
|
m_mailing = self.env['mail.mass_mailing'].with_context(
|
|
mass_mailing_sending_id=self.id, sending_avoid_batch=True)
|
|
return m_mailing.get_recipients(self.mass_mailing_id)
|
|
|
|
@api.multi
|
|
def send_mail(self):
|
|
for sending in self:
|
|
try:
|
|
sending.with_context(mass_mailing_sending_id=sending.id).\
|
|
mass_mailing_id.send_mail()
|
|
except Exception as e:
|
|
sending._send_error(e)
|
|
return True
|
|
|
|
@api.multi
|
|
def _send_error(self, exception):
|
|
self.ensure_one()
|
|
self.write({
|
|
'error': tools.ustr(exception),
|
|
'state': 'error',
|
|
'date_end': fields.Datetime.now(),
|
|
})
|
|
self.mass_mailing_id.state = 'done'
|
|
|
|
@api.multi
|
|
def _process_enqueued(self):
|
|
# Create mail_mail objects not created
|
|
self.ensure_one()
|
|
if self.pending_recipients():
|
|
self.send_mail()
|
|
# If there is no more recipient left, mark as sending
|
|
if not self.pending_recipients():
|
|
self.state = 'sending'
|
|
self._process_sending()
|
|
elif self.mass_mailing_id.state not in {'sending', 'error'}:
|
|
self.mass_mailing_id.state = 'sending'
|
|
|
|
@api.multi
|
|
def _process_sending(self):
|
|
# Check if there is any mail_mail object not sent
|
|
self.ensure_one()
|
|
if not self.pending_emails():
|
|
self.mass_mailing_id.state = 'done'
|
|
self.write({
|
|
'state': 'sent',
|
|
'date_end': fields.Datetime.now(),
|
|
})
|
|
elif self.mass_mailing_id.state not in {'sending', 'error'}:
|
|
self.mass_mailing_id.state = 'sending'
|
|
|
|
@api.multi
|
|
def _process(self):
|
|
self.ensure_one()
|
|
method = getattr(self, '_process_%s' % self.state, None)
|
|
if method and hasattr(method, '__call__'):
|
|
return method()
|
|
return False # pragma: no cover
|
|
|
|
@api.model
|
|
def sendings_running(self):
|
|
return self.search([
|
|
('state', 'in', ('enqueued', 'sending')),
|
|
])
|
|
|
|
@api.model
|
|
def cron(self):
|
|
# Process all mail.mass_mailing.sending in enqueue or sending state
|
|
sendings = self.sendings_running()
|
|
for sending in sendings:
|
|
_logger.info("Sending [%d] mass mailing [%d] '%s' (%s)",
|
|
sending.id, sending.mass_mailing_id.id,
|
|
sending.mass_mailing_id.name, sending.state)
|
|
# Process sending using user who created it
|
|
sending = sending.sudo(user=sending.create_uid.id)
|
|
ctx = sending.create_uid.context_get()
|
|
sending.with_context(**ctx)._process()
|
|
return True
|
|
|
|
@api.multi
|
|
def _compute_pending_count(self):
|
|
for sending in self.filtered(lambda r: r.state == 'enqueued'):
|
|
sending.pending_count = len(sending.pending_recipients())
|
|
|
|
@api.multi
|
|
def _compute_sending_count(self):
|
|
m_stats = self.env['mail.mail.statistics']
|
|
for sending in self.filtered(
|
|
lambda r: r.state in {'enqueued', 'sending'}):
|
|
sending.sending_count = m_stats.search_count([
|
|
('mass_mailing_sending_id', '=', sending.id),
|
|
('scheduled', '!=', False),
|
|
('sent', '=', False),
|
|
('exception', '=', False),
|
|
])
|
|
|
|
@api.multi
|
|
def _compute_sent_count(self):
|
|
m_stats = self.env['mail.mail.statistics']
|
|
for sending in self:
|
|
sending.sent_count = m_stats.search_count([
|
|
('mass_mailing_sending_id', '=', sending.id),
|
|
('scheduled', '!=', False),
|
|
('sent', '!=', False),
|
|
('exception', '=', False),
|
|
])
|
|
|
|
@api.multi
|
|
def _compute_failed_count(self):
|
|
m_stats = self.env['mail.mail.statistics']
|
|
for sending in self:
|
|
sending.failed_count = m_stats.search_count([
|
|
('mass_mailing_sending_id', '=', sending.id),
|
|
('scheduled', '!=', False),
|
|
('exception', '!=', False),
|
|
])
|