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',
|
'license': 'OPL-1',
|
||||||
'author': 'BeMade',
|
'author': 'BeMade',
|
||||||
'website': 'https://www.bemade.org',
|
'website': 'https://www.bemade.org',
|
||||||
'depends': ['mail', 'bemade_user_password_bundle'],
|
'depends': ['hr', 'mail', 'bemade_user_password_bundle'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'views/res_config_settings_views.xml',
|
'views/res_config_settings_views.xml',
|
||||||
|
|
@ -31,6 +31,11 @@ Main Features:
|
||||||
'views/res_users_views.xml',
|
'views/res_users_views.xml',
|
||||||
|
|
||||||
],
|
],
|
||||||
|
"assets": {
|
||||||
|
"web.assets_backend": [
|
||||||
|
"bemade_mailcow_blacklist/static/src/js/mailcow_mailbox.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
'demo': [],
|
'demo': [],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': False,
|
'application': False,
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,25 @@ class MailAlias(models.Model):
|
||||||
|
|
||||||
mailcow_id = fields.One2many('mail.mailcow.alias', 'alias_id')
|
mailcow_id = fields.One2many('mail.mailcow.alias', 'alias_id')
|
||||||
|
|
||||||
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
alias = super(MailAlias, self).create(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:
|
if mailcow_alias:
|
||||||
mailcow_alias.write({'active': True})
|
mailcow_alias.write({'active': True})
|
||||||
else:
|
else:
|
||||||
self.env['mail.mailcow.alias'].create({
|
self.env['mail.mailcow.alias'].create({
|
||||||
'address': alias.alias_name + '@' + alias.alias_domain,
|
'address': alias.alias_name + '@' + alias_domain,
|
||||||
'goto': alias.alias_defaults.get('email_from', False),
|
'goto': catchall_alias + '@' + alias_domain,
|
||||||
'alias_id': alias.id,
|
'alias_id': alias.id,
|
||||||
})
|
})
|
||||||
return alias
|
return alias
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from odoo import models, fields, api, exceptions
|
from odoo import models, fields, api, _
|
||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -10,15 +12,29 @@ class MailMailcow(models.AbstractModel):
|
||||||
_name = 'mail.mailcow'
|
_name = 'mail.mailcow'
|
||||||
_description = 'Mailcow API'
|
_description = 'Mailcow API'
|
||||||
|
|
||||||
|
@property
|
||||||
def get_credentials(self):
|
def get_credentials(self):
|
||||||
params = self.env['ir.config_parameter'].sudo()
|
params = self.env['ir.config_parameter'].sudo()
|
||||||
return {
|
|
||||||
'base_url': params.get_param('mailcow.base_url'),
|
base_url = params.get_param('mailcow.base_url'),
|
||||||
'api_key': params.get_param('mailcow.api_key'),
|
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):
|
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
|
url = creds['base_url'] + endpoint
|
||||||
headers = {
|
headers = {
|
||||||
'accept': 'application/json',
|
'accept': 'application/json',
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,10 @@ class MailcowAlias(models.Model):
|
||||||
"private_comment": f"Created by {self.env.user.name} on {fields.Datetime.now()}",
|
"private_comment": f"Created by {self.env.user.name} on {fields.Datetime.now()}",
|
||||||
"public_comment": "Alias created in Odoo"
|
"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:
|
if not result:
|
||||||
raise ValidationError(_("Failed to create alias on Mailcow server."))
|
#pass
|
||||||
|
raise ValidationError("Failed to create alias on Mailcow server.")
|
||||||
|
|
||||||
return alias
|
return alias
|
||||||
|
|
||||||
|
|
@ -59,7 +60,7 @@ class MailcowAlias(models.Model):
|
||||||
},
|
},
|
||||||
"items": [record.mc_id]
|
"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:
|
if not result:
|
||||||
raise ValidationError(_("Failed to update alias on Mailcow server."))
|
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
|
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.
|
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)
|
mailcow_aliases = self.api_request(endpoint)
|
||||||
|
|
||||||
if not mailcow_aliases:
|
if not mailcow_aliases:
|
||||||
|
|
@ -80,6 +81,7 @@ class MailcowAlias(models.Model):
|
||||||
|
|
||||||
for mc_alias in mailcow_aliases:
|
for mc_alias in mailcow_aliases:
|
||||||
domain = mc_alias['domain']
|
domain = mc_alias['domain']
|
||||||
|
|
||||||
alias_domain = self.env['ir.config_parameter'].sudo().get_param('mail.catchall.domain')
|
alias_domain = self.env['ir.config_parameter'].sudo().get_param('mail.catchall.domain')
|
||||||
if domain == alias_domain:
|
if domain == alias_domain:
|
||||||
alias = self.search([('address', '=', mc_alias['address'])], limit=1)
|
alias = self.search([('address', '=', mc_alias['address'])], limit=1)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ class MailcowBlacklist(models.Model):
|
||||||
_description = 'Mailcow Blacklist'
|
_description = 'Mailcow Blacklist'
|
||||||
_inherit = ['mail.mailcow', 'mail.thread', 'mail.activity.mixin']
|
_inherit = ['mail.mailcow', 'mail.thread', 'mail.activity.mixin']
|
||||||
|
|
||||||
email = fields.Char(string='Email', required=True, track_visibility='onchange')
|
email = fields.Char(string='Email', required=True, tracking=True)
|
||||||
prefid = fields.Integer(string='Mailcow ID', required=True, track_visibility='onchange')
|
prefid = fields.Integer(string='Mailcow ID', required=True, tracking=True)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
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.
|
Overridden create method to add the new blacklist entry to the Mailcow server.
|
||||||
"""
|
"""
|
||||||
res = super().create(vals)
|
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_add = '/api/v1/add/domain-policy'
|
||||||
endpoint_get_bl = f"api/v1/get/policy_bl_domain/{domain}"
|
endpoint_get_bl = f"/api/v1/get/policy_bl_domain/{domain}"
|
||||||
data = {
|
data = {
|
||||||
'domain': domain,
|
'domain': domain,
|
||||||
'object_from': res.email,
|
'object_from': res.email,
|
||||||
|
|
@ -42,8 +42,8 @@ class MailcowBlacklist(models.Model):
|
||||||
old_email = self.email
|
old_email = self.email
|
||||||
res = super().write(vals)
|
res = super().write(vals)
|
||||||
if 'email' in vals:
|
if 'email' in vals:
|
||||||
delete_endpoint = 'api/v1/delete/domain-policy'
|
delete_endpoint = '/api/v1/delete/domain-policy'
|
||||||
add_endpoint = 'api/v1/add/domain-policy'
|
add_endpoint = '/api/v1/add/domain-policy'
|
||||||
delete_data = {
|
delete_data = {
|
||||||
'items': [old_email]
|
'items': [old_email]
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ class MailcowBlacklist(models.Model):
|
||||||
Overridden unlink method to remove the blacklist entry from the Mailcow server.
|
Overridden unlink method to remove the blacklist entry from the Mailcow server.
|
||||||
"""
|
"""
|
||||||
for record in self:
|
for record in self:
|
||||||
endpoint = 'api/v1/delete/blacklist'
|
endpoint = '/api/v1/delete/blacklist'
|
||||||
data = {
|
data = {
|
||||||
'items': [record.email]
|
'items': [record.email]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,16 @@ class MailcowMailbox(models.Model):
|
||||||
_inherit = ['mail.mailcow', 'mail.thread', 'mail.activity.mixin']
|
_inherit = ['mail.mailcow', 'mail.thread', 'mail.activity.mixin']
|
||||||
_description = 'Mailcow Mailbox'
|
_description = 'Mailcow Mailbox'
|
||||||
|
|
||||||
name = fields.Char(track_visibility='onchange')
|
def _default_domain(self):
|
||||||
address = fields.Char(compute='_compute_address', store=True, readonly=True, track_visibility='onchange')
|
return self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain")
|
||||||
local_part = fields.Char(required=True, track_visibility='onchange')
|
|
||||||
domain = fields.Char(required=True, track_visibility='onchange')
|
name = fields.Char(tracking=True)
|
||||||
active = fields.Boolean(default=True, track_visibility='onchange')
|
address = fields.Char(compute='_compute_address', store=True, readonly=True, tracking=True)
|
||||||
user_id = fields.Many2one('res.users', ondelete='cascade', track_visibility='onchange')
|
local_part = fields.Char(required=True, tracking=True)
|
||||||
password = fields.Char(readonly=True, track_visibility='onchange')
|
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')
|
@api.depends('local_part', 'domain')
|
||||||
def _compute_address(self):
|
def _compute_address(self):
|
||||||
|
|
@ -28,7 +31,7 @@ class MailcowMailbox(models.Model):
|
||||||
"""
|
"""
|
||||||
Synchronize Mailcow mailboxes with Odoo
|
Synchronize Mailcow mailboxes with Odoo
|
||||||
"""
|
"""
|
||||||
endpoint = 'api/v1/get/mailbox/all'
|
endpoint = '/api/v1/get/mailbox/all'
|
||||||
data = self.api_request(endpoint)
|
data = self.api_request(endpoint)
|
||||||
if data:
|
if data:
|
||||||
for item in data:
|
for item in data:
|
||||||
|
|
@ -51,12 +54,12 @@ class MailcowMailbox(models.Model):
|
||||||
vals['password'] = password
|
vals['password'] = password
|
||||||
|
|
||||||
# Check if email exists on Mailcow
|
# 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)
|
response = self.api_request(endpoint)
|
||||||
|
|
||||||
if not response:
|
if not response:
|
||||||
# If email does not exist on Mailcow, create it
|
# If email does not exist on Mailcow, create it
|
||||||
endpoint = 'api/v1/add/mailbox'
|
endpoint = '/api/v1/add/mailbox'
|
||||||
data = {
|
data = {
|
||||||
'local_part': vals['local_part'],
|
'local_part': vals['local_part'],
|
||||||
'domain': vals['domain'],
|
'domain': vals['domain'],
|
||||||
|
|
@ -70,7 +73,7 @@ class MailcowMailbox(models.Model):
|
||||||
'tls_enforce_out': "0",
|
'tls_enforce_out': "0",
|
||||||
}
|
}
|
||||||
self.api_request(endpoint, method='POST', data=data)
|
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)
|
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.
|
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:
|
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 = {
|
data = {
|
||||||
'items': [self.address],
|
'items': [self.address],
|
||||||
'attr': {
|
'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.
|
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')
|
self.api_request(endpoint, method='POST')
|
||||||
_logger.info(f'Mailbox {self.address} has been deleted on Mailcow server')
|
_logger.info(f'Mailbox {self.address} has been deleted on Mailcow server')
|
||||||
|
|
||||||
|
|
@ -119,7 +122,7 @@ class MailcowMailbox(models.Model):
|
||||||
'name': user.name,
|
'name': user.name,
|
||||||
'password': user.password,
|
'password': user.password,
|
||||||
}
|
}
|
||||||
endpoint = 'api/v1/add/mailbox'
|
endpoint = '/api/v1/add/mailbox'
|
||||||
self.api_request(endpoint, method='POST', data=data)
|
self.api_request(endpoint, method='POST', data=data)
|
||||||
_logger.info(f'Mailbox for user {user.login} has been created on Mailcow server')
|
_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)
|
mailcow_mailbox = fields.Boolean(string='Mailcow Mailbox', default=False)
|
||||||
|
|
||||||
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
res = super(ResUsers, self).create(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)
|
self.env['mail.mailcow.mailbox'].create_mailbox_for_user(res)
|
||||||
|
|
||||||
return 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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<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="name">mailcow.mailbox.view.tree</field>
|
||||||
<field name="model">mail.mailcow.mailbox</field>
|
<field name="model">mail.mailcow.mailbox</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Mailbox" decoration-info="active == False">
|
<tree string="Mailbox" decoration-info="active == False">
|
||||||
|
<header>
|
||||||
|
<button name="sync_mailboxes" string="Sync with Mailcow" type="object"/>
|
||||||
|
</header>
|
||||||
<field name="active"/>
|
<field name="active"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="local_part"/>
|
<field name="local_part"/>
|
||||||
|
|
@ -39,7 +42,7 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</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="name">Mailboxes</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">mail.mailcow.mailbox</field>
|
<field name="res_model">mail.mailcow.mailbox</field>
|
||||||
|
|
@ -62,6 +65,21 @@
|
||||||
<menuitem id="mailcow_menu_mailbox"
|
<menuitem id="mailcow_menu_mailbox"
|
||||||
name="Mailboxes"
|
name="Mailboxes"
|
||||||
parent="mailcow_menu"
|
parent="mailcow_menu"
|
||||||
action="mailcow_mailbox_action"
|
action="action_mailcow_mailbox"
|
||||||
sequence="10"/>
|
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>
|
</odoo>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue