Stephane Wirtel (OpenERP) has proposed merging 
lp:~openerp-dev/openobject-addons/trunk-mail_gateway-mailerrorhandler into 
lp:openobject-addons.

Requested reviews:
  OpenERP Core Team (openerp)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-mail_gateway-mailerrorhandler/+merge/51295

1. Allow to send an email if there is a bug in the OpenERP Server, avoid to 
lose the email.
   The email will send the full trace back with the original email as an 
attachment and the parameters of the mailgateway.

With the attachment, you can extract the original email and resend to the 
mailgateway for debugging.

Example:
parameters
==========
<Values at 0x27709e0: {'default': None, 'custom_values': None, 'userid': 1, 
'port': 8069, 'host': 'localhost', 'model': 'crm.lead', 'password': 
'SecretPassword', 'dbname': 'SecretDatabase'}>
traceback
=========
<type 'exceptions.ZeroDivisionError'>
Python 2.6.6: /usr/bin/python
Fri Feb 25 14:53:05 2011

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 
/home/stephane/openerp/sources/trunk/addons/addons-trunk-mailgateway-mailhandler/mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py
 in main()
  189 
  190     try:
  191         1 / 0
  192         pass
  193         #email_parser.parse(msg_txt, custom_values)

<type 'exceptions.ZeroDivisionError'>: integer division or modulo by zero
    __class__ = <type 'exceptions.ZeroDivisionError'>
    __delattr__ = <method-wrapper '__delattr__' of exceptions.ZeroDivisionError 
object>
    __dict__ = {}
    __doc__ = 'Second argument to a division or modulo operation was zero.'
    __format__ = <built-in method __format__ of exceptions.ZeroDivisionError 
object>
    __getattribute__ = <method-wrapper '__getattribute__' of 
exceptions.ZeroDivisionError object>
    __getitem__ = <method-wrapper '__getitem__' of exceptions.ZeroDivisionError 
object>
    __getslice__ = <method-wrapper '__getslice__' of 
exceptions.ZeroDivisionError object>
    __hash__ = <method-wrapper '__hash__' of exceptions.ZeroDivisionError 
object>
    __init__ = <method-wrapper '__init__' of exceptions.ZeroDivisionError 
object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of exceptions.ZeroDivisionError 
object>
    __reduce_ex__ = <built-in method __reduce_ex__ of 
exceptions.ZeroDivisionError object>
    __repr__ = <method-wrapper '__repr__' of exceptions.ZeroDivisionError 
object>
    __setattr__ = <method-wrapper '__setattr__' of exceptions.ZeroDivisionError 
object>
    __setstate__ = <built-in method __setstate__ of 
exceptions.ZeroDivisionError object>
    __sizeof__ = <built-in method __sizeof__ of exceptions.ZeroDivisionError 
object>
    __str__ = <method-wrapper '__str__' of exceptions.ZeroDivisionError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __unicode__ = <built-in method __unicode__ of exceptions.ZeroDivisionError 
object>
    args = ('integer division or modulo by zero',)
    message = 'integer division or modulo by zero'

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "openerp_mailgate.py", line 191, in main
    1 / 0
ZeroDivisionError: integer division or modulo by zero




[IMP] Add a new class for the configuration
It's very useful if you want to define a specific configuration for testing


[code]
class TestingConfig(DefaultConfig):

    OPENERP_DEFAULT_PASSWORD = 'SecretPassword'
    MAIL_ERROR = '[email protected]'
    MAIL_SERVER = 'localhost'
    MAIL_ADMINS = ('[email protected]',)

config = TestingConfig()
[/code]

-- 
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-mail_gateway-mailerrorhandler/+merge/51295
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openobject-addons/trunk-mail_gateway-mailerrorhandler.
=== modified file 'mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py'
--- mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py	2011-01-14 00:11:01 +0000
+++ mail_gateway/scripts/openerp_mailgate/openerp_mailgate.py	2011-02-25 14:11:23 +0000
@@ -19,15 +19,71 @@
 #    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/>
 #
-###########################################################################################
+##############################################################################
+"""
+    openerp_mailgate.py
+"""
 
-import logging
+import cgitb
+import time
 import optparse
 import sys
 import xmlrpclib
-
-class rpc_proxy(object):
-    def __init__(self, uid, passwd, host='localhost', port=8069, path='object', dbname='openerp'):
+import smtplib
+from email.MIMEMultipart import MIMEMultipart
+from email.MIMEBase import MIMEBase
+from email.MIMEText import MIMEText
+from email.Utils import COMMASPACE, formatdate
+from email import Encoders
+
+class DefaultConfig(object):
+    """
+    Default configuration
+    """
+    OPENERP_DEFAULT_USER_ID = 1
+    OPENERP_DEFAULT_PASSWORD = 'admin'
+    OPENERP_HOSTNAME = 'localhost'
+    OPENERP_PORT = 8069
+    OPENERP_DEFAULT_DATABASE = 'openerp'
+    MAIL_ERROR = '[email protected]'
+    MAIL_SERVER = 'localhost'
+    MAIL_ADMINS = ('[email protected]',)
+
+config = DefaultConfig()
+
+
+def send_mail(_from_, to_, subject, text, files=None, server=config.MAIL_SERVER):
+    assert isinstance(to_, (list, tuple))
+
+    if files is None:
+        files = []
+
+    msg = MIMEMultipart()
+    msg['From'] = _from_
+    msg['To'] = COMMASPACE.join(to_)
+    msg['Date'] = formatdate(localtime=True)
+    msg['Subject'] = subject
+
+    msg.attach( MIMEText(text) )
+
+    for file_name, file_content in files:
+        part = MIMEBase('application', "octet-stream")
+        part.set_payload( file_content )
+        Encoders.encode_base64(part)
+        part.add_header('Content-Disposition', 'attachment; filename="%s"'
+                       % file_name)
+        msg.attach(part)
+
+    smtp = smtplib.SMTP(server)
+    smtp.sendmail(_from_, to_, msg.as_string() )
+    smtp.close()
+
+class RPCProxy(object):
+    def __init__(self, uid, passwd,
+                 host=config.OPENERP_HOSTNAME,
+                 port=config.OPENERP_PORT,
+                 path='object',
+                 dbname=config.OPENERP_DEFAULT_DATABASE):
         self.rpc = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (host, port, path), allow_none=True)
         self.user_id = uid
         self.passwd = passwd
@@ -36,9 +92,9 @@
     def __call__(self, *request, **kwargs):
         return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request, **kwargs)
 
-class email_parser(object):
+class EmailParser(object):
     def __init__(self, uid, password, model, email_default, dbname, host, port):
-        self.rpc = rpc_proxy(uid, password, host=host, port=port, dbname=dbname)
+        self.rpc = RPCProxy(uid, password, host=host, port=port, dbname=dbname)
         try:
             self.model_id = int(model)
             self.model = str(model)
@@ -51,44 +107,92 @@
     def parse(self, message, custom_values=None):
         if custom_values is None:
             custom_values = {}
-        try:
-            # pass message as bytes because we don't know its encoding until we parse its headers
-            # and hence can't convert it to utf-8 for transport
-            res_id = self.rpc('email.server.tools', 'process_email', self.model, xmlrpclib.Binary(message), custom_values)
-        except Exception:
-            logger = logging.getLogger('mail-gateway')
-            logger.warning('Failed to process incoming email. Source of the failed mail is available at debug level.', exc_info=True)
-            logger.debug('Source of the mail that failed to parse:', message)
+        # pass message as bytes because we don't know its encoding until we parse its headers
+        # and hence can't convert it to utf-8 for transport
+        self.rpc('email.server.tools',
+                 'process_email',
+                 self.model,
+                 xmlrpclib.Binary(message),
+                 custom_values)
 
-if __name__ == '__main__':
-    parser = optparse.OptionParser(usage='usage: %prog [options]', version='%prog v1.0')
+def configure_parser():
+    parser = optparse.OptionParser(usage='usage: %prog [options]', version='%prog v1.1')
     group = optparse.OptionGroup(parser, "Note",
         "This program parse a mail from standard input and communicate "
         "with the OpenERP server for case management in the CRM module.")
     parser.add_option_group(group)
-    parser.add_option("-u", "--user", dest="userid", help="ID of the user in OpenERP", default=1, type='int')
-    parser.add_option("-p", "--password", dest="password", help="Password of the user in OpenERP", default='admin')
-    parser.add_option("-o", "--model", dest="model", help="Name or ID of crm model", default="crm.lead")
-    parser.add_option("-m", "--default", dest="default", help="Default eMail in case of any trouble.", default=None)
-    parser.add_option("-d", "--dbname", dest="dbname", help="Database name (default: openerp)", default='openerp')
-    parser.add_option("--host", dest="host", help="Hostname of the OpenERP Server", default="localhost")
-    parser.add_option("--port", dest="port", help="Port of the OpenERP Server", default="8069")
-    parser.add_option("--custom-values", dest="custom_values", help="Add Custom Values to the object", default=None)
-
+    parser.add_option("-u", "--user", dest="userid",
+                      help="ID of the user in OpenERP",
+                      default=config.OPENERP_DEFAULT_USER_ID, type='int')
+    parser.add_option("-p", "--password", dest="password",
+                      help="Password of the user in OpenERP",
+                      default=config.OPENERP_DEFAULT_PASSWORD)
+    parser.add_option("-o", "--model", dest="model",
+                      help="Name or ID of crm model",
+                      default="crm.lead")
+    parser.add_option("-m", "--default", dest="default",
+                      help="Default eMail in case of any trouble.",
+                      default=None)
+    parser.add_option("-d", "--dbname", dest="dbname",
+                      help="Database name (default: %default)",
+                      default=config.OPENERP_DEFAULT_DATABASE)
+    parser.add_option("--host", dest="host",
+                      help="Hostname of the OpenERP Server",
+                      default=config.OPENERP_HOSTNAME)
+    parser.add_option("--port", dest="port",
+                      help="Port of the OpenERP Server",
+                      default=config.OPENERP_PORT)
+    parser.add_option("--custom-values", dest="custom_values",
+                      help="Add Custom Values to the object",
+                      default=None)
+
+    return parser
+
+def main():
+    """
+    Receive the email via the stdin and send it to the OpenERP Server
+    """
+    parser = configure_parser()
     (options, args) = parser.parse_args()
 
-    logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s")
-
-    parser = email_parser(options.userid, options.password, options.model, options.default, dbname=options.dbname, host=options.host, port=options.port)
+
+    email_parser = EmailParser(options.userid,
+                               options.password,
+                               options.model,
+                               options.default,
+                               dbname=options.dbname,
+                               host=options.host,
+                               port=options.port)
+
 
     msg_txt = sys.stdin.read()
 
     custom_values = {}
     try:
-        custom_values = dict(eval(options.custom_values))
+        custom_values = dict(eval(options.custom_values or {} ))
     except:
         pass
 
-    parser.parse(msg_txt, custom_values)
+    try:
+        email_parser.parse(msg_txt, custom_values)
+    except Exception:
+        msg = '\n'.join([
+            'parameters',
+            '==========',
+            '%r' % (options,),
+            'traceback',
+            '=========',
+            '%s' % (cgitb.text(sys.exc_info())),
+        ])
+
+        subject = '[OPENERP]:ERROR: Mailgateway - %s' % time.strftime('%Y-%m-%d %H:%M:%S')
+        send_mail(
+            config.MAIL_ERROR,
+            config.MAIL_ADMINS,
+            subject, msg, files=[('message.txt', msg_txt)]
+        )
+
+if __name__ == '__main__':
+    main()
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-web
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-web
More help   : https://help.launchpad.net/ListHelp

Reply via email to