trytond-electronic_mail_filter/electronic_mail.py

219 lines
7.8 KiB
Python
Raw Permalink Normal View History

2015-01-23 12:44:40 +01:00
# This file is part of electronic_mail_filter module for Tryton.
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from datetime import datetime
2018-06-27 16:20:35 +02:00
from trytond.model import ModelSQL, ModelView, fields, DeactivableMixin
2015-01-23 12:44:40 +01:00
from trytond.pool import Pool, PoolMeta
2015-07-10 08:38:13 +02:00
from trytond.pyson import Bool, Eval, Not
2015-01-23 12:44:40 +01:00
from trytond.transaction import Transaction
__all__ = ['ElectronicMailFilter', 'SearchingStart']
2018-06-27 16:20:35 +02:00
class ElectronicMailFilter(DeactivableMixin, ModelSQL, ModelView):
2015-01-23 12:44:40 +01:00
'eMail Filter'
__name__ = 'electronic.mail.filter'
name = fields.Char('Name', required=True,
help='Name of the cron for sending Email.')
template = fields.Many2One('electronic.mail.template', 'eMail Template',
required=True)
model = fields.Function(fields.Many2One('ir.model', 'Model'),
'on_change_with_model')
cron = fields.Many2One('ir.cron', 'Cron', readonly=True)
profile = fields.Many2One('searching.profile', 'Profile',
domain=[
('model', '=', Eval('model')),
],
context={
'model': Eval('model'),
},
depends=['model'])
last_send = fields.DateTime('Last Send', required=True)
manual = fields.Boolean('Manual')
source = fields.Text('Source',
states={
2015-07-10 08:38:13 +02:00
'readonly': Not(Bool(Eval('manual'))),
'required': Bool(Eval('manual')),
2015-01-23 12:44:40 +01:00
}, depends=['manual'],
help='Available global variables:\n'
'\tself: Instance of this model.\n'
'\tpool: Instance of Pool that allows get access to any model '
'of database.\n'
'Returns `records`: List of records you want to select.')
mix_operator = fields.Selection([
('all', 'All'),
('any', 'Any'),
], 'Mix operator',
states={
2015-07-10 08:38:13 +02:00
'readonly': Not(Bool(Eval('manual'))),
2015-01-23 12:44:40 +01:00
},
help='Operator to mix the records obtained through the filters in the '
'first tab and records calculated by the manual code.')
email = fields.Many2One('party.contact_mechanism', 'E-Mail',
domain=[('type', '=', 'email')],
2021-02-15 16:09:20 +01:00
help='Defines E-mail to use instead of defined in email template. '
'Required if check "Send email when no records" enabled.')
2015-01-23 12:44:40 +01:00
@classmethod
def __setup__(cls):
super(ElectronicMailFilter, cls).__setup__()
cls._error_messages.update({
'filter_error': 'Manual filter error:\n%s',
'filter_success': 'Filter obtained these records:\n%s',
'filter_without_errors': 'Filter ended without errors, but do '
'not obtained any records.',
'details': 'Details:\n%s',
})
cls._buttons.update({
'test_profile': {
},
'send_emails': {
},
'create_cron': {
2015-07-10 08:38:13 +02:00
'invisible': Bool(Eval('cron')),
2015-01-23 12:44:40 +01:00
},
'delete_cron': {
2015-07-10 08:38:13 +02:00
'invisible': Not(Bool(Eval('cron'))),
2015-01-23 12:44:40 +01:00
},
})
@staticmethod
def default_mix_operator():
return 'all'
@staticmethod
def default_last_send():
return datetime.now()
@fields.depends('template')
def on_change_with_model(self, name=None):
if self.template:
return self.template.model.id
@classmethod
@ModelView.button
def create_cron(cls, filters):
pool = Pool()
Cron = pool.get('ir.cron')
User = pool.get('res.user')
cron_user, = User.search([
('active', '=', False),
('login', '=', 'user_cron_trigger'),
])
admin_user, = User.search([('login', '=', 'admin')])
args = []
vlist = []
for filter_ in filters:
vlist = [{
'name': filter_.name,
'user': cron_user.id,
'request_user': admin_user.id,
'active': True,
'interval_number': 1,
'interval_type': 'days',
2015-07-10 08:38:13 +02:00
'number_calls': -1,
2015-01-23 12:44:40 +01:00
'next_call': datetime.now(),
'model': 'electronic.mail.filter',
'function': 'send_emails',
2019-09-14 16:32:35 +02:00
'args': '([%s,],)' % filter_.id,
2015-01-23 12:44:40 +01:00
}]
cron, = Cron.create(vlist)
args.extend(([filter_], {'cron': cron}))
cls.write(*args)
@classmethod
@ModelView.button
def delete_cron(cls, filters):
Cron = Pool().get('ir.cron')
crons = [f.cron for f in filters]
Cron.delete(crons)
@classmethod
@ModelView.button_action(
'searching.act_searching')
def test_profile(cls, filters):
pass
def search_records(self):
Model = Pool().get(self.model.model)
domain = self.profile.get_domain()
try:
records = Model.search(domain)
2019-03-08 14:16:30 +01:00
except (SyntaxError, NameError, IndexError, AttributeError) as exc:
2015-01-23 12:44:40 +01:00
self.raise_user_error('filter_error', exc)
return records
@classmethod
@ModelView.button
def send_emails(cls, filters):
pool = Pool()
ElectronicMail = pool.get('electronic.mail')
EmailConfiguration = pool.get('electronic.mail.configuration')
email_configuration = EmailConfiguration(1)
2019-09-14 16:32:35 +02:00
if filters and isinstance(filters[0], int):
2015-01-23 12:44:40 +01:00
filters = cls.search([
2019-09-14 16:32:35 +02:00
('id', 'in', filters),
2015-01-23 12:44:40 +01:00
])
emails = []
for fltr in filters:
2020-01-30 15:49:48 +01:00
ctx = fltr.profile.get_context()
with Transaction().set_context(**ctx):
template = fltr.template
records = fltr.search_records()
if not records:
if not template.no_records_email:
continue
records.append(fltr)
elif template.no_records_email:
2020-01-30 15:49:48 +01:00
continue
group_records = (getattr(template, 'single_email', False) and
getattr(template, 'group_records', False))
if group_records:
2020-01-30 15:49:48 +01:00
records = group_records(records)
if fltr.email:
# group all records, discard template 'to' grouping
2021-09-29 11:27:41 +02:00
records = [[r for g in records for r in g]]
2020-01-30 15:49:48 +01:00
for record in records:
if group_records:
attachments = template.get_attachments(record)
record = record[0]
else:
attachments = template.get_attachments([record])
message = template.render_message(record, attachments)
mailbox = (template.mailbox
if template.mailbox
else email_configuration.sent)
field_expression = getattr(template, 'bcc')
eval_result = template.eval(field_expression, record)
if eval_result:
message['bcc'] = eval_result
if fltr.email:
message.replace_header('to', fltr.email.email)
2020-01-30 15:49:48 +01:00
emails.append(ElectronicMail.create_from_mail(message,
mailbox))
2018-07-11 11:56:36 +02:00
ElectronicMail.send_mail(emails)
2015-01-23 12:44:40 +01:00
2019-03-08 14:16:30 +01:00
class SearchingStart(metaclass=PoolMeta):
2015-01-23 12:44:40 +01:00
__name__ = 'searching.start'
@staticmethod
def default_profile():
context = Transaction().context
active_id = context.get('active_id')
active_model = context.get('active_model')
if active_model == 'electronic.mail.filter':
filter_ = Pool().get('electronic.mail.filter')(active_id)
if filter_.profile:
return filter_.profile.id