marc look at .repos/bemade-addons/bemade_mailcow_blacklist/static/src/js/mailcow_mailbox.js please
This commit is contained in:
parent
68dd96a5a8
commit
ed021edc40
11 changed files with 138 additions and 40 deletions
|
|
@ -21,7 +21,7 @@ Main Features:
|
|||
'license': 'OPL-1',
|
||||
'author': 'BeMade',
|
||||
'website': 'https://www.bemade.org',
|
||||
'depends': ['mail', 'bemade_user_password_bundle'],
|
||||
'depends': ['hr', 'mail', 'bemade_user_password_bundle'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/res_config_settings_views.xml',
|
||||
|
|
@ -31,6 +31,11 @@ Main Features:
|
|||
'views/res_users_views.xml',
|
||||
|
||||
],
|
||||
"assets": {
|
||||
"web.assets_backend": [
|
||||
"bemade_mailcow_blacklist/static/src/js/mailcow_mailbox.js"
|
||||
]
|
||||
},
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
|
|
|
|||
|
|
@ -6,15 +6,25 @@ class MailAlias(models.Model):
|
|||
|
||||
mailcow_id = fields.One2many('mail.mailcow.alias', 'alias_id')
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
alias = super(MailAlias, self).create(vals)
|
||||
mailcow_alias = self.env['mail.mailcow.alias'].search([('address', '=', alias.alias_name + '@' + alias.alias_domain)])
|
||||
|
||||
alias_domain = self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"),
|
||||
catchall_alias = self.env["ir.config_parameter"].sudo().get_param("mail.catchall.alias"),
|
||||
|
||||
alias_domain = alias_domain[0]
|
||||
catchall_alias = catchall_alias[0]
|
||||
|
||||
if not alias_domain:
|
||||
raise ValidationError(_("No catchall domain is set in the system parameters. Please set one and try again."))
|
||||
mailcow_alias = self.env['mail.mailcow.alias'].search([('address', '=', alias.alias_name + '@' + alias_domain)])
|
||||
if mailcow_alias:
|
||||
mailcow_alias.write({'active': True})
|
||||
else:
|
||||
self.env['mail.mailcow.alias'].create({
|
||||
'address': alias.alias_name + '@' + alias.alias_domain,
|
||||
'goto': alias.alias_defaults.get('email_from', False),
|
||||
'address': alias.alias_name + '@' + alias_domain,
|
||||
'goto': catchall_alias + '@' + alias_domain,
|
||||
'alias_id': alias.id,
|
||||
})
|
||||
return alias
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, exceptions
|
||||
from odoo import models, fields, api, _
|
||||
import requests
|
||||
import logging
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -10,15 +12,29 @@ class MailMailcow(models.AbstractModel):
|
|||
_name = 'mail.mailcow'
|
||||
_description = 'Mailcow API'
|
||||
|
||||
@property
|
||||
def get_credentials(self):
|
||||
params = self.env['ir.config_parameter'].sudo()
|
||||
return {
|
||||
'base_url': params.get_param('mailcow.base_url'),
|
||||
'api_key': params.get_param('mailcow.api_key'),
|
||||
}
|
||||
|
||||
base_url = params.get_param('mailcow.base_url'),
|
||||
base_url = base_url[0]
|
||||
api_key = params.get_param('mailcow.api_key'),
|
||||
api_key = api_key[0]
|
||||
|
||||
if not base_url or not api_key:
|
||||
_logger.error('No API key or base URL is set in the system parameters')
|
||||
raise ValidationError(_("No API key or base URL is set in the system parameters. Please set one and try again."))
|
||||
# return False
|
||||
else:
|
||||
return {
|
||||
'base_url': base_url,
|
||||
'api_key': api_key
|
||||
}
|
||||
|
||||
def api_request(self, endpoint, method='GET', data=None):
|
||||
creds = self.get_credentials()
|
||||
creds = self.get_credentials
|
||||
if not creds:
|
||||
return False
|
||||
url = creds['base_url'] + endpoint
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@ class MailcowAlias(models.Model):
|
|||
"private_comment": f"Created by {self.env.user.name} on {fields.Datetime.now()}",
|
||||
"public_comment": "Alias created in Odoo"
|
||||
}
|
||||
result = self.env['mail.mailcow'].api_request('api/v1/add/alias', 'POST', data)
|
||||
result = self.env['mail.mailcow'].api_request('/api/v1/add/alias', 'POST', data)
|
||||
if not result:
|
||||
raise ValidationError(_("Failed to create alias on Mailcow server."))
|
||||
#pass
|
||||
raise ValidationError("Failed to create alias on Mailcow server.")
|
||||
|
||||
return alias
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ class MailcowAlias(models.Model):
|
|||
},
|
||||
"items": [record.mc_id]
|
||||
}
|
||||
result = self.env['mail.mailcow'].api_request('api/v1/edit/alias', 'POST', data)
|
||||
result = self.env['mail.mailcow'].api_request('/api/v1/edit/alias', 'POST', data)
|
||||
if not result:
|
||||
raise ValidationError(_("Failed to update alias on Mailcow server."))
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ class MailcowAlias(models.Model):
|
|||
For each alias fetched from Mailcow server, it tries to find a matching record
|
||||
in Odoo. If it doesn't exist, it creates a new record.
|
||||
"""
|
||||
endpoint = 'api/v1/get/alias/all'
|
||||
endpoint = '/api/v1/get/alias/all'
|
||||
mailcow_aliases = self.api_request(endpoint)
|
||||
|
||||
if not mailcow_aliases:
|
||||
|
|
@ -80,6 +81,7 @@ class MailcowAlias(models.Model):
|
|||
|
||||
for mc_alias in mailcow_aliases:
|
||||
domain = mc_alias['domain']
|
||||
|
||||
alias_domain = self.env['ir.config_parameter'].sudo().get_param('mail.catchall.domain')
|
||||
if domain == alias_domain:
|
||||
alias = self.search([('address', '=', mc_alias['address'])], limit=1)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ class MailcowBlacklist(models.Model):
|
|||
_description = 'Mailcow Blacklist'
|
||||
_inherit = ['mail.mailcow', 'mail.thread', 'mail.activity.mixin']
|
||||
|
||||
email = fields.Char(string='Email', required=True, track_visibility='onchange')
|
||||
prefid = fields.Integer(string='Mailcow ID', required=True, track_visibility='onchange')
|
||||
email = fields.Char(string='Email', required=True, tracking=True)
|
||||
prefid = fields.Integer(string='Mailcow ID', required=True, tracking=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
|
|
@ -19,10 +19,10 @@ class MailcowBlacklist(models.Model):
|
|||
Overridden create method to add the new blacklist entry to the Mailcow server.
|
||||
"""
|
||||
res = super().create(vals)
|
||||
domain = self.env['res.config.settings'].get_values()['mail.catchall.domain']
|
||||
domain = self.env['ir.config_parameter'].sudo().get_param('mail.catchall.domain')
|
||||
|
||||
endpoint_add = 'api/v1/add/domain-policy'
|
||||
endpoint_get_bl = f"api/v1/get/policy_bl_domain/{domain}"
|
||||
endpoint_add = '/api/v1/add/domain-policy'
|
||||
endpoint_get_bl = f"/api/v1/get/policy_bl_domain/{domain}"
|
||||
data = {
|
||||
'domain': domain,
|
||||
'object_from': res.email,
|
||||
|
|
@ -42,8 +42,8 @@ class MailcowBlacklist(models.Model):
|
|||
old_email = self.email
|
||||
res = super().write(vals)
|
||||
if 'email' in vals:
|
||||
delete_endpoint = 'api/v1/delete/domain-policy'
|
||||
add_endpoint = 'api/v1/add/domain-policy'
|
||||
delete_endpoint = '/api/v1/delete/domain-policy'
|
||||
add_endpoint = '/api/v1/add/domain-policy'
|
||||
delete_data = {
|
||||
'items': [old_email]
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ class MailcowBlacklist(models.Model):
|
|||
Overridden unlink method to remove the blacklist entry from the Mailcow server.
|
||||
"""
|
||||
for record in self:
|
||||
endpoint = 'api/v1/delete/blacklist'
|
||||
endpoint = '/api/v1/delete/blacklist'
|
||||
data = {
|
||||
'items': [record.email]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,16 @@ class MailcowMailbox(models.Model):
|
|||
_inherit = ['mail.mailcow', 'mail.thread', 'mail.activity.mixin']
|
||||
_description = 'Mailcow Mailbox'
|
||||
|
||||
name = fields.Char(track_visibility='onchange')
|
||||
address = fields.Char(compute='_compute_address', store=True, readonly=True, track_visibility='onchange')
|
||||
local_part = fields.Char(required=True, track_visibility='onchange')
|
||||
domain = fields.Char(required=True, track_visibility='onchange')
|
||||
active = fields.Boolean(default=True, track_visibility='onchange')
|
||||
user_id = fields.Many2one('res.users', ondelete='cascade', track_visibility='onchange')
|
||||
password = fields.Char(readonly=True, track_visibility='onchange')
|
||||
def _default_domain(self):
|
||||
return self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain")
|
||||
|
||||
name = fields.Char(tracking=True)
|
||||
address = fields.Char(compute='_compute_address', store=True, readonly=True, tracking=True)
|
||||
local_part = fields.Char(required=True, tracking=True)
|
||||
domain = fields.Char(required=True, tracking=True, default=_default_domain)
|
||||
active = fields.Boolean(default=True, tracking=True)
|
||||
user_id = fields.Many2one('res.users', ondelete='cascade', tracking=True)
|
||||
password = fields.Char(readonly=True, tracking=True)
|
||||
|
||||
@api.depends('local_part', 'domain')
|
||||
def _compute_address(self):
|
||||
|
|
@ -28,7 +31,7 @@ class MailcowMailbox(models.Model):
|
|||
"""
|
||||
Synchronize Mailcow mailboxes with Odoo
|
||||
"""
|
||||
endpoint = 'api/v1/get/mailbox/all'
|
||||
endpoint = '/api/v1/get/mailbox/all'
|
||||
data = self.api_request(endpoint)
|
||||
if data:
|
||||
for item in data:
|
||||
|
|
@ -51,12 +54,12 @@ class MailcowMailbox(models.Model):
|
|||
vals['password'] = password
|
||||
|
||||
# Check if email exists on Mailcow
|
||||
endpoint = f"api/v1/get/mailbox/{vals['address']}"
|
||||
endpoint = f"/api/v1/get/mailbox/{vals['local_part']}@{vals['domain']}"
|
||||
response = self.api_request(endpoint)
|
||||
|
||||
if not response:
|
||||
# If email does not exist on Mailcow, create it
|
||||
endpoint = 'api/v1/add/mailbox'
|
||||
endpoint = '/api/v1/add/mailbox'
|
||||
data = {
|
||||
'local_part': vals['local_part'],
|
||||
'domain': vals['domain'],
|
||||
|
|
@ -70,7 +73,7 @@ class MailcowMailbox(models.Model):
|
|||
'tls_enforce_out': "0",
|
||||
}
|
||||
self.api_request(endpoint, method='POST', data=data)
|
||||
_logger.info(f'Mailbox {vals["address"]} has been created on Mailcow server')
|
||||
_logger.info(f"Mailbox {vals['local_part']}@{vals['domain']} has been created on Mailcow server")
|
||||
|
||||
return super().create(vals)
|
||||
|
||||
|
|
@ -79,7 +82,7 @@ class MailcowMailbox(models.Model):
|
|||
Override the write function to update a Mailcow mailbox whenever a user is updated in Odoo.
|
||||
"""
|
||||
if 'active' in vals or 'local_part' in vals or 'domain' in vals:
|
||||
endpoint = f'api/v1/edit/mailbox/{self.address}'
|
||||
endpoint = f'/api/v1/edit/mailbox/{self.address}'
|
||||
data = {
|
||||
'items': [self.address],
|
||||
'attr': {
|
||||
|
|
@ -97,7 +100,7 @@ class MailcowMailbox(models.Model):
|
|||
"""
|
||||
Override the unlink function to delete a Mailcow mailbox whenever a user is deleted in Odoo.
|
||||
"""
|
||||
endpoint = f'api/v1/delete/mailbox/{self.address}'
|
||||
endpoint = f'/api/v1/delete/mailbox/{self.address}'
|
||||
self.api_request(endpoint, method='POST')
|
||||
_logger.info(f'Mailbox {self.address} has been deleted on Mailcow server')
|
||||
|
||||
|
|
@ -119,7 +122,7 @@ class MailcowMailbox(models.Model):
|
|||
'name': user.name,
|
||||
'password': user.password,
|
||||
}
|
||||
endpoint = 'api/v1/add/mailbox'
|
||||
endpoint = '/api/v1/add/mailbox'
|
||||
self.api_request(endpoint, method='POST', data=data)
|
||||
_logger.info(f'Mailbox for user {user.login} has been created on Mailcow server')
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ class ResUsers(models.Model):
|
|||
|
||||
mailcow_mailbox = fields.Boolean(string='Mailcow Mailbox', default=False)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(ResUsers, self).create(vals)
|
||||
|
||||
if vals.get('mailcow_mailbox'):
|
||||
if vals.get('mailcow_mailbox', false):
|
||||
self.env['mail.mailcow.mailbox'].create_mailbox_for_user(res)
|
||||
|
||||
return res
|
||||
|
|
|
|||
30
bemade_mailcow_blacklist/static/src/js/mailcow_mailbox.js
Normal file
30
bemade_mailcow_blacklist/static/src/js/mailcow_mailbox.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
odoo.define('bemade_mailcow_blacklist.mailcow_mailbox', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var ListController = require('web.ListController');
|
||||
var ListView = require('web.ListView');
|
||||
var viewRegistry = require('web.view_registry');
|
||||
|
||||
var MailboxesListController = ListController.extend({
|
||||
buttons_template: 'mail.mailcow_mailbox_list_view_buttons',
|
||||
events: _.extend({}, ListController.prototype.events, {
|
||||
'click .o_button_sync_mailboxes': '_onSyncMailboxes',
|
||||
}),
|
||||
_onSyncMailboxes: function () {
|
||||
this._rpc({
|
||||
model: 'mail.mailcow.mailbox',
|
||||
method: 'sync_mailboxes',
|
||||
args: [],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
var MailboxesListView = ListView.extend({
|
||||
config: _.extend({}, ListView.prototype.config, {
|
||||
Controller: MailboxesListController,
|
||||
}),
|
||||
});
|
||||
|
||||
viewRegistry.add('mail.mailcow.mailbox', MailboxesListView);
|
||||
});
|
||||
1
bemade_mailcow_blacklist/tests/__init__.py
Normal file
1
bemade_mailcow_blacklist/tests/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from . import test_mailcow
|
||||
12
bemade_mailcow_blacklist/tests/test_mailcow.py
Normal file
12
bemade_mailcow_blacklist/tests/test_mailcow.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
from odoo.tests.common import TransactionCase, tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestMailcow(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
def test_new_mail_alias(self):
|
||||
model_id = self.env['ir.model']._get('res.partner').id
|
||||
self.alias = self.env['mail.alias'].create({'alias_name': 'test', 'alias_model_id': model_id})
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mailcow_mailbox_view_tree" model="ir.ui.view">
|
||||
<record id="view_mailcow_mailbox_tree" model="ir.ui.view">
|
||||
<field name="name">mailcow.mailbox.view.tree</field>
|
||||
<field name="model">mail.mailcow.mailbox</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Mailbox" decoration-info="active == False">
|
||||
<header>
|
||||
<button name="sync_mailboxes" string="Sync with Mailcow" type="object"/>
|
||||
</header>
|
||||
<field name="active"/>
|
||||
<field name="name"/>
|
||||
<field name="local_part"/>
|
||||
|
|
@ -39,7 +42,7 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mailcow_mailbox_action" model="ir.actions.act_window">
|
||||
<record id="action_mailcow_mailbox" model="ir.actions.act_window">
|
||||
<field name="name">Mailboxes</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mail.mailcow.mailbox</field>
|
||||
|
|
@ -62,6 +65,21 @@
|
|||
<menuitem id="mailcow_menu_mailbox"
|
||||
name="Mailboxes"
|
||||
parent="mailcow_menu"
|
||||
action="mailcow_mailbox_action"
|
||||
action="action_mailcow_mailbox"
|
||||
sequence="10"/>
|
||||
|
||||
<record id="action_server_sync_mailboxes" model="ir.actions.server">
|
||||
<field name="name">Sync Mailboxes</field>
|
||||
<field name="model_id" ref="model_mail_mailcow_mailbox"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.sync_mailboxes()</field>
|
||||
</record>
|
||||
|
||||
<record id="action_sync_mailboxes" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="act_window_id" ref="action_mailcow_mailbox"/>
|
||||
<field name="view_id" ref="view_mailcow_mailbox_tree"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
|
|||
Loading…
Reference in a new issue