[MERGE] mergedlp:~openerp-dev/openobject-server/trunk-email-smtp-improvement-rha
bzr revid: hmo@tinyerp.com-20110331050935-9sj6nzmqvykygkd9
This commit is contained in:
commit
bd8a37054e
|
@ -1603,7 +1603,14 @@
|
|||
<field name="rate">691.3153</field>
|
||||
<field name="currency_id" ref="CRC"/>
|
||||
<field eval="time.strftime('%Y-01-01')" name="name"/>
|
||||
</record>
|
||||
</record>
|
||||
|
||||
<record id="ir_mail_server_localhost0" model="ir.mail_server">
|
||||
<field name="name">localhost</field>
|
||||
<field name="smtp_host">localhost</field>
|
||||
<field eval="25" name="smtp_port"/>
|
||||
<field eval="10" name="priority"/>
|
||||
</record>
|
||||
|
||||
<record id="MUR" model="res.currency">
|
||||
<field name="name">MUR</field>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
|
@ -15,7 +15,7 @@
|
|||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
@ -36,6 +36,7 @@ import ir_rule
|
|||
import wizard
|
||||
import ir_config_parameter
|
||||
import osv_memory_autovacuum
|
||||
import ir_mail_server
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -1942,5 +1942,77 @@
|
|||
<field name="args">()</field>
|
||||
</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="Smtp Server Configuration">
|
||||
<group colspan="4">
|
||||
<field name="name"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Configuration">
|
||||
<separator string="Server Information" colspan="4"/>
|
||||
<group colspan="4" col="8">
|
||||
<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"/>
|
||||
</group>
|
||||
|
||||
<separator string="User Information" colspan="4"/>
|
||||
<group col="6" colspan="4">
|
||||
<field name="smtp_user"/>
|
||||
<field name="smtp_pass" password="True"/>
|
||||
|
||||
</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>
|
||||
<field name="model">ir.mail_server</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="SMTP Server">
|
||||
<field name="name"/>
|
||||
<field name="smtp_host"/>
|
||||
<field name="priority"/>
|
||||
<button name="test_smtp_connection" type="object" string="Test Connection" icon="gtk-network"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_ir_mail_server_search" model="ir.ui.view">
|
||||
<field name="name">ir.mail.server.search</field>
|
||||
<field name="model">ir.mail_server</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Smtp Server">
|
||||
<field name="name"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_ir_mail_server_tree_all">
|
||||
<field name="name">Email Accounts</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="search_view_id" ref="view_ir_mail_server_search"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -162,7 +162,7 @@ class act_window(osv.osv):
|
|||
|
||||
def _invalid_model_msg(self, cr, uid, ids, context=None):
|
||||
return _('Invalid model name in the action definition.')
|
||||
|
||||
|
||||
_constraints = [
|
||||
(_check_model, _invalid_model_msg, ['res_model','src_model'])
|
||||
]
|
||||
|
@ -195,7 +195,7 @@ class act_window(osv.osv):
|
|||
if act.search_view_id:
|
||||
search_view_id = act.search_view_id.id
|
||||
else:
|
||||
res_view = self.pool.get('ir.ui.view').search(cr, uid,
|
||||
res_view = self.pool.get('ir.ui.view').search(cr, uid,
|
||||
[('model','=',act.res_model),('type','=','search'),
|
||||
('inherit_id','=',False)], context=context)
|
||||
if res_view:
|
||||
|
@ -631,7 +631,8 @@ class actions_server(osv.osv):
|
|||
subject = self.merge_message(cr, uid, action.subject, action, context)
|
||||
body = self.merge_message(cr, uid, action.message, action, context)
|
||||
|
||||
if tools.email_send(user, [address], subject, body, debug=False, subtype='html') == True:
|
||||
smtp_server_obj = self.pool.get('ir.mail_server')
|
||||
if smtp_server_obj.send_email(uid, user, [address], subject, body, debug=False, subtype='html', cr=cr) == True:
|
||||
logger.info('Email successfully sent to: %s', address)
|
||||
else:
|
||||
logger.warning('Failed to send email to: %s', address)
|
||||
|
|
|
@ -0,0 +1,329 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2011 Tiny SPRL (<http://tiny.be>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
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 import Encoders
|
||||
try:
|
||||
from html2text import html2text
|
||||
except ImportError:
|
||||
html2text = None
|
||||
|
||||
import openerp.loglevels as loglevels
|
||||
from tools import config
|
||||
from email.generator import Generator
|
||||
|
||||
# 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
|
||||
|
||||
_logger = logging.getLogger('tools')
|
||||
|
||||
priorities = {
|
||||
'1': '1 (Highest)',
|
||||
'2': '2 (High)',
|
||||
'3': '3 (Normal)',
|
||||
'4': '4 (Low)',
|
||||
'5': '5 (Lowest)',
|
||||
}
|
||||
|
||||
class ir_mail_server(osv.osv):
|
||||
"""
|
||||
mail server
|
||||
"""
|
||||
_name = "ir.mail_server"
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name',
|
||||
size=64, required=True,
|
||||
select=True,
|
||||
help="The Name is used as the Sender name along with the provided From Email, \
|
||||
unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
|
||||
),
|
||||
'smtp_host': fields.char('Server',
|
||||
size=120, required=True,
|
||||
help="Enter name of outgoing server, eg: smtp.yourdomain.com"),
|
||||
'smtp_port': fields.integer('SMTP Port',
|
||||
size=64, required=True,
|
||||
help="Enter port number, eg: 25 or 587"),
|
||||
'smtp_user': fields.char('User Name',
|
||||
size=120, required=False,
|
||||
help="Specify the username if your SMTP server requires authentication, "
|
||||
"otherwise leave it empty."),
|
||||
'smtp_pass': fields.char('Password',
|
||||
size=120,
|
||||
required=False),
|
||||
'smtp_tls':fields.boolean('TLS'),
|
||||
'smtp_ssl':fields.boolean('SSL/TLS'),
|
||||
'priority': fields.integer('Priority', help="If no specific server is \
|
||||
requested for a mail then the highest priority one is used"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'smtp_port': 25,
|
||||
'priority': 10,
|
||||
}
|
||||
|
||||
_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
|
||||
"""
|
||||
try:
|
||||
for smtp_server in self.browse(cr, uid, ids, context=context):
|
||||
smtp = self.connect_smtp_server(cr, uid, 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)
|
||||
try:
|
||||
smtp.quit()
|
||||
except Exception:
|
||||
# ignored, just a consequence of the previous exception
|
||||
pass
|
||||
except Exception, error:
|
||||
raise osv.except_osv(
|
||||
_("SMTP Connection: Test failed"),
|
||||
_("Reason: %s") % error
|
||||
)
|
||||
|
||||
raise osv.except_osv(_("SMTP Connection: Test Successfully!"), '')
|
||||
|
||||
def connect_smtp_server(self, cr, uid, server_host, server_port, user_name=None,
|
||||
user_password=None, ssl=False, tls=False, debug=False):
|
||||
"""
|
||||
Connect SMTP Server and returned the (SMTP) object
|
||||
"""
|
||||
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)
|
||||
|
||||
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 generate_tracking_message_id(self, openobject_id):
|
||||
"""Returns a string that can be used in the Message-ID RFC822 header field so we
|
||||
can track the replies related to a given object thanks to the "In-Reply-To" or
|
||||
"References" fields that Mail User Agents will set.
|
||||
"""
|
||||
return "<%s-openobject-%s@%s>" % (time.time(), openobject_id, socket.gethostname())
|
||||
|
||||
def send_email(self, cr, uid, smtp_from, email_to, message=None, subject=None, body=None, 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', smtp_server=None, smtp_port=None,
|
||||
ssl=False, smtp_user=None, smtp_password=None, id=None):
|
||||
|
||||
"""Send an email.
|
||||
"""
|
||||
if x_headers is None:
|
||||
x_headers = {}
|
||||
|
||||
if not (smtp_from or config['email_from']):
|
||||
raise ValueError("Sending an email requires either providing a sender "
|
||||
"address or having configured one")
|
||||
if not smtp_from: smtp_from = config.get('email_from', False)
|
||||
smtp_from = ustr(smtp_from).encode('utf-8')
|
||||
|
||||
if id:
|
||||
server = self.browse(cr, uid, id)
|
||||
smtp_server = server.smtp_host
|
||||
smtp_user = server.smtp_user
|
||||
smtp_password = server.smtp_pass
|
||||
smtp_port = server.smtp_port
|
||||
ssl = server.smtp_ssl
|
||||
elif not (id and smtp_server):
|
||||
server_ids = self.search(cr, uid, [], order='priority', limit=1)
|
||||
server = self.browse(cr, uid, server_ids[0])
|
||||
smtp_server = server.smtp_host
|
||||
smtp_user = server.smtp_user
|
||||
smtp_password = server.smtp_pass
|
||||
smtp_port = server.smtp_port
|
||||
ssl = server.smtp_ssl
|
||||
elif not id and smtp_server:
|
||||
smtp_server = smtp_server
|
||||
smtp_user = smtp_user
|
||||
smtp_password = smtp_password
|
||||
smtp_port = smtp_port
|
||||
ssl = ssl
|
||||
|
||||
class WriteToLogger(object):
|
||||
def __init__(self):
|
||||
self.logger = loglevels.Logger()
|
||||
|
||||
def write(self, s):
|
||||
self.logger.notifyChannel('email_send', loglevels.LOG_DEBUG, s)
|
||||
|
||||
#preparing the message
|
||||
if not message:
|
||||
if not email_cc: email_cc = []
|
||||
if not email_bcc: email_bcc = []
|
||||
if not body: body = u''
|
||||
email_body = ustr(body).encode('utf-8')
|
||||
email_text = MIMEText(email_body or '', _subtype=subtype, _charset='utf-8')
|
||||
msg = MIMEMultipart()
|
||||
|
||||
if not message_id and openobject_id:
|
||||
message_id = self.generate_tracking_message_id(openobject_id)
|
||||
else:
|
||||
message_id = Utils.make_msgid()
|
||||
|
||||
msg['Message-Id'] = message_id
|
||||
if references:
|
||||
msg['references'] = references
|
||||
msg['Subject'] = Header(ustr(subject), 'utf-8')
|
||||
msg['From'] = smtp_from
|
||||
|
||||
del msg['Reply-To']
|
||||
if reply_to:
|
||||
msg['Reply-To'] = reply_to
|
||||
else:
|
||||
msg['Reply-To'] = msg['From']
|
||||
|
||||
msg['To'] = COMMASPACE.join(email_to)
|
||||
|
||||
if email_cc:
|
||||
msg['Cc'] = COMMASPACE.join(email_cc)
|
||||
if email_bcc:
|
||||
msg['Bcc'] = COMMASPACE.join(email_bcc)
|
||||
|
||||
msg['X-Priority'] = priorities.get(priority, '3 (Normal)')
|
||||
msg['Date'] = formatdate(localtime=True)
|
||||
|
||||
# Add dynamic X Header
|
||||
for key, value in x_headers.iteritems():
|
||||
msg['%s' % key] = str(value)
|
||||
if html2text and sub_type == 'html':
|
||||
text = html2text(email_body.decode('utf-8')).encode('utf-8')
|
||||
alternative_part = MIMEMultipart(_subtype="alternative")
|
||||
alternative_part.attach(MIMEText(text, _charset='utf-8', _subtype='plain'))
|
||||
alternative_part.attach(email_text)
|
||||
msg.attach(alternative_part)
|
||||
else:
|
||||
msg.attach(email_text)
|
||||
|
||||
if attach:
|
||||
for (fname, fcontent) in attach:
|
||||
part = MIMEBase('application', "octet-stream")
|
||||
part.set_payload( fcontent )
|
||||
Encoders.encode_base64(part)
|
||||
part.add_header('Content-Disposition', 'attachment; filename="%s"' % (fname,))
|
||||
msg.attach(part)
|
||||
message = msg
|
||||
|
||||
try:
|
||||
smtp_server = smtp_server or config['smtp_server']
|
||||
|
||||
if smtp_server.startswith('maildir:/'):
|
||||
from mailbox import Maildir
|
||||
maildir_path = smtp_server[8:]
|
||||
mdir = Maildir(maildir_path,factory=None, create = True)
|
||||
mdir.add(message.as_string(True))
|
||||
return True
|
||||
|
||||
if debug:
|
||||
oldstderr = smtplib.stderr
|
||||
smtplib.stderr = WriteToLogger()
|
||||
|
||||
if not ssl:
|
||||
ssl = config.get('smtp_ssl', False)
|
||||
|
||||
smtp = self.connect_smtp_server(cr, uid, smtp_server, smtp_port,
|
||||
user_name=smtp_user, user_password=smtp_password, ssl=ssl, tls=True, debug=debug)
|
||||
try:
|
||||
smtp.sendmail(smtp_from, email_to, message.as_string())
|
||||
except Exception:
|
||||
_logger.error('could not deliver Email(s)', exc_info=True)
|
||||
return False
|
||||
finally:
|
||||
try:
|
||||
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)
|
||||
|
||||
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_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:
|
|
@ -74,5 +74,6 @@
|
|||
</record>
|
||||
<menuitem id="next_id_15" name="Parameters" parent="base.menu_config" groups="base.group_extended" />
|
||||
<menuitem action="ir_property_form" id="menu_ir_property_form_all" parent="base.next_id_15"/>
|
||||
<menuitem name="Email Accounts" id="menu_email_smtp_server_all" parent="base.next_id_15" action="base.action_ir_mail_server_tree_all" sequence="15"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -62,12 +62,11 @@ class partner_wizard_spam(osv.osv_memory):
|
|||
to = '"%s" <%s>' % (name, adr.email)
|
||||
#TODO: add some tests to check for invalid email addresses
|
||||
#CHECKME: maybe we should use res.partner/email_send
|
||||
tools.email_send(data.email_from,
|
||||
[to],
|
||||
data.subject,
|
||||
data.text,
|
||||
subtype=type_,
|
||||
openobject_id="res.partner-%s"%partner.id)
|
||||
smtp_server_obj = self.pool.get('ir.mail_server')
|
||||
smtp_server_obj.send_email(uid, data.email_from,
|
||||
[to], data.subject,
|
||||
data.text, subtype=type_,
|
||||
cr=cr)
|
||||
nbr += 1
|
||||
event_pool.create(cr, uid,
|
||||
{'name': 'Email(s) sent through mass mailing',
|
||||
|
|
|
@ -59,6 +59,7 @@ except ImportError:
|
|||
import openerp.loglevels as loglevels
|
||||
from config import config
|
||||
from lru import LRU
|
||||
import openerp.pooler as pooler
|
||||
|
||||
# get_encodings, ustr and exception_to_unicode were originally from tools.misc.
|
||||
# There are moved to loglevels until we refactor tools.
|
||||
|
@ -346,14 +347,6 @@ res_re = re.compile(r"\[([0-9]+)\]", re.UNICODE)
|
|||
command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE)
|
||||
reference_re = re.compile("<.*-openobject-(\\d+)@(.*)>", re.UNICODE)
|
||||
|
||||
priorities = {
|
||||
'1': '1 (Highest)',
|
||||
'2': '2 (High)',
|
||||
'3': '3 (Normal)',
|
||||
'4': '4 (Low)',
|
||||
'5': '5 (Lowest)',
|
||||
}
|
||||
|
||||
def html2plaintext(html, body_id=None, encoding='utf-8'):
|
||||
## (c) Fry-IT, www.fry-it.com, 2007
|
||||
## <peter@fry-it.com>
|
||||
|
@ -420,183 +413,27 @@ def html2plaintext(html, body_id=None, encoding='utf-8'):
|
|||
|
||||
return html
|
||||
|
||||
def generate_tracking_message_id(openobject_id):
|
||||
"""Returns a string that can be used in the Message-ID RFC822 header field so we
|
||||
can track the replies related to a given object thanks to the "In-Reply-To" or
|
||||
"References" fields that Mail User Agents will set.
|
||||
"""
|
||||
return "<%s-openobject-%s@%s>" % (time.time(), openobject_id, socket.gethostname())
|
||||
|
||||
def connect_smtp_server(server_host, server_port, user_name=None, user_password=None, ssl=False, tls=False, debug=False):
|
||||
"""
|
||||
Connect SMTP Server and returned the (SMTP) object
|
||||
"""
|
||||
smtp_server = None
|
||||
try:
|
||||
if ssl:
|
||||
# In Python 2.6
|
||||
smtp_server = smtplib.SMTP_SSL(server_host, server_port)
|
||||
def email_send(smtp_from, smtp_to_list, message, ssl=False, debug=False, smtp_server=None, smtp_port=None,
|
||||
smtp_user=None, smtp_password=None, cr=None, uid=None):
|
||||
if not cr:
|
||||
db_name = getattr(threading.currentThread(), 'dbname', None)
|
||||
if db_name:
|
||||
cr = pooler.get_db_only(db_name).cursor()
|
||||
else:
|
||||
smtp_server = smtplib.SMTP(server_host, server_port)
|
||||
|
||||
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 _email_send(smtp_from, smtp_to_list, message, ssl=False, debug=False,
|
||||
smtp_server=None, smtp_port=None, smtp_user=None, smtp_password=None):
|
||||
"""Low-level method to send directly a Message through the configured smtp server.
|
||||
:param smtp_from: RFC-822 envelope FROM (not displayed to recipient)
|
||||
:param smtp_to_list: RFC-822 envelope RCPT_TOs (not displayed to recipient)
|
||||
:param message: an email.message.Message to send
|
||||
:param debug: True if messages should be output to stderr before being sent,
|
||||
and smtplib.SMTP put into debug mode.
|
||||
:return: True if the mail was delivered successfully to the smtp,
|
||||
else False (+ exception logged)
|
||||
"""
|
||||
class WriteToLogger(object):
|
||||
def __init__(self):
|
||||
self.logger = loglevels.Logger()
|
||||
|
||||
def write(self, s):
|
||||
self.logger.notifyChannel('email_send', loglevels.LOG_DEBUG, s)
|
||||
|
||||
raise Exception("No database cursor found!")
|
||||
if not uid:
|
||||
uid = 1
|
||||
try:
|
||||
smtp_server = smtp_server or config['smtp_server']
|
||||
|
||||
if smtp_server.startswith('maildir:/'):
|
||||
from mailbox import Maildir
|
||||
maildir_path = smtp_server[8:]
|
||||
mdir = Maildir(maildir_path,factory=None, create = True)
|
||||
mdir.add(message.as_string(True))
|
||||
return True
|
||||
|
||||
if debug:
|
||||
oldstderr = smtplib.stderr
|
||||
smtplib.stderr = WriteToLogger()
|
||||
|
||||
if not ssl: ssl = config.get('smtp_ssl', False)
|
||||
smtp = connect_smtp_server(smtp_server, smtp_port, smtp_user, smtp_password, ssl=ssl, tls=True, debug=debug)
|
||||
try:
|
||||
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:
|
||||
try:
|
||||
smtp.quit()
|
||||
except Exception:
|
||||
# ignored, just a consequence of the previous exception
|
||||
pass
|
||||
|
||||
if debug:
|
||||
smtplib.stderr = oldstderr
|
||||
server_pool = pooler.get_pool(cr.dbname).get('ir.mail_server')
|
||||
server_pool.send_email(cr, uid, smtp_from, smtp_to_list, message=message,
|
||||
ssl=ssl,debug=debug, smtp_server=smtp_server, smtp_port=smtp_port,
|
||||
smtp_user=smtp_user, smtp_password=smtp_password)
|
||||
except Exception:
|
||||
_logger.error('Error on Send Emails Services', exc_info=True)
|
||||
return False
|
||||
|
||||
finally:
|
||||
cr.close()
|
||||
return True
|
||||
|
||||
|
||||
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',
|
||||
smtp_server=None, smtp_port=None, ssl=False, smtp_user=None, smtp_password=None):
|
||||
|
||||
"""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.
|
||||
"""
|
||||
if x_headers is None:
|
||||
x_headers = {}
|
||||
|
||||
|
||||
if not (email_from or config['email_from']):
|
||||
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 = ustr(email_from).encode('utf-8')
|
||||
|
||||
if not email_cc: email_cc = []
|
||||
if not email_bcc: email_bcc = []
|
||||
if not body: body = u''
|
||||
|
||||
email_body = ustr(body).encode('utf-8')
|
||||
email_text = MIMEText(email_body or '',_subtype=subtype,_charset='utf-8')
|
||||
msg = MIMEMultipart()
|
||||
|
||||
if not message_id and openobject_id:
|
||||
message_id = generate_tracking_message_id(openobject_id)
|
||||
else:
|
||||
message_id = Utils.make_msgid()
|
||||
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']
|
||||
if reply_to:
|
||||
msg['Reply-To'] = reply_to
|
||||
else:
|
||||
msg['Reply-To'] = msg['From']
|
||||
msg['To'] = COMMASPACE.join(email_to)
|
||||
if email_cc:
|
||||
msg['Cc'] = COMMASPACE.join(email_cc)
|
||||
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
|
||||
for key, value in x_headers.iteritems():
|
||||
msg['%s' % key] = str(value)
|
||||
|
||||
if html2text and subtype == 'html':
|
||||
text = html2text(email_body.decode('utf-8')).encode('utf-8')
|
||||
alternative_part = MIMEMultipart(_subtype="alternative")
|
||||
alternative_part.attach(MIMEText(text, _charset='utf-8', _subtype='plain'))
|
||||
alternative_part.attach(email_text)
|
||||
msg.attach(alternative_part)
|
||||
else:
|
||||
msg.attach(email_text)
|
||||
|
||||
if attach:
|
||||
for (fname,fcontent) in attach:
|
||||
part = MIMEBase('application', "octet-stream")
|
||||
part.set_payload( fcontent )
|
||||
Encoders.encode_base64(part)
|
||||
part.add_header('Content-Disposition', 'attachment; filename="%s"' % (fname,))
|
||||
msg.attach(part)
|
||||
|
||||
res = _email_send(email_from, flatten([email_to, email_cc, email_bcc]), msg, ssl=ssl, debug=debug,
|
||||
smtp_server=smtp_server, smtp_port=smtp_port, smtp_user=smtp_user, smtp_password=smtp_password)
|
||||
if res:
|
||||
return message_id
|
||||
return False
|
||||
|
||||
#----------------------------------------------------------
|
||||
# SMS
|
||||
#----------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue