From dc9f82b88c734836b4114ee543dc64ecf826236d Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Mon, 14 Jun 2010 15:24:41 +0530 Subject: [PATCH 1/3] [IMP]: mail_gateway: Improvement for sending reply mail bzr revid: rpa@tinyerp.com-20100614095441-d6d74jd8a0idkq3e --- addons/fetchmail/fetchmail.py | 2 +- addons/mail_gateway/mail_gateway.py | 44 +++++++- addons/mail_gateway/mail_gateway_view.xml | 2 +- .../openerp_mailgate/openerp_mailgate.py | 106 +++--------------- 4 files changed, 57 insertions(+), 97 deletions(-) diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py index a61d4f50031..450362b80a5 100644 --- a/addons/fetchmail/fetchmail.py +++ b/addons/fetchmail/fetchmail.py @@ -134,7 +134,7 @@ class email_server(osv.osv): action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]}) imap_server.store(num, '+FLAGS', '\\Seen') - count += 1 + count += 1 logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail fetch/process %s email(s) from %s' % (count, server.name)) imap_server.close() diff --git a/addons/mail_gateway/mail_gateway.py b/addons/mail_gateway/mail_gateway.py index 4f7962f988e..b4de38b1471 100644 --- a/addons/mail_gateway/mail_gateway.py +++ b/addons/mail_gateway/mail_gateway.py @@ -25,7 +25,7 @@ import base64 import re import tools import binascii - +import socket import email from email.header import decode_header import netsvc @@ -154,7 +154,21 @@ class mailgate_tool(osv.osv): _name = 'email.server.tools' _description = "Email Tools" _auto = False + + def _to_decode(self, s, charsets): + for charset in charsets: + if charset: + try: + return s.decode(charset) + except UnicodeError: + pass + return s.decode('latin1') + def _decode_header(self, text): + if text: + text = decode_header(text.replace('\r', '')) + return ''.join(map(lambda x:self._to_decode(x[0], [x[1]]), text or [])) + def to_email(self, cr, uid, text): _email = re.compile(r'.*<.*@.*\..*>', re.UNICODE) def record(path): @@ -191,6 +205,31 @@ class mailgate_tool(osv.osv): } msg_id = self.pool.get('mailgate.message').create(cr, uid, msg_data) return True + + def email_send(self, cr, uid, model, res_id, msg, email_default ): + message = email.message_from_string(str(msg)) + subject = '['+str(res_id)+'] '+ self._decode_header(message['Subject']) + message['Message-Id'] = '<' + str(time.time()) + '-openerp-' + \ + model + '-' + str(res_id) + '@'+socket.gethostname() + '>' + msg_mails = [] + mails = [self._decode_header(message['From']), self._decode_header(message['To'])]+self._decode_header(message.get('Cc', '')).split(',') + for mail in mails: + if mail: + msg_mails.append(self.to_email(cr, uid, mail)) + encoding = message.get_content_charset() + message['body'] = message.get_payload(decode=True) + if encoding: + message['body'] = message['body'].decode(encoding).encode('utf-8') + + try: + tools.email_send(email_default or tools.config.get('email_from', None), msg_mails, subject, message.get('body')) + except Exception, e: + if email_default: + temp_msg = '['+str(res_id)+'] ' + self._decode_header(message['Subject']) + del message['Subject'] + message['Subject'] = '[OpenERP-FetchError] ' + temp_msg + tools.email_send(email_default, email_default, message.get('Subject'), message.get('body')) + return True def process_email(self, cr, uid, model, message, attach=True, server_id=None, server_type=None, context=None): if not context: @@ -229,7 +268,8 @@ class mailgate_tool(osv.osv): att_ids.append(self.pool.get('ir.attachment').create(cr, uid, data_attach)) if hasattr(model_pool, 'history'): - model_pool.history(cr, uid, [res_id], 'Receive', True, msg.get('to'), msg.get('body'), msg.get('from'), False, {'model' : model}) + res = model_pool.browse(cr, uid, [res_id]) + model_pool._history(cr, uid, res, 'Receive', True, msg.get('to'), msg.get('body'), msg.get('from'), False, {'model' : model}) else: self.history(cr, uid, model, res_id, msg, att_ids, server_id=server_id, server_type=server_type) diff --git a/addons/mail_gateway/mail_gateway_view.xml b/addons/mail_gateway/mail_gateway_view.xml index 0ce1af446e9..bd286875e7a 100644 --- a/addons/mail_gateway/mail_gateway_view.xml +++ b/addons/mail_gateway/mail_gateway_view.xml @@ -181,7 +181,7 @@ mailgate.message tree,form form - [('history', '=', True)] + [('history', '=', True)] diff --git a/addons/mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py b/addons/mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py index 0698be88eaf..e0ea723c75f 100755 --- a/addons/mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py +++ b/addons/mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py @@ -23,25 +23,11 @@ from email.header import decode_header import email as EMAIL -import re -import smtplib -import time, socket +import logging +import optparse +import sys import xmlrpclib - -email_re = re.compile(r"([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6})") -case_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)', -} - class rpc_proxy(object): def __init__(self, uid, passwd, host='localhost', port=8069, path='object', dbname='terp'): self.rpc = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (host, port, path), allow_none=True) @@ -53,7 +39,7 @@ class rpc_proxy(object): return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request, **kwargs) class email_parser(object): - def __init__(self, uid, password, model, email, email_default, dbname, host, port, smtp_server=None, smtp_port=None, smtp_ssl=None, smtp_user=None, smtp_password=None): + def __init__(self, uid, password, model, email, email_default, dbname, host, port): self.rpc = rpc_proxy(uid, password, host=host, port=port, dbname=dbname) try: self.model_id = int(model) @@ -64,53 +50,8 @@ class email_parser(object): self.email = email self.email_default = email_default self.canal_id = False - self.smtp_server = smtp_server - self.smtp_port = smtp_port - self.smtp_ssl = smtp_ssl - self.smtp_user = smtp_user - self.smtp_password = smtp_password - def email_get(self, email_from): - return self.rpc('email.server.tools', 'to_email', email_from) - - def _to_decode(self, s, charsets): - for charset in charsets: - if charset: - try: - return s.decode(charset) - except UnicodeError: - pass - return s.decode('latin1') - - def _decode_header(self, s): - if s: - s = decode_header(s.replace('\r', '')) - return ''.join(map(lambda x:self._to_decode(x[0], [x[1]]), s or [])) - - def msg_send(self, msg, emails, priority=None): - if not emails: - return False - - msg['To'] = emails[0] - if len(emails)>1: - if 'Cc' in msg: - del msg['Cc'] - msg['Cc'] = ','.join(emails[1:]) - - del msg['Reply-To'] - msg['Reply-To'] = self.email - if self.smtp_user and self.smtp_password: - s = smtplib.SMTP(self.smtp_server, self.smtp_port) - s.ehlo() - s.starttls() - s.ehlo() - s.login(self.smtp_user, self.smtp_password) - s.sendmail(self.email, emails, msg.as_string()) - s.close() - return True - return False - def parse(self, message): try: @@ -118,34 +59,16 @@ class email_parser(object): except Exception, e: res_id = False - msg = EMAIL.message_from_string(str(message)) - subject = self._decode_header(msg['Subject']) - if msg.get('Subject', ''): - del msg['Subject'] - - #Changed for sending reply mail +# Reply mail if res_id: - msg['Subject'] = '['+str(res_id)+'] '+subject - msg['Message-Id'] = '<'+str(time.time())+'-openerpcrm-'+str(res_id)+'@'+socket.gethostname()+'>' - - mm = [self._decode_header(msg['From']), self._decode_header(msg['To'])]+self._decode_header(msg.get('Cc', '')).split(',') - msg_mails = map(self.email_get, filter(None, mm)) - - try: - self.msg_send(msg, msg_mails) - except Exception, e: - if self.email_default: - a = self._decode_header(msg['Subject']) - del msg['Subject'] - msg['Subject'] = '[OpenERP-FetchError] ' + a - self.msg_send(msg, self.email_default.split(',')) - return res_id, msg_mails + self.rpc('email.server.tools', 'email_send', self.model, res_id, message, self.email_default) + + return res_id if __name__ == '__main__': parser = optparse.OptionParser(usage='usage: %prog [options]', version='%prog v1.0') group = optparse.OptionGroup(parser, "Note", - "This program parse a mail from standard input and communicate " - "with the Open ERP server for case management in the CRM module.") + "This program parse a mail from standard input and communicate with the Open ERP server") parser.add_option_group(group) parser.add_option("-u", "--user", dest="userid", help="ID of the user in Open ERP", default=1, type='int') parser.add_option("-p", "--password", dest="password", help="Password of the user in Open ERP", default='admin') @@ -155,16 +78,13 @@ if __name__ == '__main__': parser.add_option("-d", "--dbname", dest="dbname", help="Database name (default: terp)", default='terp') parser.add_option("--host", dest="host", help="Hostname of the Open ERP Server", default="localhost") parser.add_option("--port", dest="port", help="Port of the Open ERP Server", default="8069") - parser.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email') - parser.add_option('--smtp-port', dest='smtp_port', default='25', help='specify the SMTP port', type="int") - parser.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not') - parser.add_option('--smtp-user', dest='smtp_user', default='', help='specify the SMTP username for sending email') - parser.add_option('--smtp-password', dest='smtp_password', default='', help='specify the SMTP password for sending email') (options, args) = parser.parse_args() - parser = email_parser(options.userid, options.password, options.model, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port, smtp_server=options.smtp_server, smtp_port=options.smtp_port, smtp_ssl=options.smtp_ssl, smtp_user=options.smtp_user, smtp_password=options.smtp_password) - msg_txt = sys.stdin.read().decode('utf8') + logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s") + + parser = email_parser(options.userid, options.password, options.model, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port) + msg_txt = sys.stdin.read() parser.parse(msg_txt) From 80d0f5dfc97d97fb6af681eefa9aee6b28945009 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Mon, 14 Jun 2010 16:54:22 +0530 Subject: [PATCH 2/3] [IMP]: mail_gateway: Improvement for history bzr revid: rpa@tinyerp.com-20100614112422-yj34kne5fibi5iop --- addons/mail_gateway/mail_gateway.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/mail_gateway/mail_gateway.py b/addons/mail_gateway/mail_gateway.py index b4de38b1471..d92ee16905c 100644 --- a/addons/mail_gateway/mail_gateway.py +++ b/addons/mail_gateway/mail_gateway.py @@ -267,9 +267,15 @@ class mailgate_tool(osv.osv): } att_ids.append(self.pool.get('ir.attachment').create(cr, uid, data_attach)) - if hasattr(model_pool, 'history'): + if hasattr(model_pool, '_history'): res = model_pool.browse(cr, uid, [res_id]) - model_pool._history(cr, uid, res, 'Receive', True, msg.get('to'), msg.get('body'), msg.get('from'), False, {'model' : model}) + model_pool._history(cr, uid, res, 'Receive', True, + subject=msg.get('subject'), + email=msg.get('to'), details=msg.get('body'), + email_from=msg.get('from'), + message_id=msg.get('message-id'), + attach=msg.get('attachments', {}).items(), + context={'model' : model}) else: self.history(cr, uid, model, res_id, msg, att_ids, server_id=server_id, server_type=server_type) From 1eb6c48afad34dcea61ea00c85159a469e6422c9 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Mon, 14 Jun 2010 17:40:22 +0530 Subject: [PATCH 3/3] [IMP]: mail_gateway: Docstring updated bzr revid: rpa@tinyerp.com-20100614121022-kwapy94qqlgci1i6 --- addons/mail_gateway/mail_gateway.py | 31 ++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/addons/mail_gateway/mail_gateway.py b/addons/mail_gateway/mail_gateway.py index d92ee16905c..809c9310768 100644 --- a/addons/mail_gateway/mail_gateway.py +++ b/addons/mail_gateway/mail_gateway.py @@ -181,13 +181,23 @@ class mailgate_tool(osv.osv): return bits def history(self, cr, uid, model, new_id, msg, attach, server_id=None, server_type=None): + """This function creates history for mails fetched + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param model: OpenObject Model + @param new_id: Id of the record of OpenObject model created from the Email details + @param msg: Email details + @param attach: Email attachments + @param server_id: Id of the POP/IMAP Server if the mail is fetched using OpenERP interface + @param server_type: Type of Fetchmail server""" try: thread_id = self.pool.get(model).read(cr, uid, new_id, ['thread_id'])['thread_id'][0] except Exception, e: thread_id = None msg_data = { 'name': msg.get('subject', 'No subject'), - 'date': msg.get('date') , # or time.strftime('%Y-%m-%d %H:%M:%S')?? + 'date': msg.get('date') , 'description': msg.get('body', msg.get('from')), 'history': True, 'model': model, @@ -207,6 +217,15 @@ class mailgate_tool(osv.osv): return True def email_send(self, cr, uid, model, res_id, msg, email_default ): + """This function Sends return email on submission of Fetched email in OpenERP database + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param model: OpenObject Model + @param res_id: Id of the record of OpenObject model created from the Email details + @param msg: Email details + @param email_default: Default Email address in case of any Problem + """ message = email.message_from_string(str(msg)) subject = '['+str(res_id)+'] '+ self._decode_header(message['Subject']) message['Message-Id'] = '<' + str(time.time()) + '-openerp-' + \ @@ -232,6 +251,16 @@ class mailgate_tool(osv.osv): return True def process_email(self, cr, uid, model, message, attach=True, server_id=None, server_type=None, context=None): + """This function Processes email and create record for given OpenERP model + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param model: OpenObject Model + @param message: Email details + @param attach: Email attachments + @param server_id: Id of the POP/IMAP Server if the mail is fetched using OpenERP interface + @param server_type: Type of Fetchmail server + @param context: A standard dictionary for contextual values""" if not context: context = {} context.update({