Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions mail_server_connection_alert/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
===================================
Mail Server Connection Issue Alerts
===================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ee631b7d5ac8dd0a9c3f35d82823af1fc5cdb922db07cc826a767336b443348c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmail-lightgray.png?logo=github
:target: https://github.com/OCA/mail/tree/18.0/mail_server_connection_alert
:alt: OCA/mail
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_server_connection_alert
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/mail&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module periodically checks the connection status of incoming and
outgoing mail servers to detect failures early. It displays prominent
notifications to administrators whenever a mail server configuration
stops working.

It uses the **``web_notify``** module (from
`OCA/web <https://github.com/OCA/web>`__) to display sticky
notifications. It also creates a chatter channel for the same.

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/mail/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/mail/issues/new?body=module:%20mail_server_connection_alert%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* CIT-Services

Contributors
------------

- `CIT-Services <cit-services.eu>`__

- Prayag <prayag.k@cit-services.eu>

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/mail <https://github.com/OCA/mail/tree/18.0/mail_server_connection_alert>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 4 additions & 0 deletions mail_server_connection_alert/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2026 CIT-Services
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import models
18 changes: 18 additions & 0 deletions mail_server_connection_alert/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 CIT-Services
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Mail Server Connection Issue Alerts",
"summary": "Incoming & Outgoing Mail Status Warning",
"version": "18.0.1.0.0",
"category": "Tools",
"website": "https://github.com/OCA/mail",
"author": "CIT-Services, Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"depends": ["base", "mail", "web_notify"],
"data": [
"data/test_connection.xml",
"data/mail_alerts_channel.xml",
],
}
7 changes: 7 additions & 0 deletions mail_server_connection_alert/data/mail_alerts_channel.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="channel_system_mail_alerts" model="discuss.channel">
<field name="name">⚠️ System Mail Alerts</field>
<field name="channel_type">group</field>
</record>
</odoo>
11 changes: 11 additions & 0 deletions mail_server_connection_alert/data/test_connection.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="test_connection_reminder" model="ir.cron">
<field name="name">Test Connection</field>
<field name="model_id" ref="model_ir_mail_server" />
<field name="state">code</field>
<field name="code">model._process_reminders()</field>
<field name="interval_number">1</field>
<field name="interval_type">hours</field>
</record>
</odoo>
4 changes: 4 additions & 0 deletions mail_server_connection_alert/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2026 CIT-Services
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import ir_mail_server
162 changes: 162 additions & 0 deletions mail_server_connection_alert/models/ir_mail_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Copyright 2026 CIT-Services
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import logging

from markupsafe import Markup

from odoo import Command, api, models

_logger = logging.getLogger(__name__)


class IrMailServer(models.Model):
_inherit = "ir.mail_server"

def _format_failure_item(self, label, message, url=False):
if url:
bus_item = Markup(
f'[{label}] <a href="{url}" class="alert-link '
f'text-decoration-underline">{message}</a>'
)
list_item = Markup(f'<li><a href="{url}">{message}</a></li>')
else:
bus_item = f"[{label}] {message}"
list_item = Markup(f"<li>{message}</li>")
return bus_item, list_item

@api.model
def _process_reminders(self):
failures = {
"outgoing": {"web_notify_data": [], "channel_data": []},
"incoming": {"web_notify_data": [], "channel_data": []},
}

base_url = self.get_base_url()

active_outgoing = self.search([("active", "=", True)])
if not active_outgoing:
bus_item, list_item = self._format_failure_item(
"Outgoing",
"No active outgoing mail servers found in system settings.",
)
failures["outgoing"]["web_notify_data"].append(bus_item)
failures["outgoing"]["channel_data"].append(list_item)
else:
for server in active_outgoing:
try:
server.test_smtp_connection()
except Exception as e:
_logger.warning(
"Outgoing mail server %s (ID: %s) connection failed: %s",
server.name,
server.id,
e,
)
bus_item, list_item = self._format_failure_item(
"Outgoing",
f"{server.name} (ID: {server.id}) is not working properly.",
url=f"{base_url}/odoo/{server._name}/{server.id}",
)
failures["outgoing"]["web_notify_data"].append(bus_item)
failures["outgoing"]["channel_data"].append(list_item)

incoming_servers = self.env["fetchmail.server"].search(
[
("active", "=", True),
("server_type", "!=", "local"),
("state", "=", "done"),
]
)
for inc_server in incoming_servers:
connection = None
try:
connection = inc_server.connect()
except Exception as e:
_logger.warning(
"Incoming mail server %s (ID: %s) connection failed: %s",
inc_server.name,
inc_server.id,
e,
)
bus_item, list_item = self._format_failure_item(
"Incoming",
f"{inc_server.name} (ID: {inc_server.id}) is not working properly.",
url=f"{base_url}/odoo/{inc_server._name}/{inc_server.id}",
)
failures["incoming"]["web_notify_data"].append(bus_item)
failures["incoming"]["channel_data"].append(list_item)
finally:
try:
if connection:
connection_type = inc_server.server_type
if connection_type == "imap":
connection.close()
elif connection_type == "pop":
connection.quit()
except Exception as e:
_logger.debug("Failed to close incoming mail connection: %s", e)

if (
failures["outgoing"]["web_notify_data"]
or failures["incoming"]["web_notify_data"]
):
self._notify_system_admins(failures)

def _notify_system_admins(self, failures):
admin_group = self.env.ref("base.group_system")
admin_users = admin_group.users
if not admin_users:
return
admin_partners = admin_users.mapped("partner_id")
odoobot_partner = self.env.ref("base.partner_root")
all_members = admin_partners | odoobot_partner

outgoing = failures.get("outgoing", {})
incoming = failures.get("incoming", {})

if outgoing.get("web_notify_data"):
admin_users.sudo().notify_danger(
title="⚠️ Outgoing Mail System Warning",
message=Markup("<br/>").join(outgoing.get("web_notify_data")),
sticky=True,
html=True,
)
if incoming.get("web_notify_data"):
admin_users.sudo().notify_danger(
title="⚠️ Incoming Mail System Warning",
message=Markup("<br/>").join(incoming.get("web_notify_data")),
sticky=True,
html=True,
)

channel = self.env.ref(
"mail_server_connection_alert.channel_system_mail_alerts"
).sudo()

channel.channel_partner_ids = [Command.link(pid) for pid in all_members.ids]

html_sections = []
if outgoing.get("channel_data"):
html_sections.append(
f"<p><b>Outgoing Mail Server(s):</b></p><ul>"
f"{''.join(outgoing.get('channel_data'))}</ul>"
)
if incoming.get("channel_data"):
prefix = "<br/>" if html_sections else ""
html_sections.append(
f"{prefix}<p><b>Incoming Mail Server(s):</b></p><ul>"
f"{''.join(incoming.get('channel_data'))}</ul>"
)

formatted_body = Markup(
"<h3>⚠️ Mail System Warning</h3><br/>" + "".join(html_sections)
)

channel.sudo().message_post(
body=formatted_body,
author_id=odoobot_partner.id,
message_type="comment",
subtype_xmlid="mail.mt_comment",
silent=True,
)
3 changes: 3 additions & 0 deletions mail_server_connection_alert/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
2 changes: 2 additions & 0 deletions mail_server_connection_alert/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- [CIT-Services](cit-services.eu)
- Prayag \<<prayag.k@cit-services.eu>\>
3 changes: 3 additions & 0 deletions mail_server_connection_alert/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This module periodically checks the connection status of incoming and outgoing mail servers to detect failures early. It displays prominent notifications to administrators whenever a mail server configuration stops working.

It uses the **`web_notify`** module (from [OCA/web](https://github.com/OCA/web)) to display sticky notifications. It also creates a chatter channel for the same.
Loading
Loading