diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index db636797d12a8d9685938615b8731953936364a5..825a880b62c8fe92448b86c322387274a3964f5a 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -38,7 +38,7 @@ class AuthSignupHome(Home):
                 if request.env["res.users"].sudo().search([("login", "=", qcontext.get("login"))]):
                     qcontext["error"] = _("Another user is already registered using this email address.")
                 else:
-                    _logger.error(e.message)
+                    _logger.error("%s", e)
                     qcontext['error'] = _("Could not create a new account.")
 
         return request.render('auth_signup.signup', qcontext)
@@ -64,7 +64,7 @@ class AuthSignupHome(Home):
                 qcontext['error'] = _("Could not reset your password")
                 _logger.exception('error when resetting password')
             except Exception as e:
-                qcontext['error'] = e.message or e.name
+                qcontext['error'] = str(e)
 
         response = request.render('auth_signup.reset_password', qcontext)
         response.headers['X-Frame-Options'] = 'DENY'
diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py
index 0b6b534a28af64e5a4aa611bb465bc54557a4755..35262774bf4a44aa9ea87994ef449645f0b76c53 100644
--- a/addons/base_import/models/base_import.py
+++ b/addons/base_import/models/base_import.py
@@ -617,9 +617,9 @@ class Import(models.TransientModel):
                             try:
                                 line[index] = dt.strftime(dt.strptime(ustr(line[index]).encode('utf-8'), user_format), server_format)
                             except ValueError as e:
-                                raise ValueError(_("Column %s contains incorrect values. Error in line %d: %s") % (name, num + 1, ustr(e.message)))
+                                raise ValueError(_("Column %s contains incorrect values. Error in line %d: %s") % (name, num + 1, e))
                             except Exception as e:
-                                raise ValueError(_("Error Parsing Date [%s:L%d]: %s") % (name, num + 1, ustr(e.message)))
+                                raise ValueError(_("Error Parsing Date [%s:L%d]: %s") % (name, num + 1, e))
 
             elif field['type'] in ('float', 'monetary') and name in import_fields:
                 # Parse float, sometimes float values from file have currency symbol or () to denote a negative value
diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py
index 89f037d55d32846414017ea0853944717bf3427b..56c447dd9d42c9d7382c5bceced0a2e6fd973a33 100644
--- a/addons/gamification/models/goal.py
+++ b/addons/gamification/models/goal.py
@@ -87,7 +87,9 @@ class GoalDefinition(models.Model):
                 # dummy search to make sure the domain is valid
                 Obj.search_count(domain)
             except (ValueError, SyntaxError) as e:
-                msg = e.message or (e.msg + '\n' + e.text)
+                msg = e
+                if isinstance(e, SyntaxError):
+                    msg = (e.msg + '\n' + e.text)
                 raise exceptions.UserError(_("The domain for the definition %s seems incorrect, please check it.\n\n%s") % (definition.name, msg))
         return True
 
@@ -105,7 +107,7 @@ class GoalDefinition(models.Model):
                         _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not stored") % (definition.name, definition.field_id.name))
             except KeyError as e:
                 raise exceptions.UserError(
-                    _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e.message))
+                    _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e))
 
     @api.model
     def create(self, vals):
diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py
index e55dc57af5aa946f01d62a3fce5cd5d188e777eb..6c929ca2f26dae94623dd6f7098da76d23b08dcf 100644
--- a/addons/hw_escpos/controllers/main.py
+++ b/addons/hw_escpos/controllers/main.py
@@ -81,7 +81,7 @@ class EscposDriver(Thread):
             try:
                 description = usb.util.get_string(printer, 256, printer.iManufacturer) + " " + usb.util.get_string(printer, 256, printer.iProduct)
             except Exception as e:
-                _logger.error("Can not get printer description: %s" % (e.message or repr(e)))
+                _logger.error("Can not get printer description: %s" % e)
                 description = 'Unknown printer'
             connected.append({
                 'vendor': printer.idVendor,
diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py
index 8517274205bf7379f2800f4081e1878f050e85c2..3f206424e07e9e4344fa0d0362b4bdc555f2f164 100644
--- a/addons/mail/models/mail_mail.py
+++ b/addons/mail/models/mail_mail.py
@@ -326,7 +326,7 @@ class MailMail(models.Model):
                         res = IrMailServer.send_email(
                             msg, mail_server_id=mail.mail_server_id.id, smtp_session=smtp_session)
                     except AssertionError as error:
-                        if error.message == IrMailServer.NO_VALID_RECIPIENT:
+                        if str(error) == IrMailServer.NO_VALID_RECIPIENT:
                             # No valid recipient found for this particular
                             # mail item -> ignore error to avoid blocking
                             # delivery to next recipients, if any. If this is
diff --git a/addons/payment_ogone/controllers/main.py b/addons/payment_ogone/controllers/main.py
index 2dfa2747ab8eb7f496a81cd573632cf8c12fb9d1..53150686f25dd29eacbeed71e2009e775a35012b 100644
--- a/addons/payment_ogone/controllers/main.py
+++ b/addons/payment_ogone/controllers/main.py
@@ -41,7 +41,7 @@ class OgoneController(http.Controller):
             acq.s2s_process(post)
         except Exception as e:
             # synthax error: 'CHECK ERROR: |Not a valid date\n\n50001111: None'
-            error = e.message.splitlines()[0].split('|')[-1] or ''
+            error = str(e).splitlines()[0].split('|')[-1] or ''
         return werkzeug.utils.redirect(post.get('return_url', '/') + (error and '#error=%s' % werkzeug.url_quote(error) or ''))
 
     @http.route(['/payment/ogone/s2s/feedback'], auth='none', csrf=False)
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index f00c6ff512249b65e145d6cc282f0ea4dd171ab6..105c8ab78418b9d9dd4476c907aecd7ef15b47e3 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1053,7 +1053,7 @@ class Binary(http.Controller):
             args = [len(data), ufile.filename,
                     ufile.content_type, base64.b64encode(data)]
         except Exception as e:
-            args = [False, e.message]
+            args = [False, str(e)]
         return out % (json.dumps(callback), json.dumps(args))
 
     @http.route('/web/binary/upload_attachment', type='http', auth="user")
@@ -1647,4 +1647,4 @@ class ReportController(http.Controller):
 
     @http.route(['/report/check_wkhtmltopdf'], type='json', auth="user")
     def check_wkhtmltopdf(self):
-        return request.env['ir.actions.report'].get_wkhtmltopdf_state()
\ No newline at end of file
+        return request.env['ir.actions.report'].get_wkhtmltopdf_state()
diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py
index 6385c84069a11393afd80cb8a981a20c76f2cb8c..adc6aeaad399f99700714c39f3603480039652bf 100644
--- a/addons/website_slides/controllers/main.py
+++ b/addons/website_slides/controllers/main.py
@@ -319,7 +319,7 @@ class WebsiteSlides(http.Controller):
             return {'error': e.name}
         except Exception as e:
             _logger.error(e)
-            return {'error': _('Internal server error, please try again later or contact administrator.\nHere is the error message: %s') % e.message}
+            return {'error': _('Internal server error, please try again later or contact administrator.\nHere is the error message: %s') % e}
         return {'url': "/slides/slide/%s" % (slide_id.id)}
 
     # --------------------------------------------------
diff --git a/odoo/addons/base/ir/ir_model.py b/odoo/addons/base/ir/ir_model.py
index 2ff66b455dea6c03882aa41272a0c7bb490970c8..374ff5edc15eeaa45800d5adbd6b6606da16a433 100644
--- a/odoo/addons/base/ir/ir_model.py
+++ b/odoo/addons/base/ir/ir_model.py
@@ -406,7 +406,7 @@ class IrModelFields(models.Model):
             try:
                 field = self._related_field()
             except UserError as e:
-                return {'warning': {'title': _("Warning"), 'message': e.message}}
+                return {'warning': {'title': _("Warning"), 'message': e}}
             self.ttype = field.type
             self.relation = field.comodel_name
             self.readonly = True
diff --git a/odoo/addons/base/ir/ir_qweb/assetsbundle.py b/odoo/addons/base/ir/ir_qweb/assetsbundle.py
index 19902e78d1b8c274561d85f70839a1de01a5c1a7..6a8ad84c9ddaca10dc0842005e964b77b5c2989f 100644
--- a/odoo/addons/base/ir/ir_qweb/assetsbundle.py
+++ b/odoo/addons/base/ir/ir_qweb/assetsbundle.py
@@ -524,7 +524,7 @@ class JavascriptAsset(WebAsset):
         try:
             return super(JavascriptAsset, self)._fetch_content()
         except AssetError as e:
-            return "console.error(%s);" % json.dumps(e.message)
+            return "console.error(%s);" % json.dumps(str(e))
 
     def to_html(self):
         if self.url:
@@ -573,7 +573,7 @@ class StylesheetAsset(WebAsset):
 
             return content
         except AssetError as e:
-            self.bundle.css_errors.append(e.message)
+            self.bundle.css_errors.append(str(e))
             return ''
 
     def minify(self):
diff --git a/odoo/addons/base/ir/ir_ui_view.py b/odoo/addons/base/ir/ir_ui_view.py
index 0a709985ff6b474e62a2f5f8387b80142244a1de..3e674b02a486f93ee6f2feb1839c5f54433b95e1 100644
--- a/odoo/addons/base/ir/ir_ui_view.py
+++ b/odoo/addons/base/ir/ir_ui_view.py
@@ -1200,4 +1200,4 @@ actual arch.
             try:
                 self.browse(vid)._check_xml()
             except Exception as e:
-                self.raise_view_error("Can't validate view:\n%s" % (e.message or repr(e)), vid)
+                self.raise_view_error("Can't validate view:\n%s" % e, vid)
diff --git a/odoo/loglevels.py b/odoo/loglevels.py
index 400f08e1a8fa0e643b532378c4ec961c15729122..8c0242867d22963dee4ba235428b8418ac554761 100644
--- a/odoo/loglevels.py
+++ b/odoo/loglevels.py
@@ -92,8 +92,6 @@ def ustr(value, hint_encoding='utf-8', errors='strict'):
 
 
 def exception_to_unicode(e):
-    if (sys.version_info[:2] < (2,6)) and hasattr(e, 'message'):
-        return ustr(e.message)
     if hasattr(e, 'args'):
         return "\n".join((ustr(a) for a in e.args))
     try:
diff --git a/odoo/service/wsgi_server.py b/odoo/service/wsgi_server.py
index afcac829856ce1b35499b17d7f5cbff68c8fc878..46c589157c1988c657ecbfa06e205b5da1efa1a4 100644
--- a/odoo/service/wsgi_server.py
+++ b/odoo/service/wsgi_server.py
@@ -85,17 +85,12 @@ def xmlrpc_handle_exception_int(e):
         fault = xmlrpclib.Fault(RPC_FAULT_CODE_APPLICATION_ERROR, formatted_info)
         response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
     else:
-        if hasattr(e, 'message') and e.message == 'AccessDenied': # legacy
-            fault = xmlrpclib.Fault(RPC_FAULT_CODE_ACCESS_DENIED, str(e))
-            response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
-        #InternalError
-        else:
-            info = sys.exc_info()
-            # Which one is the best ?
-            formatted_info = "".join(traceback.format_exception(*info))
-            #formatted_info = odoo.tools.exception_to_unicode(e) + '\n' + info
-            fault = xmlrpclib.Fault(RPC_FAULT_CODE_APPLICATION_ERROR, formatted_info)
-            response = xmlrpclib.dumps(fault, allow_none=None, encoding=None)
+        info = sys.exc_info()
+        # Which one is the best ?
+        formatted_info = "".join(traceback.format_exception(*info))
+        #formatted_info = odoo.tools.exception_to_unicode(e) + '\n' + info
+        fault = xmlrpclib.Fault(RPC_FAULT_CODE_APPLICATION_ERROR, formatted_info)
+        response = xmlrpclib.dumps(fault, allow_none=None, encoding=None)
     return response
 
 def xmlrpc_handle_exception_string(e):
@@ -116,7 +111,7 @@ def xmlrpc_handle_exception_string(e):
     elif isinstance(e, odoo.exceptions.DeferredException):
         info = e.traceback
         formatted_info = "".join(traceback.format_exception(*info))
-        fault = xmlrpclib.Fault(odoo.tools.ustr(e.message), formatted_info)
+        fault = xmlrpclib.Fault(odoo.tools.ustr(e), formatted_info)
         response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
     #InternalError
     else:
diff --git a/odoo/tools/xml_utils.py b/odoo/tools/xml_utils.py
index df4c5669644a1bb85d276bd6938edee9da15ab75..b7c03a87f537bf446f1dafe8089201f46f545c39 100644
--- a/odoo/tools/xml_utils.py
+++ b/odoo/tools/xml_utils.py
@@ -13,4 +13,4 @@ def check_with_xsd(tree_or_str, xsd_path):
     except etree.DocumentInvalid as xml_errors:
         #import UserError only here to avoid circular import statements with tools.func being imported in exceptions.py
         from odoo.exceptions import UserError
-        raise UserError('\n'.join([e.message for e in xml_errors.error_log]))
+        raise UserError('\n'.join(str(e) for e in xml_errors.error_log))