2016-04-12 13:39:27 +02:00
|
|
|
# This file is part smtp module for Tryton.
|
|
|
|
# The COPYRIGHT file at the top level of this repository contains
|
|
|
|
# the full copyright notices and license terms.
|
2023-03-21 17:16:57 +01:00
|
|
|
import logging
|
2012-10-30 10:24:06 +01:00
|
|
|
from trytond.model import ModelView, ModelSQL, fields
|
|
|
|
from trytond.pool import Pool
|
2015-12-10 23:11:24 +01:00
|
|
|
from trytond.pyson import Eval
|
2018-06-12 23:29:22 +02:00
|
|
|
import smtplib
|
2019-01-16 15:37:47 +01:00
|
|
|
from trytond.i18n import gettext
|
|
|
|
from trytond.exceptions import UserError
|
2012-10-30 10:24:06 +01:00
|
|
|
|
2023-03-21 17:16:57 +01:00
|
|
|
logger = logging.getLogger(__name__)
|
2012-10-30 10:24:06 +01:00
|
|
|
|
2012-12-04 17:07:52 +01:00
|
|
|
|
2012-10-30 10:24:06 +01:00
|
|
|
class SmtpServer(ModelSQL, ModelView):
|
|
|
|
'SMTP Servers'
|
|
|
|
__name__ = 'smtp.server'
|
|
|
|
name = fields.Char('Name', required=True)
|
|
|
|
smtp_server = fields.Char('Server', required=True,
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'])
|
2018-06-12 23:29:22 +02:00
|
|
|
smtp_timeout = fields.Integer('Timeout', required=True,
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
|
|
|
}, depends=['state'], help="Time in secods")
|
2012-12-04 17:04:42 +01:00
|
|
|
smtp_port = fields.Integer('Port', required=True,
|
2012-10-30 10:24:06 +01:00
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'])
|
2012-10-30 10:24:06 +01:00
|
|
|
smtp_ssl = fields.Boolean('SSL',
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'])
|
2012-10-30 10:24:06 +01:00
|
|
|
smtp_tls = fields.Boolean('TLS',
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'])
|
2012-10-30 10:24:06 +01:00
|
|
|
smtp_user = fields.Char('User',
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'])
|
2022-09-26 16:43:19 +02:00
|
|
|
smtp_password = fields.Char('Password', strip=False,
|
2012-10-30 10:24:06 +01:00
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'])
|
2012-11-06 16:37:00 +01:00
|
|
|
smtp_use_email = fields.Boolean('Use email',
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'], help='Force to send emails using this email')
|
2012-11-06 16:37:00 +01:00
|
|
|
smtp_email = fields.Char('Email', required=True,
|
|
|
|
states={
|
|
|
|
'readonly': (Eval('state') != 'draft'),
|
2016-04-12 13:39:27 +02:00
|
|
|
}, depends=['state'],
|
2012-12-04 17:04:42 +01:00
|
|
|
help='Default From (if active this option) and Reply Email')
|
2012-10-30 10:24:06 +01:00
|
|
|
state = fields.Selection([
|
2016-04-12 13:39:27 +02:00
|
|
|
('draft', 'Draft'),
|
|
|
|
('done', 'Done'),
|
|
|
|
], 'State', readonly=True, required=True)
|
2012-10-30 10:24:06 +01:00
|
|
|
default = fields.Boolean('Default')
|
2012-12-04 17:04:42 +01:00
|
|
|
models = fields.Many2Many('smtp.server-ir.model',
|
|
|
|
'server', 'model', 'Models',
|
|
|
|
states={
|
|
|
|
'readonly': Eval('state').in_(['done']),
|
|
|
|
},
|
|
|
|
depends=['state'])
|
2012-10-30 10:24:06 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(SmtpServer, cls).__setup__()
|
|
|
|
cls._buttons.update({
|
2016-04-12 13:39:27 +02:00
|
|
|
'get_smtp_test': {},
|
|
|
|
'draft': {
|
|
|
|
'invisible': Eval('state') == 'draft',
|
2018-12-15 10:38:23 +01:00
|
|
|
'depends': ['state'],
|
2016-04-12 13:39:27 +02:00
|
|
|
},
|
|
|
|
'done': {
|
|
|
|
'invisible': Eval('state') == 'done',
|
2018-12-15 10:38:23 +01:00
|
|
|
'depends': ['state'],
|
2016-04-12 13:39:27 +02:00
|
|
|
},
|
|
|
|
})
|
2012-10-30 10:24:06 +01:00
|
|
|
|
2015-03-03 11:42:16 +01:00
|
|
|
@classmethod
|
|
|
|
def check_xml_record(cls, records, values):
|
|
|
|
return True
|
|
|
|
|
2012-10-30 10:24:06 +01:00
|
|
|
@staticmethod
|
|
|
|
def default_default():
|
|
|
|
return True
|
|
|
|
|
2018-06-12 23:29:22 +02:00
|
|
|
@staticmethod
|
2018-08-18 11:12:31 +02:00
|
|
|
def default_smtp_timeout():
|
2018-06-12 23:29:22 +02:00
|
|
|
return 60
|
|
|
|
|
2012-10-30 10:24:06 +01:00
|
|
|
@staticmethod
|
2013-12-09 12:43:33 +01:00
|
|
|
def default_smtp_ssl():
|
2012-10-30 10:24:06 +01:00
|
|
|
return True
|
|
|
|
|
|
|
|
@staticmethod
|
2013-12-09 12:43:33 +01:00
|
|
|
def default_smtp_port():
|
|
|
|
return 465
|
2012-10-30 10:24:06 +01:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_state():
|
|
|
|
return 'draft'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def draft(cls, servers):
|
2015-03-18 14:37:30 +01:00
|
|
|
cls.write(servers, {
|
2016-04-12 13:39:27 +02:00
|
|
|
'state': 'draft',
|
|
|
|
})
|
2012-10-30 10:24:06 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def done(cls, servers):
|
2015-03-18 14:37:30 +01:00
|
|
|
cls.write(servers, {
|
2016-04-12 13:39:27 +02:00
|
|
|
'state': 'done',
|
|
|
|
})
|
2012-10-30 10:24:06 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def get_smtp_test(cls, servers):
|
|
|
|
"""Checks SMTP credentials and confirms if outgoing connection works"""
|
|
|
|
for server in servers:
|
|
|
|
try:
|
2015-02-19 16:23:13 +01:00
|
|
|
server.get_smtp_server()
|
2018-08-18 11:12:46 +02:00
|
|
|
except Exception as message:
|
2023-03-21 17:16:57 +01:00
|
|
|
logger.error('Exception getting smtp server: %s', message)
|
2019-01-16 15:37:47 +01:00
|
|
|
raise UserError(gettext('smtp.smtp_test_details',
|
|
|
|
error=message))
|
|
|
|
raise UserError(gettext('smtp.smtp_successful'))
|
2012-10-30 10:24:06 +01:00
|
|
|
|
2015-02-19 16:23:13 +01:00
|
|
|
def get_smtp_server(self):
|
2012-10-30 10:24:06 +01:00
|
|
|
"""
|
|
|
|
Instanciate, configure and return a SMTP or SMTP_SSL instance from
|
|
|
|
smtplib.
|
|
|
|
:return: A SMTP instance. The quit() method must be call when all
|
|
|
|
the calls to sendmail() have been made.
|
|
|
|
"""
|
2015-02-19 16:23:13 +01:00
|
|
|
if self.smtp_ssl:
|
2018-06-12 23:29:22 +02:00
|
|
|
smtp_server = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port,
|
|
|
|
timeout=self.smtp_timeout)
|
2012-10-30 10:24:06 +01:00
|
|
|
else:
|
2018-06-12 23:29:22 +02:00
|
|
|
smtp_server = smtplib.SMTP(self.smtp_server, self.smtp_port,
|
|
|
|
timeout=self.smtp_timeout)
|
2012-10-30 10:24:06 +01:00
|
|
|
|
2015-02-19 16:23:13 +01:00
|
|
|
if self.smtp_tls:
|
2012-10-30 10:24:06 +01:00
|
|
|
smtp_server.starttls()
|
|
|
|
|
2015-02-19 16:23:13 +01:00
|
|
|
if self.smtp_user and self.smtp_password:
|
2018-09-19 07:46:16 +02:00
|
|
|
smtp_server.login(self.smtp_user, self.smtp_password)
|
2012-10-30 10:24:06 +01:00
|
|
|
|
|
|
|
return smtp_server
|
2012-12-04 17:04:42 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_smtp_server_from_model(self, model):
|
|
|
|
"""
|
|
|
|
Return Server from Models
|
|
|
|
:param model: str Model name
|
|
|
|
return object server
|
|
|
|
"""
|
|
|
|
model = Pool().get('ir.model').search([('model', '=', model)])[0]
|
|
|
|
servers = Pool().get('smtp.server-ir.model').search([
|
2016-04-12 13:39:27 +02:00
|
|
|
('model', '=', model),
|
|
|
|
], limit=1)
|
2012-12-04 17:04:42 +01:00
|
|
|
if not servers:
|
2023-03-21 17:16:57 +01:00
|
|
|
logger.warning('No SMTP server found for model %s' % model)
|
2019-01-16 15:37:47 +01:00
|
|
|
raise UserError(gettext(
|
|
|
|
'smtp.server_model_not_found', model=model.name))
|
2012-12-04 17:04:42 +01:00
|
|
|
return servers[0].server
|
|
|
|
|
2018-06-12 23:29:22 +02:00
|
|
|
def send_mail(self, from_, cc, email):
|
|
|
|
try:
|
|
|
|
smtp_server = self.get_smtp_server()
|
2023-03-21 17:16:57 +01:00
|
|
|
issues = smtp_server.sendmail(from_, cc, email)
|
2018-06-12 23:29:22 +02:00
|
|
|
smtp_server.quit()
|
|
|
|
return True
|
2018-08-18 11:12:46 +02:00
|
|
|
except smtplib.SMTPException as error:
|
2023-03-21 17:16:57 +01:00
|
|
|
logger.error('SMTPException: %s', error)
|
2020-11-05 16:22:17 +01:00
|
|
|
raise UserError(gettext('smtp.smtp_exception', error=error))
|
2018-08-18 11:12:46 +02:00
|
|
|
except smtplib.socket.error as error:
|
2023-03-21 17:16:57 +01:00
|
|
|
logger.error('socket.error: %s', error)
|
2019-01-16 15:37:47 +01:00
|
|
|
raise UserError(gettext('smtp.smtp_server_error', error=error))
|
2018-06-12 23:29:22 +02:00
|
|
|
return False
|
|
|
|
|
2012-12-04 17:04:42 +01:00
|
|
|
|
|
|
|
class SmtpServerModel(ModelSQL):
|
|
|
|
'SMTP Server - Model'
|
|
|
|
__name__ = 'smtp.server-ir.model'
|
|
|
|
_table = 'smtp_server_ir_model'
|
|
|
|
|
|
|
|
server = fields.Many2One('smtp.server', 'Server', ondelete='CASCADE',
|
2022-11-08 19:24:34 +01:00
|
|
|
required=True)
|
2012-12-04 17:04:42 +01:00
|
|
|
model = fields.Many2One('ir.model', 'Model', ondelete='RESTRICT',
|
2022-11-08 19:24:34 +01:00
|
|
|
required=True)
|