-
Notifications
You must be signed in to change notification settings - Fork 24k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ADD] fetchmail_outlook, microsoft_outlook: add OAuth authentication
Purpose ======= As it has been done for Gmail, we want to add the OAuth authentication for the incoming / outgoing mail server. Specifications ============== The user has to create a project on Outlook and fill the credentials in Odoo. Once it's done, he can create an incoming / outgoing mail server. For the authentication flow is a bit different from Gmail. For Outlook the user is redirected to Outlook where he'll accept the permission. Once it's done, he's redirected again to the mail server form view and the tokens are automatically added on the mail server. Technical ========= There are 3 tokens used for the OAuth authentication. 1. The authentication code. This one is only used to get the refresh token and the first access token. It's the code returned by the user browser during the authentication flow. 2. The refresh token. This one will never change once the user is authenticated. This token is used to get new access token once they are expired. 3. The access token. Those tokens have an expiration date (1 hour) and are used in the XOAUTH2 protocol to authenticate the IMAP / SMTP connection. During the authentication process, we can also give a state that will be returned by the user browser. This state contains 1. The model and the ID of the mail server (as the same mixin manage both incoming and outgoing mail server) 2. A CSRF token which sign those values and is verified once the browser redirect the user to the Odoo database. This is useful so a malicious user can not send a link to an admin to disconnect the mail server. Task-2751996 X-original-commit: e54d63b Part-of: #87294
- Loading branch information
Showing
24 changed files
with
944 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
{ | ||
"name": "Fetchmail Outlook", | ||
"version": "1.0", | ||
"category": "Hidden", | ||
"description": "OAuth authentication for incoming Outlook mail server", | ||
"depends": [ | ||
"microsoft_outlook", | ||
"fetchmail", | ||
], | ||
"data": [ | ||
"views/fetchmail_server_views.xml", | ||
], | ||
"auto_install": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * fetchmail_outlook | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 13.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2022-03-25 15:26+0000\n" | ||
"PO-Revision-Date: 2022-03-25 15:26+0000\n" | ||
"Last-Translator: \n" | ||
"Language-Team: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: \n" | ||
|
||
#. module: fetchmail_outlook | ||
#: model_terms:ir.ui.view,arch_db:fetchmail_outlook.fetchmail_server_view_form | ||
msgid "" | ||
"<i class=\"fa fa-arrow-right\"/>\n" | ||
" Connect your Outlook account" | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: model_terms:ir.ui.view,arch_db:fetchmail_outlook.fetchmail_server_view_form | ||
msgid "" | ||
"<i class=\"fa fa-cog\"/>\n" | ||
" Edit Settings" | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: model_terms:ir.ui.view,arch_db:fetchmail_outlook.fetchmail_server_view_form | ||
msgid "" | ||
"<span attrs=\"{'invisible': ['|', ('use_microsoft_outlook_service', '=', False), ('microsoft_outlook_refresh_token', '=', False)]}\" class=\"badge badge-success\">\n" | ||
" Outlook Token Valid\n" | ||
" </span>" | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: model:ir.model,name:fetchmail_outlook.model_fetchmail_server | ||
msgid "Incoming Mail Server" | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: model_terms:ir.ui.view,arch_db:fetchmail_outlook.fetchmail_server_view_form | ||
msgid "Outlook" | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: code:addons/fetchmail_outlook/models/fetchmail_server.py:0 | ||
#, python-format | ||
msgid "Outlook mail server %r only supports IMAP server type." | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: code:addons/fetchmail_outlook/models/fetchmail_server.py:0 | ||
#, python-format | ||
msgid "" | ||
"Please leave the password field empty for Outlook mail server %r. The OAuth " | ||
"process does not require it" | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: code:addons/fetchmail_outlook/models/fetchmail_server.py:0 | ||
#, python-format | ||
msgid "SSL is required ." | ||
msgstr "" | ||
|
||
#. module: fetchmail_outlook | ||
#: model_terms:ir.ui.view,arch_db:fetchmail_outlook.fetchmail_server_view_form | ||
msgid "" | ||
"Setup your Outlook API credentials in the general settings to link a Outlook" | ||
" account." | ||
msgstr "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
from . import fetchmail_server |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# -*- 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 | ||
|
||
|
||
class FetchmailServer(models.Model): | ||
"""Add the Outlook OAuth authentication on the incoming mail servers.""" | ||
|
||
_name = 'fetchmail.server' | ||
_inherit = ['fetchmail.server', 'microsoft.outlook.mixin'] | ||
|
||
_OUTLOOK_SCOPE = 'https://outlook.office.com/IMAP.AccessAsUser.All' | ||
|
||
@api.constrains('use_microsoft_outlook_service', 'server_type', 'password', 'is_ssl') | ||
def _check_use_microsoft_outlook_service(self): | ||
for server in self: | ||
if not server.use_microsoft_outlook_service: | ||
continue | ||
|
||
if server.server_type != 'imap': | ||
raise UserError(_('Outlook mail server %r only supports IMAP server type.') % server.name) | ||
|
||
if server.password: | ||
raise UserError(_( | ||
'Please leave the password field empty for Outlook mail server %r. ' | ||
'The OAuth process does not require it') | ||
% server.name) | ||
|
||
if not server.is_ssl: | ||
raise UserError(_('SSL is required .') % server.name) | ||
|
||
@api.onchange('use_microsoft_outlook_service') | ||
def _onchange_use_microsoft_outlook_service(self): | ||
"""Set the default configuration for a IMAP Outlook server.""" | ||
if self.use_microsoft_outlook_service: | ||
self.server = 'imap.outlook.com' | ||
self.server_type = 'imap' | ||
self.is_ssl = True | ||
self.port = 993 | ||
else: | ||
self.microsoft_outlook_refresh_token = False | ||
self.microsoft_outlook_access_token = False | ||
self.microsoft_outlook_access_token_expiration = False | ||
|
||
def _imap_login(self, connection): | ||
"""Authenticate the IMAP connection. | ||
If the mail server is Outlook, we use the OAuth2 authentication protocol. | ||
""" | ||
self.ensure_one() | ||
if self.use_microsoft_outlook_service: | ||
auth_string = self._generate_outlook_oauth2_string(self.user) | ||
connection.authenticate('XOAUTH2', lambda x: auth_string) | ||
connection.select('INBOX') | ||
else: | ||
super()._imap_login(connection) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
from . import test_fetchmail_outlook |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
import time | ||
|
||
from unittest.mock import ANY, Mock, patch | ||
|
||
from odoo.exceptions import UserError | ||
from odoo.tests.common import SavepointCase | ||
|
||
|
||
class TestFetchmailOutlook(SavepointCase): | ||
|
||
@patch('odoo.addons.fetchmail.models.fetchmail.IMAP4_SSL') | ||
def test_connect(self, mock_imap): | ||
"""Test that the connect method will use the right | ||
authentication method with the right arguments. | ||
""" | ||
mock_connection = Mock() | ||
mock_imap.return_value = mock_connection | ||
|
||
mail_server = self.env['fetchmail.server'].create({ | ||
'name': 'Test server', | ||
'use_microsoft_outlook_service': True, | ||
'user': 'test@example.com', | ||
'microsoft_outlook_access_token': 'test_access_token', | ||
'microsoft_outlook_access_token_expiration': time.time() + 1000000, | ||
'password': '', | ||
'server_type': 'imap', | ||
'is_ssl': True, | ||
}) | ||
|
||
mail_server.connect() | ||
|
||
mock_connection.authenticate.assert_called_once_with('XOAUTH2', ANY) | ||
args = mock_connection.authenticate.call_args[0] | ||
|
||
self.assertEqual(args[1](None), 'user=test@example.com\1auth=Bearer test_access_token\1\1', | ||
msg='Should use the right access token') | ||
|
||
mock_connection.select.assert_called_once_with('INBOX') | ||
|
||
def test_constraints(self): | ||
"""Test the constraints related to the Outlook mail server.""" | ||
with self.assertRaises(UserError, msg='Should ensure that the password is empty'): | ||
self.env['fetchmail.server'].create({ | ||
'name': 'Test server', | ||
'use_microsoft_outlook_service': True, | ||
'password': 'test', | ||
'server_type': 'imap', | ||
}) | ||
|
||
with self.assertRaises(UserError, msg='Should ensure that the server type is IMAP'): | ||
self.env['fetchmail.server'].create({ | ||
'name': 'Test server', | ||
'use_microsoft_outlook_service': True, | ||
'password': '', | ||
'server_type': 'pop', | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<odoo> | ||
<record id="fetchmail_server_view_form" model="ir.ui.view"> | ||
<field name="name">fetchmail.server.view.form.inherit.outlook</field> | ||
<field name="model">fetchmail.server</field> | ||
<field name="priority">1000</field> | ||
<field name="inherit_id" ref="fetchmail.view_email_server_form"/> | ||
<field name="arch" type="xml"> | ||
<field name="server" position="before"> | ||
<field name="use_microsoft_outlook_service" string="Outlook" | ||
attrs="{'readonly': [('state', '=', 'done')]}"/> | ||
</field> | ||
<field name="user" position="after"> | ||
<field name="is_microsoft_outlook_configured" invisible="1"/> | ||
<field name="microsoft_outlook_refresh_token" invisible="1"/> | ||
<field name="microsoft_outlook_access_token" invisible="1"/> | ||
<field name="microsoft_outlook_access_token_expiration" invisible="1"/> | ||
<div></div> | ||
<div attrs="{'invisible': [('use_microsoft_outlook_service', '=', False)]}"> | ||
<span attrs="{'invisible': ['|', ('use_microsoft_outlook_service', '=', False), ('microsoft_outlook_refresh_token', '=', False)]}" | ||
class="badge badge-success"> | ||
Outlook Token Valid | ||
</span> | ||
<button type="object" | ||
name="open_microsoft_outlook_uri" class="btn-link px-0" | ||
attrs="{'invisible': ['|', '|', '|', ('is_microsoft_outlook_configured', '=', False), ('use_microsoft_outlook_service', '=', False), ('microsoft_outlook_refresh_token', '!=', False)]}"> | ||
<i class="fa fa-arrow-right"/> | ||
Connect your Outlook account | ||
</button> | ||
<button type="object" | ||
name="open_microsoft_outlook_uri" class="btn-link px-0" | ||
attrs="{'invisible': ['|', '|', '|', ('is_microsoft_outlook_configured', '=', False), ('use_microsoft_outlook_service', '=', False), ('microsoft_outlook_refresh_token', '=', False)]}"> | ||
<i class="fa fa-cog"/> | ||
Edit Settings | ||
</button> | ||
<div class="alert alert-warning" role="alert" | ||
attrs="{'invisible': ['|', ('is_microsoft_outlook_configured', '=', True), ('use_microsoft_outlook_service', '=', False)]}"> | ||
Setup your Outlook API credentials in the general settings to link a Outlook account. | ||
</div> | ||
</div> | ||
</field> | ||
<field name="password" position="attributes"> | ||
<attribute name="attrs">{}</attribute> | ||
</field> | ||
</field> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
from . import controllers | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
{ | ||
"name": "Microsoft Outlook", | ||
"version": "1.0", | ||
"category": "Hidden", | ||
"description": "Outlook support for outgoing mail servers", | ||
"depends": [ | ||
"mail", | ||
], | ||
"data": [ | ||
"views/ir_mail_server_views.xml", | ||
"views/res_config_settings_views.xml", | ||
"views/templates.xml", | ||
], | ||
"auto_install": False, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -* | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
from . import main |
Oops, something went wrong.