Skip to content
Closed
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
10 changes: 10 additions & 0 deletions helpdesk_mgmt/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ Tags

|image5|

Auto-reply Ignore List
----------------------

To prevent automatic replies from being sent to certain senders (e.g.
monitoring systems, no-reply addresses, or mailing lists):

1. Go to *Helpdesk > Settings*.
2. Select one or more contacts in the **Auto-reply ignored partners** field.
Only contacts that have an email address are shown.

Permissions
-----------

Expand Down
11 changes: 11 additions & 0 deletions helpdesk_mgmt/models/helpdesk_ticket.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from odoo import api, fields, models, tools
from odoo.exceptions import AccessError
from odoo.tools import email_normalize


class HelpdeskTicket(models.Model):
Expand Down Expand Up @@ -307,6 +308,16 @@ def _track_template(self, tracking):
res = super()._track_template(tracking)
ticket = self[0]
if "stage_id" in tracking and ticket.stage_id.mail_template_id:
# Skip auto-reply if the sender's email matches an ignored partner
ignored_emails = {
email_normalize(p.email)
for p in ticket.company_id.helpdesk_mgmt_autoreply_ignored_partners
if p.email
}
ignored_emails.discard(False)
ticket_email = email_normalize(ticket.partner_email or "")
if ticket_email and ticket_email in ignored_emails:
return res
res["stage_id"] = (
ticket.stage_id.mail_template_id,
{
Expand Down
10 changes: 10 additions & 0 deletions helpdesk_mgmt/models/res_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@ class Company(models.Model):
string="Auto assign tickets",
default=True,
)
helpdesk_mgmt_autoreply_ignored_partners = fields.Many2many(
comodel_name="res.partner",
relation="helpdesk_mgmt_company_autoreply_ignored_partner_rel",
column1="company_id",
column2="partner_id",
string="Auto-reply ignored partners",
domain=[("email", "!=", False)],
help="Partners whose email address will not receive an automatic reply "
"when a helpdesk ticket is created from their email.",
)
4 changes: 4 additions & 0 deletions helpdesk_mgmt/models/res_config_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ class ResConfigSettings(models.TransientModel):
related="company_id.helpdesk_mgmt_ticket_auto_assign",
readonly=False,
)
helpdesk_mgmt_autoreply_ignored_partners = fields.Many2many(
related="company_id.helpdesk_mgmt_autoreply_ignored_partners",
readonly=False,
)
9 changes: 9 additions & 0 deletions helpdesk_mgmt/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ in the list view.

![](../static/description/Tags.PNG)

## Auto-reply Ignore List

To prevent automatic replies from being sent to certain senders (e.g.
monitoring systems, no-reply addresses, or mailing lists):

1. Go to *Helpdesk \> Settings*.
2. Select one or more contacts in the **Auto-reply ignored partners** field.
Only contacts that have an email address are shown.

## Permissions

There are restrictions to read tickets according to the user's
Expand Down
115 changes: 115 additions & 0 deletions helpdesk_mgmt/tests/test_helpdesk_fetchmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,118 @@ def test_message_process_missing_channel(self):
self.assertEqual(ticket_id.name, "Need backup")
# ensure that the channel is not set
self.assertFalse(ticket_id.channel_id)

def _create_autoreply_template(self):
"""Return a minimal mail.template for helpdesk.ticket."""
return self.env["mail.template"].create(
{
"name": "Test Auto Reply",
"model_id": self.env.ref("helpdesk_mgmt.model_helpdesk_ticket").id,
"subject": "We received your ticket",
"body_html": "<p>Thank you for contacting us!</p>",
}
)

def _create_ignored_partner(self, email, name=None):
"""Create a res.partner with the given email and add it to the company's
autoreply ignore list."""
partner = self.env["res.partner"].create(
{"name": name or email, "email": email}
)
self.company.helpdesk_mgmt_autoreply_ignored_partners = [(4, partner.id)]
return partner

def test_autoreply_sent_for_normal_email(self):
"""_track_template includes the stage template for a non-ignored sender."""
mail_template = self._create_autoreply_template()
self.new_stage.mail_template_id = mail_template
# configure an ignored partner whose email differs from the ticket sender
self._create_ignored_partner("noreply@monitoring.example.com")
ticket = self.env["helpdesk.ticket"].create(
{
"name": "Normal customer ticket",
"description": "I need help",
"team_id": self.team_a.id,
"stage_id": self.new_stage.id,
"partner_email": "customer@example.com",
}
)
result = ticket._track_template({"stage_id": self.new_stage})
self.assertIn(
"stage_id",
result,
"Auto-reply template should be present for a non-ignored sender.",
)

def test_autoreply_not_sent_for_ignored_partner(self):
"""Stage template is skipped when the ticket sender is an ignored partner."""
mail_template = self._create_autoreply_template()
self.new_stage.mail_template_id = mail_template
ignored_email = "noreply@monitoring.example.com"
self._create_ignored_partner(ignored_email)
ticket = self.env["helpdesk.ticket"].create(
{
"name": "Alert from monitoring system",
"description": "Automated alert",
"team_id": self.team_a.id,
"stage_id": self.new_stage.id,
"partner_email": ignored_email,
}
)
result = ticket._track_template({"stage_id": self.new_stage})
self.assertNotIn(
"stage_id",
result,
"Auto-reply template should be absent for an ignored sender.",
)

def test_autoreply_ignored_partner_email_is_normalized(self):
"""Ignore list matching is case-insensitive (via email_normalize)."""
mail_template = self._create_autoreply_template()
self.new_stage.mail_template_id = mail_template
# store the partner's address in upper case
self._create_ignored_partner("NOREPLY@MONITORING.EXAMPLE.COM")
ticket = self.env["helpdesk.ticket"].create(
{
"name": "Alert from monitoring system",
"description": "Automated alert",
"team_id": self.team_a.id,
"stage_id": self.new_stage.id,
# ticket arrives with the address in a display-name format
"partner_email": "Monitoring Bot <noreply@monitoring.example.com>",
}
)
result = ticket._track_template({"stage_id": self.new_stage})
self.assertNotIn(
"stage_id",
result,
"Ignore list matching should normalize both sides via email_normalize.",
)

def test_autoreply_multiple_ignored_partners(self):
"""Multiple ignored partners all suppress the auto-reply."""
mail_template = self._create_autoreply_template()
self.new_stage.mail_template_id = mail_template
emails = [
"alerts@example.com",
"noreply@example.com",
"monitoring@example.com",
]
for email in emails:
self._create_ignored_partner(email)
for email in emails:
ticket = self.env["helpdesk.ticket"].create(
{
"name": f"Alert from {email}",
"description": "Automated alert",
"team_id": self.team_a.id,
"stage_id": self.new_stage.id,
"partner_email": email,
}
)
result = ticket._track_template({"stage_id": self.new_stage})
self.assertNotIn(
"stage_id",
result,
f"Auto-reply should be suppressed for ignored address {email}.",
)
12 changes: 12 additions & 0 deletions helpdesk_mgmt/views/res_config_settings_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@
</div>
</div>
</setting>
<setting
id="helpdesk_mgmt_autoreply_ignored_partners"
string="Auto-reply ignored partners"
help="Partners whose email address will never receive an automatic reply when a ticket is created from their email."
>
<field
name="helpdesk_mgmt_autoreply_ignored_partners"
widget="many2many_tags"
domain="[('email', '!=', False)]"
options="{'no_create_edit': True}"
/>
</setting>
</block>
</app>
</xpath>
Expand Down
Loading