[IMP] : improvement in send_email

bzr revid: rha@tinyerp.com-20110323130601-hryhc1fh8dakr2o7
This commit is contained in:
Rifakat Haradwala (Open ERP) 2011-03-23 18:36:01 +05:30
parent 6c699c5082
commit b0d6ac3915
3 changed files with 36 additions and 174 deletions

View File

@ -1961,6 +1961,7 @@
<field name="smtp_port"/>
<field name="smtp_ssl"/>
<field name="smtp_tls"/>
<field name="priority"/>
</group>
<separator string="User Information" colspan="4"/>
@ -1986,6 +1987,7 @@
<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>

View File

@ -128,8 +128,8 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
"""
try:
for smtp_server in self.browse(cr, uid, ids, context=context):
smtp = self.connect_smtp_server(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)
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:
@ -143,7 +143,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
raise osv.except_osv(_("SMTP Connection: Test Successfully!"), '')
def connect_smtp_server(server_host, server_port, user_name=None, user_password=None, ssl=False, tls=False, debug=False):
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
"""
@ -174,7 +174,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
raise error
return smtp_server
def _email_send(smtp_from, smtp_to_list, message, ssl=False, debug=False,
def _email_send(self, cr, uid, 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)
@ -185,7 +185,6 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
:return: True if the mail was delivered successfully to the smtp,
else False (+ exception logged)
"""
print '_email::'
class WriteToLogger(object):
def __init__(self):
self.logger = loglevels.Logger()
@ -207,8 +206,10 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
oldstderr = smtplib.stderr
smtplib.stderr = WriteToLogger()
if not ssl: ssl = config.get('smtp_ssl', False)
smtp = self.connect_smtp_server(smtp_server, smtp_port, smtp_user, smtp_password, ssl=ssl, tls=True, debug=debug)
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, smtp_to_list, message.as_string())
except Exception:
@ -239,9 +240,16 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
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:
smtp_server = self.browse(cr, uid, id)
if not (id and smtp_server):
server = self.search(cr, uid, [], order='priority', limit=1)
smtp_server = self.browse(cr, uid, server[0])
if not message: message = u''
email_body = ustr(message).encode('utf-8')
email_text = MIMEText(email_body or '',_charset='utf-8')
msg = MIMEMultipart()
@ -265,7 +273,9 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
msg.attach(alternative_part)
else:
msg.attach(email_text)
res = self._email_send(smtp_from, smtp_to_list, msg)
res = self._email_send(cr, uid, smtp_from, smtp_to_list, msg, smtp_server=smtp_server.smtp_host,
smtp_user=smtp_server.smtp_user, smtp_password=smtp_server.smtp_pass, smtp_port=smtp_server.smtp_port)
if res:
return message_id
return False

View File

@ -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.
@ -427,176 +428,25 @@ def generate_tracking_message_id(openobject_id):
"""
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
def email_send(smtp_from, smtp_to_list, subject, message, ssl=False, debug=False, smtp_server=None, smtp_port=None,
smtp_user=None, smtp_password=None, cr=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 _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)
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
if not cr:
db_name = getattr(threading.currentThread(), 'dbname', None)
if db_name:
cr = pooler.get_db_only(dbname).cursor()
server_pool = pooler.get_pool(cr.dbname).get('ir.mail_server')
server_pool.send_email(cr, uid, smtp_from, smtp_to_list, message,
ssl=ssl,debug=debug, smtp_server=smtp_server, smtp_port=smtp_port,
smtp_user=smtp_user, smtp_password=smtp_password)
else:
raise Exception("No database cursor found!")
except Exception:
_logger.error('Error on Send Emails Services', exc_info=True)
return False
finally:
if cr: 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
#----------------------------------------------------------