From d497dbe9199bd189a462a590dbd7e74364f6ac69 Mon Sep 17 00:00:00 2001 From: std-odoo Date: Wed, 26 Jan 2022 12:42:25 +0000 Subject: [PATCH] [IMP] fetchmail_gmail, google_gmail: simplify the mail server form view Purpose ======= A field `use_google_gmail_service` has been used in stable to define a mail server which use Gmail authentication. But now that the fields `smtp_authentication` exists, we want to use it to simplify the mail server form view. For the incoming mail server, the field `server_type` will be used for the same purpose. Add a new field to have the option to install `google_gmail` in the main settings page. Task-2170676 closes odoo/odoo#83413 Related: odoo/upgrade#3199 Signed-off-by: Thibault Delavallee (tde) --- addons/fetchmail/models/fetchmail.py | 27 +++++++++++++------ addons/fetchmail/views/fetchmail_views.xml | 2 +- addons/fetchmail_gmail/__manifest__.py | 2 +- .../models/fetchmail_server.py | 27 ++++++++++--------- .../views/fetchmail_server_views.xml | 15 +++++------ addons/google_gmail/__manifest__.py | 2 +- .../google_gmail/models/google_gmail_mixin.py | 1 - addons/google_gmail/models/ir_mail_server.py | 21 ++++++++------- .../views/ir_mail_server_views.xml | 17 ++++++------ .../views/res_config_settings_views.xml | 27 ++++++------------- addons/mail/models/res_config_settings.py | 1 + .../mail/views/res_config_settings_views.xml | 16 +++++++++++ odoo/addons/base/models/ir_mail_server.py | 8 +++--- 13 files changed, 92 insertions(+), 74 deletions(-) diff --git a/addons/fetchmail/models/fetchmail.py b/addons/fetchmail/models/fetchmail.py index eaef01099fe..1c0f3ecfa24 100644 --- a/addons/fetchmail/models/fetchmail.py +++ b/addons/fetchmail/models/fetchmail.py @@ -100,13 +100,14 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO def connect(self): self.ensure_one() - if self.server_type == 'imap': + connection_type = self._get_connection_type() + if connection_type == 'imap': if self.is_ssl: connection = IMAP4_SSL(self.server, int(self.port)) else: connection = IMAP4(self.server, int(self.port)) self._imap_login(connection) - elif self.server_type == 'pop': + elif connection_type == 'pop': if self.is_ssl: connection = POP3_SSL(self.server, int(self.port)) else: @@ -148,9 +149,10 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO finally: try: if connection: - if server.server_type == 'imap': + connection_type = server._get_connection_type() + if connection_type == 'imap': connection.close() - elif server.server_type == 'pop': + elif connection_type == 'pop': connection.quit() except Exception: # ignored, just a consequence of the previous exception @@ -160,7 +162,7 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO @api.model def _fetch_mails(self): """ Method called by cron to fetch mails from servers """ - return self.search([('state', '=', 'done'), ('server_type', 'in', ['pop', 'imap'])]).fetch_mail() + return self.search([('state', '=', 'done'), ('server_type', '!=', 'local')]).fetch_mail() def fetch_mail(self): """ WARNING: meant for cron usage only - will commit() after each email! """ @@ -174,7 +176,8 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO count, failed = 0, 0 imap_server = None pop_server = None - if server.server_type == 'imap': + connection_type = server._get_connection_type() + if connection_type == 'imap': try: imap_server = server.connect() imap_server.select() @@ -198,7 +201,7 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO if imap_server: imap_server.close() imap_server.logout() - elif server.server_type == 'pop': + elif connection_type == 'pop': try: while True: failed_in_loop = 0 @@ -231,6 +234,14 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO server.write({'date': fields.Datetime.now()}) return True + def _get_connection_type(self): + """Return which connection must be used for this mail server (IMAP or POP). + Can be overridden in sub-module to define which connection to use for a specific + "server_type" (e.g. Gmail server). + """ + self.ensure_one() + return self.server_type + @api.model def _update_cron(self): if self.env.context.get('fetchmail_cron_running'): @@ -238,6 +249,6 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO try: # Enabled/Disable cron based on the number of 'done' server of type pop or imap cron = self.env.ref('fetchmail.ir_cron_mail_gateway_action') - cron.toggle(model=self._name, domain=[('state', '=', 'done'), ('server_type', 'in', ['pop', 'imap'])]) + cron.toggle(model=self._name, domain=[('state', '=', 'done'), ('server_type', '!=', 'local')]) except ValueError: pass diff --git a/addons/fetchmail/views/fetchmail_views.xml b/addons/fetchmail/views/fetchmail_views.xml index 5264cdbff54..59e65aad444 100644 --- a/addons/fetchmail/views/fetchmail_views.xml +++ b/addons/fetchmail/views/fetchmail_views.xml @@ -31,8 +31,8 @@ - + diff --git a/addons/fetchmail_gmail/__manifest__.py b/addons/fetchmail_gmail/__manifest__.py index 6638c3443d9..ec9db906501 100644 --- a/addons/fetchmail_gmail/__manifest__.py +++ b/addons/fetchmail_gmail/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Fetchmail Gmail", - "version": "1.0", + "version": "1.1", "category": "Hidden", "description": "Google authentication for incoming mail server", "depends": [ diff --git a/addons/fetchmail_gmail/models/fetchmail_server.py b/addons/fetchmail_gmail/models/fetchmail_server.py index 5dffbfea53f..09196892015 100644 --- a/addons/fetchmail_gmail/models/fetchmail_server.py +++ b/addons/fetchmail_gmail/models/fetchmail_server.py @@ -1,34 +1,28 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, models, _ -from odoo.exceptions import UserError +from odoo import api, fields, models class FetchmailServer(models.Model): _name = 'fetchmail.server' _inherit = ['fetchmail.server', 'google.gmail.mixin'] - @api.constrains('use_google_gmail_service', 'server_type') - def _check_use_google_gmail_service(self): - if any(server.use_google_gmail_service and server.server_type != 'imap' for server in self): - raise UserError(_('Gmail authentication only supports IMAP server type.')) + server_type = fields.Selection(selection_add=[('gmail', 'Gmail OAuth Authentication')], ondelete={'gmail': 'set default'}) - @api.onchange('use_google_gmail_service') - def _onchange_use_google_gmail_service(self): + @api.onchange('server_type', 'is_ssl', 'object_id') + def onchange_server_type(self): """Set the default configuration for a IMAP Gmail server.""" - if self.use_google_gmail_service: + if self.server_type == 'gmail': self.server = 'imap.gmail.com' - self.server_type = 'imap' self.is_ssl = True self.port = 993 else: - self.server_type = 'pop' - self.is_ssl = False self.google_gmail_authorization_code = False self.google_gmail_refresh_token = False self.google_gmail_access_token = False self.google_gmail_access_token_expiration = False + super(FetchmailServer, self).onchange_server_type() def _imap_login(self, connection): """Authenticate the IMAP connection. @@ -36,9 +30,16 @@ class FetchmailServer(models.Model): If the mail server is Gmail, we use the OAuth2 authentication protocol. """ self.ensure_one() - if self.use_google_gmail_service: + if self.server_type == 'gmail': auth_string = self._generate_oauth2_string(self.user, self.google_gmail_refresh_token) connection.authenticate('XOAUTH2', lambda x: auth_string) connection.select('INBOX') else: super(FetchmailServer, self)._imap_login(connection) + + def _get_connection_type(self): + """Return which connection must be used for this mail server (IMAP or POP). + The Gmail mail server used an IMAP connection. + """ + self.ensure_one() + return 'imap' if self.server_type == 'gmail' else super()._get_connection_type() diff --git a/addons/fetchmail_gmail/views/fetchmail_server_views.xml b/addons/fetchmail_gmail/views/fetchmail_server_views.xml index abbb906f13f..76056ebd6ac 100644 --- a/addons/fetchmail_gmail/views/fetchmail_server_views.xml +++ b/addons/fetchmail_gmail/views/fetchmail_server_views.xml @@ -5,26 +5,25 @@ fetchmail.server - - - - {'required' : [('server_type', '!=', 'local'), ('use_google_gmail_service', '=', False), ('password', '!=', False)], 'invisible' : [('use_google_gmail_service', '=', True)]} + + {'required' : [('server_type', '!=', 'local'), ('server_type', '!=', 'gmail'), ('password', '!=', False)], 'invisible' : [('server_type', '=', 'gmail')]} + diff --git a/addons/google_gmail/__manifest__.py b/addons/google_gmail/__manifest__.py index 0230d1dd1aa..76a8727f44e 100644 --- a/addons/google_gmail/__manifest__.py +++ b/addons/google_gmail/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Google Gmail", - "version": "1.0", + "version": "1.1", "category": "Hidden", "description": "Gmail support for incoming / outgoing mail servers", "depends": [ diff --git a/addons/google_gmail/models/google_gmail_mixin.py b/addons/google_gmail/models/google_gmail_mixin.py index c0a4dfde9f7..72ff093e845 100644 --- a/addons/google_gmail/models/google_gmail_mixin.py +++ b/addons/google_gmail/models/google_gmail_mixin.py @@ -16,7 +16,6 @@ class GoogleGmailMixin(models.AbstractModel): _SERVICE_SCOPE = 'https://mail.google.com/' - use_google_gmail_service = fields.Boolean('Gmail Authentication') google_gmail_authorization_code = fields.Char(string='Authorization Code', groups='base.group_system') google_gmail_refresh_token = fields.Char(string='Refresh Token', groups='base.group_system') google_gmail_access_token = fields.Char(string='Access Token', groups='base.group_system') diff --git a/addons/google_gmail/models/ir_mail_server.py b/addons/google_gmail/models/ir_mail_server.py index 5f6dd40f54a..97af27957b1 100644 --- a/addons/google_gmail/models/ir_mail_server.py +++ b/addons/google_gmail/models/ir_mail_server.py @@ -3,7 +3,7 @@ import base64 -from odoo import models, api +from odoo import fields, models, api class IrMailServer(models.Model): @@ -12,17 +12,20 @@ class IrMailServer(models.Model): _name = 'ir.mail_server' _inherit = ['ir.mail_server', 'google.gmail.mixin'] + smtp_authentication = fields.Selection( + selection_add=[('gmail', 'Gmail OAuth Authentication')], + ondelete={'gmail': 'set default'}) + @api.onchange('smtp_encryption') def _onchange_encryption(self): """Do not change the SMTP configuration if it's a Gmail server - (e.g. the port which is already set)""" - if not self.use_google_gmail_service: - super()._onchange_encryption() + if self.smtp_authentication != 'gmail': + super(IrMailServer, self)._onchange_encryption() - @api.onchange('use_google_gmail_service') - def _onchange_use_google_gmail_service(self): - if self.use_google_gmail_service: + @api.onchange('smtp_authentication') + def _onchange_smtp_authentication(self): + if self.smtp_authentication == 'gmail': self.smtp_host = 'smtp.gmail.com' self.smtp_encryption = 'starttls' self.smtp_port = 587 @@ -34,10 +37,10 @@ class IrMailServer(models.Model): self.google_gmail_access_token_expiration = False def _smtp_login(self, connection, smtp_user, smtp_password): - if len(self) == 1 and self.use_google_gmail_service: + if len(self) == 1 and self.smtp_authentication == 'gmail': auth_string = self._generate_oauth2_string(smtp_user, self.google_gmail_refresh_token) oauth_param = base64.b64encode(auth_string.encode()).decode() connection.ehlo() - connection.docmd('AUTH', 'XOAUTH2 %s' % oauth_param) + connection.docmd('AUTH', f'XOAUTH2 {oauth_param}') else: super(IrMailServer, self)._smtp_login(connection, smtp_user, smtp_password) diff --git a/addons/google_gmail/views/ir_mail_server_views.xml b/addons/google_gmail/views/ir_mail_server_views.xml index 90e4bba4a34..d8755f71386 100644 --- a/addons/google_gmail/views/ir_mail_server_views.xml +++ b/addons/google_gmail/views/ir_mail_server_views.xml @@ -5,26 +5,25 @@ ir.mail_server - - - + attrs="{'required': [('smtp_authentication', '=', 'gmail')], 'invisible': [('smtp_authentication', '!=', 'gmail')]}"/> + + {'invisible' : [('smtp_authentication', '!=', 'login'), ('smtp_authentication', '!=', 'gmail')]} + - {'invisible' : [('use_google_gmail_service', '=', True)]} + {'invisible' : [('smtp_authentication', '=', 'gmail')]} diff --git a/addons/google_gmail/views/res_config_settings_views.xml b/addons/google_gmail/views/res_config_settings_views.xml index 236edf7e1d9..d2744864ccc 100644 --- a/addons/google_gmail/views/res_config_settings_views.xml +++ b/addons/google_gmail/views/res_config_settings_views.xml @@ -6,25 +6,14 @@ res.config.settings -
-
-
- Gmail Credentials -
- Send and receive email with your Gmail account. -
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/addons/mail/models/res_config_settings.py b/addons/mail/models/res_config_settings.py index 6626b9fc192..04e6769c969 100644 --- a/addons/mail/models/res_config_settings.py +++ b/addons/mail/models/res_config_settings.py @@ -15,6 +15,7 @@ class ResConfigSettings(models.TransientModel): alias_domain = fields.Char( 'Alias Domain', config_parameter='mail.catchall.domain', help="If you have setup a catch-all email domain redirected to the Odoo server, enter the domain name here.") + module_google_gmail = fields.Boolean('Support Gmail Authentication') restrict_template_rendering = fields.Boolean( 'Restrict Template Rendering', config_parameter='mail.restrict.template.rendering', diff --git a/addons/mail/views/res_config_settings_views.xml b/addons/mail/views/res_config_settings_views.xml index 343f707c032..69e5ae4e432 100644 --- a/addons/mail/views/res_config_settings_views.xml +++ b/addons/mail/views/res_config_settings_views.xml @@ -66,6 +66,22 @@
+
Custom ICE server list diff --git a/odoo/addons/base/models/ir_mail_server.py b/odoo/addons/base/models/ir_mail_server.py index 0ff6bb2a7b4..79b678c6605 100644 --- a/odoo/addons/base/models/ir_mail_server.py +++ b/odoo/addons/base/models/ir_mail_server.py @@ -233,12 +233,12 @@ class IrMailServer(models.Model): if mail_server: smtp_server = mail_server.smtp_host smtp_port = mail_server.smtp_port - if mail_server.smtp_authentication == "login": - smtp_user = mail_server.smtp_user - smtp_password = mail_server.smtp_pass - else: + if mail_server.smtp_authentication == "certificate": smtp_user = None smtp_password = None + else: + smtp_user = mail_server.smtp_user + smtp_password = mail_server.smtp_pass smtp_encryption = mail_server.smtp_encryption smtp_debug = smtp_debug or mail_server.smtp_debug from_filter = mail_server.from_filter