mirror of
https://bitbucket.org/presik/trytonpsk-smtp.git
synced 2023-12-14 05:22:56 +01:00
confirguration smtp client
This commit is contained in:
parent
b665e950ea
commit
a9664f93dc
|
@ -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
141
email_.py
Normal 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
|
22
setup.py
22
setup.py
|
@ -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
102
smtp.py
|
@ -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)
|
||||
|
|
16
smtp.xml
16
smtp.xml
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in a new issue