[IMP] ir.mail_server: another round of cleanup

bzr revid: odo@openerp.com-20110715002809-ryvm27wi4ktv8v49
This commit is contained in:
Olivier Dony 2011-07-15 02:28:09 +02:00
parent c122a09608
commit 3080ba3452
4 changed files with 215 additions and 249 deletions

View File

@ -1943,51 +1943,48 @@
</record>
<!-- ir.mail.server -->
<record model="ir.ui.view" id="ir_mail_server_form">
<field name="name">ir.mail.server.form</field>
<field name="model">ir.mail_server</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Outgoing Mail Server">
<form string="Outgoing Mail Servers">
<group colspan="4">
<field name="name"/>
<field name="sequence"/>
</group>
<notebook colspan="4">
<page string="Configuration">
<separator string="Server Information" colspan="4"/>
<group colspan="4" col="8">
<group col="4" colspan="2">
<separator string="Connection Information" colspan="4"/>
<field name="smtp_host"/>
<field name="smtp_port"/>
<field name="smtp_ssl" on_change="on_change_ssl(smtp_ssl)"/>
<field name="smtp_tls" on_change="on_change_tls(smtp_tls)"/>
<field name="priority"/>
<field name="smtp_encryption" on_change="on_change_encryption(smtp_encryption)"/>
<field name="smtp_debug"/>
</group>
<separator string="User Information" colspan="4"/>
<group col="6" colspan="4">
<group col="2" colspan="2">
<separator string="Authentication Information" colspan="2"/>
<field name="smtp_user"/>
<field name="smtp_pass" password="True"/>
<button name="test_smtp_connection" type="object" string="Test Connection" icon="gtk-network" colspan="2"/>
</group>
<separator string="" colspan="4"/>
<label string="" colspan="2"/>
<button name="test_smtp_connection" type="object" string="Test Connection" icon="gtk-network" colspan="2"/>
</page>
</notebook>
</form>
</field>
</record>
<record model="ir.ui.view" id="ir_mail_server_tree">
<field name="name">ir.mail.server.tree</field>
<record model="ir.ui.view" id="ir_mail_server_list">
<field name="name">ir.mail.server.list</field>
<field name="model">ir.mail_server</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Outgoing Mail Server">
<field name="priority"/>
<tree string="Outgoing Mail Servers">
<field name="sequence"/>
<field name="name"/>
<field name="smtp_host"/>
<field name="smtp_user"/>
<field name="smtp_encryption"/>
</tree>
</field>
</record>
@ -1997,22 +1994,24 @@
<field name="model">ir.mail_server</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Outgoing Mail Server">
<search string="Outgoing Mail Servers">
<field name="name"/>
<field name="smtp_host"/>
<field name="smtp_user"/>
<field name="smtp_encryption"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_ir_mail_server_tree_all">
<record model="ir.actions.act_window" id="action_ir_mail_server_list">
<field name="name">Outgoing Mail Servers</field>
<field name="res_model">ir.mail_server</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="ir_mail_server_tree" />
<field name="context">{'group_by': [], 'search_default_draft': 1, 'search_default_my': 1}</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="ir_mail_server_list" />
<field name="search_view_id" ref="view_ir_mail_server_search"/>
</record>
<menuitem id="next_id_15" name="Parameters" parent="base.menu_config" groups="base.group_extended" />
<menuitem id="menu_email_smtp_server_all" parent="base.next_id_15" action="base.action_ir_mail_server_tree_all" sequence="15"/>
<menuitem id="menu_mail_servers" parent="base.next_id_15" action="action_ir_mail_server_list" sequence="15"/>
</data>
</openerp>

View File

@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 Tiny SPRL (<http://tiny.be>)
# Copyright (C) 2011 OpenERP S.A (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -19,170 +19,143 @@
#
##############################################################################
from osv import osv
from osv import fields
from tools.translate import _
import tools
from tools import ustr
from tools import config
import netsvc
import base64
import subprocess
import logging
import smtplib
import socket
import sys
import time
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email.Header import Header
from email.Utils import formatdate, COMMASPACE
from email import Utils
from email.Utils import formatdate, make_msgid, COMMASPACE
from email import Encoders
try:
from html2text import html2text
except ImportError:
html2text = None
import logging
import smtplib
import openerp.loglevels as loglevels
from tools import config
from email.generator import Generator
from osv import osv
from osv import fields
from tools.translate import _
import tools
# get_encodings, ustr and exception_to_unicode were originally from tools.misc.
# There are moved to loglevels until we refactor tools.
from openerp.loglevels import get_encodings, ustr, exception_to_unicode
# ustr was originally from tools.misc.
# it is moved to loglevels until we refactor tools.
from openerp.loglevels import ustr
_logger = logging.getLogger('tools')
priorities = {
'1': '1 (Highest)',
'2': '2 (High)',
'3': '3 (Normal)',
'4': '4 (Low)',
'5': '5 (Lowest)',
}
_logger = logging.getLogger('ir.mail_server')
class MailDeliveryException(osv.except_osv):
"""Specific exception subclass for mail delivery errors"""
def __init__(self, name, value, exc_type='warning'):
super(MailDeliveryException, self).__init__(name, value, exc_type=exc_type)
class WriteToLogger(object):
"""debugging helper: behave as a fd and pipe to DEBUG logger"""
def __init__(self, logger):
self.logger = logger
def write(self, s):
self.logger.debug(s)
class ir_mail_server(osv.osv):
"""
mail server
"""
"""Represents an SMTP server, able to send outgoing e-mails, with SSL and TLS capabilities."""
_name = "ir.mail_server"
_columns = {
'name': fields.char('Name',
size=64, required=True,
select=True,
),
'smtp_host': fields.char('Server',
size=120, required=True,
help="Hostname or IP of SMTP server"),
'smtp_port': fields.integer('SMTP Port',
size=64, required=True,
help="SMTP Port of SMPT server"),
'smtp_user': fields.char('User Name',
size=120, required=False,
help="Username for SMTP authentication"),
'smtp_pass': fields.char('Password',
size=120,
required=False, help="Password for SMTP authentication"),
'smtp_tls': fields.boolean('TLS', help="If True, TLS encryption will be requested at \
beginning of SMTP transactions. \nDo not use if SSL is \
enabled, or if the server does not support it."),
'smtp_ssl':fields.boolean('SSL/TLS', readonly='SMTP_SSL' not in smtplib.__all__, help="If True, SMTPS (Secure SMTP over SSL encryption) will be used. \
When selected, change smtp_port to 465. \
\nDo not use with TLS or if the server does not support it. \
%s" %('SMTP_SSL' not in smtplib.__all__ and '\nNote: This is a Readonly. You should Install Python2.6 if need Secure SMTP' or '')),
'priority': fields.integer('Priority', help="If no specific \
server is requested for a mail, the highest priority one \
is used. Default priority is 10"),
'name': fields.char('Name', size=64, required=True, select=True),
'smtp_host': fields.char('Server Name', size=128, required=True, help="Hostname or IP of SMTP server"),
'smtp_port': fields.integer('SMTP Port', size=5, required=True, help="SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases."),
'smtp_user': fields.char('Username', size=64, help="Optional username for SMTP authentication"),
'smtp_pass': fields.char('Password', size=64, help="Optional password for SMTP authentication"),
'smtp_encryption': fields.selection([('none','None'),
('starttls','TLS (STARTTLS)'),
('ssl','SSL/TLS')],
string='Connection Security',
help="Choose the connection encryption scheme:\n"
"- None: SMTP sessions are done in cleartext.\n"
"- TLS (STARTTLS): TLS encryption will be requested at start of cleartext SMTP session (Recommended)\n"
"- SSL/TLS: Uses Secure SMTP over SSL tunnel, through dedicated SMTP/SSL port (default: 465)"),
'smtp_debug': fields.boolean('Debugging', help="If checked, the full output of SMTP sessions will "
"be written to the server log (may include confidential info)"),
'sequence': fields.integer('Priority', help="When no specific mail server is requested for a mail, the highest priority one "
"is used. Default priority is 10 (smaller number = higher priority)"),
}
_defaults = {
'smtp_port': 25,
'priority': 10,
'sequence': 10,
'smtp_encryption': 'none',
}
_sql_constraints = [
]
def name_get(self, cr, uid, ids, context=None):
return [(a["id"], "(%s)" % (a['name'])) for a in self.read(cr, uid, ids, ['name'], context=context)]
def test_smtp_connection(self, cr, uid, ids, context=None):
"""
Test SMTP connection works
"""
for smtp_server in self.browse(cr, uid, ids, context=context):
smtp = False
try:
smtp = self.connect_smtp_server(smtp_server.smtp_host,
smtp = self.connect(smtp_server.smtp_host,
smtp_server.smtp_port, user_name=smtp_server.smtp_user,
user_password=smtp_server.smtp_pass, ssl=smtp_server.smtp_ssl,
tls=smtp_server.smtp_tls, debug=False)
except Exception, error:
raise osv.except_osv(
_("SMTP Connection: Test failed"),
_("Reason: %s") % error )
user_password=smtp_server.smtp_pass, encryption=smtp_server.smtp_encryption,
debug=smtp_server.smtp_debug)
except Exception, e:
raise osv.except_osv(_("Connection test failed!"), _("Here is we got instead: %s") % e)
finally:
try:
if smtp:smtp.quit()
if smtp: smtp.quit()
except Exception:
# ignored, just a consequence of the previous exception
pass
raise osv.except_osv(_("SMTP Connection: Test Successfully!"), '')
raise osv.except_osv(_("Connection test succeeded!"), _("Everything seems properly set up!"))
def connect_smtp_server(self, server_host, server_port, user_name=None,
user_password=None, ssl=False, tls=False, debug=False):
def connect(self, host, port, user=None, password=None, encryption=False, debug=False):
"""Returns a new SMTP connection to the give SMTP server, authenticated
with ``user`` and ``password`` if provided, and encrypted as requested
by the ``encryption`` parameter.
:param host: host or IP of SMTP server to connect to
:param int port: SMTP port to connect to
:param user: optional username to authenticate with
:param password: optional password to authenticate with
:param string encryption: optional: ``'ssl'`` | ``'starttls'``
:param bool debug: toggle debugging of SMTP sessions (all i/o
will be output in logs)
"""
Connect SMTP Server and returned the (SMTP) object
if encryption == 'ssl':
if not 'SMTP_SSL' in smtplib.__all__:
raise osv.except_osv(
_("SMTP-over-SSL mode unavailable"),
_("Your OpenERP Server does not support SMTP-over-SSL. You could use STARTTLS instead."
"If SSL is needed, an upgrade to Python 2.6 on the server-side should do the trick."))
connection = smtplib.SMTP_SSL(host, port)
else:
connection = smtplib.SMTP(host, port)
connection.set_debuglevel(debug)
if encryption == 'starttls':
# starttls() will perform ehlo if needed first
connection.starttls()
# force load/refresh feature list
connection.ehlo()
if user:
# Attempt authentication - will raise if AUTH service not supported
connection.login(user, password)
return connection
def build_email(self, email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
attachments=None, message_id=None, references=None, openobject_id=False, subtype='plain', headers=None):
"""Constructs an email.message.Message object based on the keyword arguments passed, returns it.
:param body: email body, according to the ``subtype`` (by default, plaintext). If html subtype is used,
the message will be automatically converted to plaintext and wrapped in multipart/alternative.
:param reply_to: optional value of Reply-To header
:param email_cc: optional list of string values for CC header (to be joined with commas)
:param email_bcc: optional list of string values for BCC header (to be joined with commas)
:param attachments: list of (filename,filecontent) pairs, where filecontent
"""
smtp_server = None
try:
if ssl:
# In Python 2.6
smtp_server = smtplib.SMTP_SSL(server_host, server_port)
else:
smtp_server = smtplib.SMTP(server_host, server_port)
email_from = email_from or tools.config.get('email_from')
assert email_from, "email_from is mandatory"
email_from = ustr(email_from).encode('utf-8') # force to 8-bit utf-8
smtp_server.set_debuglevel(int(bool(debug))) # 0 or 1
if tls:
smtp_server.ehlo()
smtp_server.starttls()
smtp_server.ehlo()
#smtp_server.connect(server_host, server_port)
if smtp_server.has_extn('AUTH') or user_name or user_password:
smtp_server.login(user_name, user_password)
except Exception, error:
_logger.error('Could not connect to smtp server : %s' %(error), exc_info=True)
raise error
return smtp_server
def pack_message(self, cr, uid, email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
attach=None, message_id=None, references=None, openobject_id=False, subtype='plain', x_headers=None, priority='3'):
"""
Pack all message attributes into one object.
Return email.message.Message object after packed all email attribure.
"""
if not (email_from or config.get('email_from', False)):
raise ValueError("Sending an email requires either providing a sender "
"address or having configured one")
if not email_from: email_from = config.get('email_from', False)
email_from = tools.ustr(email_from).encode('utf-8')
if x_headers is None:
x_headers = {}
if headers is None:
headers = {}
if not email_cc: email_cc = []
if not email_bcc: email_bcc = []
@ -192,13 +165,14 @@ When selected, change smtp_port to 465. \
email_text = MIMEText(email_body or '', _subtype=subtype,_charset='utf-8')
msg = MIMEMultipart()
if not message_id and openobject_id:
message_id = tools.generate_tracking_message_id(openobject_id)
else:
message_id = Utils.make_msgid()
if not message_id:
if openobject_id:
message_id = tools.generate_tracking_message_id(openobject_id)
else:
message_id = make_msgid()
msg['Message-Id'] = message_id
if references:
msg['references'] = references
msg['Message-Id'] = message_id
msg['Subject'] = Header(ustr(subject), 'utf-8')
msg['From'] = email_from
del msg['Reply-To']
@ -212,14 +186,12 @@ When selected, change smtp_port to 465. \
if email_bcc:
msg['Bcc'] = COMMASPACE.join(email_bcc)
msg['Date'] = formatdate(localtime=True)
msg['X-Priority'] = priorities.get(priority, '3 (Normal)')
# Add dynamic X Header
# Custom headers may override normal headers or provide additional ones
for key, value in x_headers.iteritems():
msg['%s' % key] = str(value)
if html2text and subtype == 'html':
# Always provide alternative text body if possible.
text = tools.html2text(email_body.decode('utf-8')).encode('utf-8')
alternative_part = MIMEMultipart(_subtype="alternative")
alternative_part.attach(MIMEText(text, _charset='utf-8', _subtype='plain'))
@ -228,30 +200,43 @@ When selected, change smtp_port to 465. \
else:
msg.attach(email_text)
if attach:
for (fname, fcontent) in attach:
if attachments:
for (fname, fcontent) in attachments:
part = MIMEBase('application', "octet-stream")
part.set_payload( fcontent )
part.set_payload(fcontent)
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % (fname,))
msg.attach(part)
return msg
def send_email(self, cr, uid, message,
mail_server_id=None, smtp_server=None, smtp_port=None,
smtp_user=None, smtp_password=None, ssl=False, tls=True, debug=False):
def send_email(self, cr, uid, message, mail_server_id=None, smtp_server=None, smtp_port=None,
smtp_user=None, smtp_password=None, smtp_encryption='none', smtp_debug=False):
"""Sends an email directly (no queuing).
"""Send an email.
@message : The Object of 'email.message.Message' Class
If the mail_server_id is provided, send using this mail server, ignoring other smtp_* arguments.
If mail_server_id == None and smtp_server == None, use the default mail server (highest priority).
If mail_server_id == None and smtp_server is not None, use the provided smtp_* arguments.
Return messageID of message if Successfully sent Email otherwise return False
No retries are done, the caller should handle MailDeliveryException in order to ensure that
the mail is never lost.
If the mail_server_id is provided, sends using this mail server, ignoring other smtp_* arguments.
If mail_server_id is None and smtp_server is None, use the default mail server (highest priority).
If mail_server_id is None and smtp_server is not None, use the provided smtp_* arguments.
If both mail_server_id and smtp_server are None, look for an 'smtp_server' value in server config,
and fails if not found.
:param message: the email.message.Message to send
:param mail_server_id: optional id of ir.mail_server to use for sending. overrides other smtp_* arguments.
:param smtp_server: optional hostname of SMTP server to use
:param smtp_encryption: one of 'none', 'starttls' or 'ssl' (see ir.mail_server fields for explanation)
:param smtp_port: optional SMTP port, if mail_server_id is not passed
:param smtp_user: optional SMTP user, if mail_server_id is not passed
:param smtp_password: optional SMTP password to use, if mail_server_id is not passed
:param smtp_debug: optional SMTP debug flag, if mail_server_id is not passed
:param debug: whether to turn on the SMTP level debugging, output to DEBUG log level
:return: the Message-ID of the message that was just sent, if successfully sent, otherwise raises
MailDeliveryException and logs root cause.
"""
smtp_from = message['From']
if not smtp_from:
raise ValueError("Sending an email requires either providing a sender "
"address or having configured one")
raise ValueError("Sending an email requires either providing a sender address or having configured one")
email_to = message['To']
email_cc = message['Cc']
@ -259,31 +244,37 @@ When selected, change smtp_port to 465. \
smtp_to_list = tools.flatten([email_to, email_cc, email_bcc])
# Get SMTP Server Details from Mail Server
mail_server = False
mail_server = None
if mail_server_id:
mail_server = self.browse(cr, uid, mail_server_id)
elif not (mail_server_id and smtp_server):
mail_server_ids = self.search(cr, uid, [], order='priority', limit=1)
mail_server = self.browse(cr, uid, mail_server_ids[0])
elif not smtp_server:
mail_server_ids = self.search(cr, uid, [], order='sequence', limit=1)
if mail_server_ids:
mail_server = self.browse(cr, uid, mail_server_ids[0])
else:
# we were passed an explicit smtp_server or nothing at all
smtp_server = smtp_server or tools.config.get('smtp_server')
smtp_port = tools.config.get('smtp_port', 25) if smtp_port is None else smtp_port
smtp_user = smtp_user or tools.config.get('smtp_user')
smtp_password = smtp_password or tools.config.get('smtp_password')
if mail_server:
smtp_server = mail_server.smtp_host
smtp_user = mail_server.smtp_user
smtp_password = mail_server.smtp_pass
smtp_port = mail_server.smtp_port
ssl = mail_server.smtp_ssl
tls = mail_server.smtp_tls
smtp_encryption = mail_server.smtp_encryption
smtp_debug = smtp_debug or mail_server.smtp_debug
class WriteToLogger(object):
def __init__(self):
self.logger = loglevels.Logger()
def write(self, s):
self.logger.notifyChannel('email_send', loglevels.LOG_DEBUG, s)
if not smtp_server:
raise osv.except_osv(
_("Missing SMTP Server"),
_("Please define at least one SMTP server, or provide the SMTP parameters explicitly."))
try:
message_id = message['Message-Id']
smtp_server = smtp_server or config.get('smtp_server')
smtp_server = smtp_server
# Add email in Maildir if smtp_server contains maildir.
if smtp_server.startswith('maildir:/'):
@ -293,52 +284,35 @@ When selected, change smtp_port to 465. \
mdir.add(message.as_string(True))
return message_id
if debug:
oldstderr = smtplib.stderr
smtplib.stderr = WriteToLogger()
# Open Connection of SMTP Server
smtp = self.connect_smtp_server(
smtp_server,
smtp_port or config.get('smtp_port', 25),
user_name=smtp_user or config.get('smtp_user', False),
user_password=smtp_password or config.get('smtp_password', False),
ssl=ssl or config.get('smtp_ssl', False),
tls=tls, debug=debug)
try:
# Send Email
if smtp_debug:
oldstderr = smtplib.stderr
smtplib.stderr = WriteToLogger(_logger)
smtp = self.connect(smtp_server, smtp_port, smtp_user, smtp_password, smtp_encryption, smtp_debug)
smtp.sendmail(smtp_from, smtp_to_list, message.as_string())
except Exception:
_logger.error('could not deliver Email(s)', exc_info=True)
return False
finally:
if debug:
smtplib.stderr = oldstderr
try:
# Close Connection of SMTP Server
smtp.quit()
except Exception:
# ignored, just a consequence of the previous exception
pass
if debug:
smtplib.stderr = oldstderr
except Exception:
_logger.error('Error on Send Emails Services', exc_info=True)
except Exception, e:
msg = _("Mail delivery failed via SMTP server '%s'.\n%s: %s") % (smtp_server, e.__class__.__name__, e)
_logger.exception(msg)
raise MailDeliveryException(_("Mail delivery failed"), msg)
return message_id
def on_change_ssl(self, cr, uid, ids, smtp_ssl):
smtp_port = 0
if smtp_ssl:
smtp_port = 465
return {'value': {'smtp_ssl':smtp_ssl, 'smtp_tls':False, 'smtp_port':smtp_port}}
def on_change_encryption(self, cr, uid, ids, smtp_encryption):
if smtp_encryption == 'ssl':
result = {'value': {'smtp_port': 465}}
if not 'SMTP_SSL' in smtplib.__all__:
result['warning'] = {'title': _('Warning'),
'message': _('Your server does not seem to support SSL, you may want to try STARTTLS instead')}
else:
result = {'value': {'smtp_port': 25}}
return result
def on_change_tls(self, cr, uid, ids, smtp_tls):
smtp_port = 0
if smtp_tls:
smtp_port = 0
return {'value': {'smtp_tls':smtp_tls, 'smtp_ssl':False, 'smtp_port':smtp_port}}
ir_mail_server()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -125,3 +125,4 @@
"access_res_widget_user","res.widget.user","model_res_widget",,1,0,0,0
"access_res_log_all","res.log","model_res_log",,1,1,1,1
"access_ir_config_parameter","ir_config_parameter","model_ir_config_parameter",,1,0,0,0
"access_ir_mail_server_all","ir_mail_server","model_ir_mail_server",,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
125 access_res_widget_user res.widget.user model_res_widget 1 0 0 0
126 access_res_log_all res.log model_res_log 1 1 1 1
127 access_ir_config_parameter ir_config_parameter model_ir_config_parameter 1 0 0 0
128 access_ir_mail_server_all ir_mail_server model_ir_mail_server 1 0 0 0

View File

@ -422,18 +422,15 @@ def generate_tracking_message_id(openobject_id):
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False,
attach=None, message_id=None, references=None, openobject_id=False, debug=False, subtype='plain', x_headers=None, priority='3',
attachments=None, message_id=None, references=None, openobject_id=False, debug=False, subtype='plain', headers=None,
smtp_server=None, smtp_port=None, ssl=False, smtp_user=None, smtp_password=None, cr=None, uid=None):
"""Low-level function for sending an email (deprecated).
"""Send an email.
Arguments:
`email_from`: A string used to fill the `From` header, if falsy,
config['email_from'] is used instead. Also used for
the `Reply-To` header if `reply_to` is not provided
`email_to`: a sequence of addresses to send the mail to.
:deprecate: since OpenERP 6.1, please use ir.mail_server.send_email() instead.
:param email_from: A string used to fill the `From` header, if falsy,
config['email_from'] is used instead. Also used for
the `Reply-To` header if `reply_to` is not provided
:param email_to: a sequence of addresses to send the mail to.
"""
# If not cr, get cr from current thread database
@ -442,26 +439,21 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
if db_name:
cr = pooler.get_db_only(db_name).cursor()
else:
raise Exception("No database cursor found!")
# if not uid, take uid as a root
#TOFIX: uid should taken from current thread
if not uid:
uid = 1
mail_server_pool = pooler.get_pool(cr.dbname).get('ir.mail_server')
# Pack Message into MIME Object
msg = mail_server_pool.pack_message(cr, uid, email_from, email_to, subject, body, email_cc, email_bcc, reply_to,
attach, message_id, references, openobject_id, debug, subtype, x_headers, priority)
raise Exception("No database cursor found, please pass one explicitly")
# Send Email
res = False
try:
res = mail_server_pool.send_email(cr, uid, msg,
mail_server_pool = pooler.get_pool(cr.dbname).get('ir.mail_server')
res = False
# Pack Message into MIME Object
email_msg = mail_server_pool.build_email(email_from, email_to, subject, body, email_cc, email_bcc, reply_to,
attachments, message_id, references, openobject_id, subtype, headers=headers)
res = mail_server_pool.send_email(cr, uid or 1, email_msg, mail_server_id=None,
smtp_server=smtp_server, smtp_port=smtp_port, smtp_user=smtp_user, smtp_password=smtp_password,
ssl=ssl, tls=True, debug=debug)
smtp_encryption=('ssl' if ssl else None), debug=debug)
except Exception:
_log.exception("tools.email_send failed to deliver email")
return False
finally:
cr.close()