confirguration smtp client

This commit is contained in:
wilsongomez 2022-09-02 09:06:03 -05:00
parent b665e950ea
commit a9664f93dc
7 changed files with 203 additions and 96 deletions

View file

@ -3,10 +3,11 @@
# the full copyright notices and license terms.
from trytond.pool import Pool
from . import smtp
from . import email_
def register():
Pool.register(
smtp.SmtpServer,
smtp.SmtpServerModel,
smtp.SmtpConnectionMail,
email_.Email,
module='smtp', type_='model')

141
email_.py Normal file
View file

@ -0,0 +1,141 @@
import heapq
import mimetypes
import re
from email.encoders import encode_base64
from email.header import Header
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.nonmultipart import MIMENonMultipart
from email.mime.text import MIMEText
from email.utils import formataddr, getaddresses
try:
import html2text
except ImportError:
html2text = None
from genshi.template import TextTemplate
# from trytond.i18n import gettext
from trytond.config import config
from trytond.pool import Pool, PoolMeta
from trytond.report import Report
from trytond.ir.email_ import HTML_EMAIL, _get_emails
from trytond.sendmail import sendmail_transactional, SMTPDataManager
from trytond.transaction import Transaction
from .sendmail import _SMTPDataManager
class Email(metaclass=PoolMeta):
"Email"
__name__ = 'ir.email'
@classmethod
def send(cls, to='', cc='', bcc='', subject='', body='',
files=None, record=None, reports=None, attachments=None):
pool = Pool()
User = pool.get('res.user')
ActionReport = pool.get('ir.action.report')
Attachment = pool.get('ir.attachment')
transaction = Transaction()
user = User(transaction.user)
SmtpConnection = pool.get('smtp.connection.mail')
smtps = SmtpConnection.search([('user', '=', user.id)])
uri = None
user_email = None
if smtps:
uri = smtps[0].get_uri()
user_email = smtps[0].smtp_email
Model = pool.get(record[0])
record = Model(record[1])
body_html = HTML_EMAIL % {
'subject': subject,
'body': body,
'signature': user.signature or '',
}
content = MIMEMultipart('alternative')
if html2text:
body_text = HTML_EMAIL % {
'subject': subject,
'body': body,
'signature': '',
}
converter = html2text.HTML2Text()
body_text = converter.handle(body_text)
if user.signature:
body_text += '\n-- \n' + converter.handle(user.signature)
part = MIMEText(body_text, 'plain', _charset='utf-8')
content.attach(part)
part = MIMEText(body_html, 'html', _charset='utf-8')
content.attach(part)
if files or reports or attachments:
msg = MIMEMultipart('mixed')
msg.attach(content)
if files is None:
files = []
else:
files = list(files)
for report_id in (reports or []):
report = ActionReport(report_id)
Report = pool.get(report.report_name, type='report')
ext, content, _, title = Report.execute(
[record.id], {
'action_id': report.id,
})
name = '%s.%s' % (title, ext)
if isinstance(content, str):
content = content.encode('utf-8')
files.append((name, content))
if attachments:
files += [
(a.name, a.data) for a in Attachment.browse(attachments)]
for name, data in files:
mimetype, _ = mimetypes.guess_type(name)
if mimetype:
attachment = MIMENonMultipart(*mimetype.split('/'))
attachment.set_payload(data)
encode_base64(attachment)
else:
attachment = MIMEApplication(data)
attachment.add_header(
'Content-Disposition', 'attachment',
filename=('utf-8', '', name))
msg.attach(attachment)
else:
msg = content
msg['From'] = from_ = user_email
if user.email:
if user.name:
user_email = formataddr((user.name, user.email))
else:
user_email = user.email
msg['Behalf-Of'] = user_email
msg['Reply-To'] = user_email
msg['To'] = ', '.join(formataddr(a) for a in getaddresses([to]))
msg['Cc'] = ', '.join(formataddr(a) for a in getaddresses([cc]))
msg['Subject'] = Header(subject, 'utf-8')
to_addrs = list(filter(None, map(
str.strip,
_get_emails(to) + _get_emails(cc) + _get_emails(bcc))))
sendmail_transactional(
from_, to_addrs, msg, datamanager=SMTPDataManager(uri=uri, strict=True))
email = cls(
recipients=to,
recipients_secondary=cc,
recipients_hidden=bcc,
addresses=[{'address': a} for a in to_addrs],
subject=subject,
body=body,
resource=record)
email.save()
with Transaction().set_context(_check_access=False):
attachments_ = []
for name, data in files:
attachments_.append(
Attachment(resource=email, name=name, data=data))
Attachment.save(attachments_)
return email

View file

@ -90,25 +90,15 @@ setup(name=name,
'Intended Audience :: Financial and Insurance Industry',
'Intended Audience :: Legal Industry',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Natural Language :: Bulgarian',
'Natural Language :: Catalan',
'Natural Language :: Chinese (Simplified)',
'Natural Language :: Czech',
'Natural Language :: Dutch',
'Natural Language :: English',
'Natural Language :: French',
'Natural Language :: German',
'Natural Language :: Hungarian',
'Natural Language :: Italian',
'Natural Language :: Portuguese (Brazilian)',
'Natural Language :: Russian',
'Natural Language :: Slovenian',
'Natural Language :: Spanish',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Office/Business',
@ -125,8 +115,4 @@ setup(name=name,
test_suite='tests',
test_loader='trytond.test_loader:Loader',
tests_require=tests_require,
use_2to3=True,
convert_2to3_doctests=[
'tests/scenario.rst',
],
)

102
smtp.py
View file

@ -8,9 +8,9 @@ from trytond.pool import Pool
from trytond.pyson import Eval
class SmtpServer(ModelSQL, ModelView):
'SMTP Servers'
__name__ = 'smtp.server'
class SmtpConnectionMail(ModelSQL, ModelView):
'SMTP Conection Mail'
__name__ = 'smtp.connection.mail'
name = fields.Char('Name', required=True)
smtp_server = fields.Char('Server', required=True,
states={
@ -28,18 +28,10 @@ class SmtpServer(ModelSQL, ModelView):
states={
'readonly': (Eval('state') != 'draft'),
}, depends=['state'])
smtp_user = fields.Char('User',
states={
'readonly': (Eval('state') != 'draft'),
}, depends=['state'])
smtp_password = fields.Char('Password',
states={
'readonly': (Eval('state') != 'draft'),
}, depends=['state'])
smtp_use_email = fields.Boolean('Use email',
states={
'readonly': (Eval('state') != 'draft'),
}, depends=['state'], help='Force to send emails using this email')
smtp_email = fields.Char('Email', required=True,
states={
'readonly': (Eval('state') != 'draft'),
@ -49,24 +41,11 @@ class SmtpServer(ModelSQL, ModelView):
('draft', 'Draft'),
('done', 'Done'),
], 'State', readonly=True, required=True)
default = fields.Boolean('Default')
models = fields.Many2Many('smtp.server-ir.model',
'server', 'model', 'Models',
states={
'readonly': Eval('state').in_(['done']),
},
depends=['state'])
user = fields.Many2One('res.user', 'User')
@classmethod
def __setup__(cls):
super(SmtpServer, cls).__setup__()
cls._error_messages.update({
'smtp_successful': 'SMTP Test Connection Was Successful',
'smtp_test_details': 'SMTP Test Connection Details:\n%s',
'smtp_error': 'SMTP Test Connection Failed.',
'server_model_not_found': (
'There are not SMTP server related at model %s'),
})
super(SmtpConnectionMail, cls).__setup__()
cls._buttons.update({
'get_smtp_test': {},
'draft': {
@ -81,9 +60,6 @@ class SmtpServer(ModelSQL, ModelView):
def check_xml_record(cls, records, values):
return True
@staticmethod
def default_default():
return True
@staticmethod
def default_smtp_ssl():
@ -97,6 +73,15 @@ class SmtpServer(ModelSQL, ModelView):
def default_state():
return 'draft'
def get_uri(self):
option = 'smtp'
if self.smtp_tls:
option = 'smtp+tls'
elif self.smtp_ssl:
option = 'smtps'
# smtps://cuenta@dominio.com:miclave@mail.dominio.com:465
return option + '://' + self.smtp_email + ':' + self.smtp_password + '@' + self.smtp_server + ':' + str(self.smtp_port)
@classmethod
@ModelView.button
def draft(cls, servers):
@ -116,13 +101,14 @@ class SmtpServer(ModelSQL, ModelView):
def get_smtp_test(cls, servers):
"""Checks SMTP credentials and confirms if outgoing connection works"""
for server in servers:
try:
server.get_smtp_server()
except Exception, message:
cls.raise_user_error('smtp_test_details', message)
except:
cls.raise_user_error('smtp_error')
cls.raise_user_error('smtp_successful')
# try:
server = server.get_smtp_server()
print(server, 'server')
# except e:
# cls.raise_user_error('smtp_test_details', message)
# except:
# cls.raise_user_error('smtp_error')
# cls.raise_user_error('smtp_successful')
def get_smtp_server(self):
"""
@ -144,28 +130,28 @@ class SmtpServer(ModelSQL, ModelView):
return smtp_server
@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([
('model', '=', model),
], limit=1)
if not servers:
self.raise_user_error('server_model_not_found', model.name)
return servers[0].server
# @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([
# ('model', '=', model),
# ], limit=1)
# if not servers:
# self.raise_user_error('server_model_not_found', model.name)
# return servers[0].server
class SmtpServerModel(ModelSQL):
'SMTP Server - Model'
__name__ = 'smtp.server-ir.model'
_table = 'smtp_server_ir_model'
# class SmtpServerModel(ModelSQL):
# 'SMTP Server - Model'
# __name__ = 'smtp.server-ir.model'
# _table = 'smtp_server_ir_model'
server = fields.Many2One('smtp.server', 'Server', ondelete='CASCADE',
select=True, required=True)
model = fields.Many2One('ir.model', 'Model', ondelete='RESTRICT',
select=True, required=True)
# server = fields.Many2One('smtp.server', 'Server', ondelete='CASCADE',
# select=True, required=True)
# model = fields.Many2One('ir.model', 'Model', ondelete='RESTRICT',
# select=True, required=True)

View file

@ -18,20 +18,20 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<!-- smtp.server -->
<record model="ir.ui.view" id="server_view_form">
<field name="model">smtp.server</field>
<field name="model">smtp.connection.mail</field>
<field name="type">form</field>
<field name="name">smtp_server_form</field>
<field name="name">smtp_connection_mail_form</field>
</record>
<record model="ir.ui.view" id="server_view_tree">
<field name="model">smtp.server</field>
<field name="model">smtp.connection.mail</field>
<field name="type">tree</field>
<field name="name">smtp_server_tree</field>
<field name="name">smtp_connection_mail_tree</field>
</record>
<!-- Actions / Menu -->
<record model="ir.action.act_window" id="act_server_form">
<field name="name">Servers</field>
<field name="res_model">smtp.server</field>
<field name="name">Smtp Connection Users</field>
<field name="res_model">smtp.connection.mail</field>
</record>
<record model="ir.action.act_window.view" id="act_server_form_view1">
<field name="sequence" eval="10"/>
@ -67,7 +67,7 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
id="menu_server_form"/>
<!-- Access -->
<record model="ir.model.access" id="access_smtp_server">
<!-- <record model="ir.model.access" id="access_smtp_server">
<field name="model" search="[('model', '=', 'smtp.server')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
@ -104,6 +104,6 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
</record> -->
</data>
</tryton>

View file

@ -4,8 +4,8 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<form>
<label name="name"/>
<field name="name"/>
<label name="default"/>
<field name="default"/>
<label name="user"/>
<field name="user"/>
<notebook colspan="4">
<page string="Server" id="server">
<label name="smtp_server"/>
@ -16,12 +16,8 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<field name="smtp_ssl"/>
<label name="smtp_tls"/>
<field name="smtp_tls"/>
<label name="smtp_user"/>
<field name="smtp_user"/>
<label name="smtp_password"/>
<field name="smtp_password" widget="password"/>
<label name="smtp_use_email"/>
<field name="smtp_use_email"/>
<label name="smtp_email"/>
<field name="smtp_email"/>
<group col="6" colspan="6" id="server_buttons">
@ -32,8 +28,5 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<button name="get_smtp_test" string="Test Connection" icon="tryton-ok"/>
</group>
</page>
<page string="Models" id="model">
<field name="models"/>
</page>
</notebook>
</form>

View file

@ -2,8 +2,8 @@
<!-- 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. -->
<tree>
<field name="user"/>
<field name="name"/>
<field name="smtp_server"/>
<field name="smtp_user"/>
<field name="state"/>
</tree>