Enable Dark Mode!
By: Afra MP

How to Inherit & Update an Existing Mail Template in Odoo 17

Technical Odoo 17

In Odoo 17, one of the essential tasks in customizing the system is to inherit and edit existing mail templates. By making adjustments or updates to the content of these templates, you can tailor them to your specific business needs.

In this comprehensive guide, we will explore the process of inheriting and editing an existing mail template in Odoo 17, step by step.

Understanding the Mail Template Structure in Odoo 17

Before we dive into the process, let's take a moment to understand the structure of a mail template in Odoo 17. Mail templates in Odoo are defined using XML code and consist of various fields that define the email's content, including the subject, body, recipient, and attachments. These templates serve as the foundation for sending automated emails from the system.


To illustrate the concept, let's consider an example of updating the mail template in the accounting module. When the "SEND & PRINT" button is clicked from the "account.move" model, a wizard will open. Our goal is to make changes to the existing mail template used in this wizard.

The existing code for the "Invoice: Sending" mail template looks like this:

<?xml version="1.0" ?>
    <data noupdate="1">
        <!--Email template -->
        <record id="email_template_edi_invoice" model="mail.template">
            <field name="name">Invoice: Sending</field>
            <field name="model_id" ref="account.model_account_move"/>
            <field name="email_from">{{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }}</field>
            <field name="partner_to">{{ object.partner_id.id }}</field>
            <field name="subject">{{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }})</field>
            <field name="description">Sent to customers with their invoices in attachment</field>
            <field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
    <p style="margin: 0px; padding: 0px; font-size: 13px;">
        <t t-if="object.partner_id.parent_id">
            <t t-out="object.partner_id.name or ''">Brandon Freeman</t> (<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>),
        <t t-else="">
            <t t-out="object.partner_id.name or ''">Brandon Freeman</t>,
        <br /><br />
        Here is your
        <t t-if="object.name">
            invoice <span style="font-weight:bold;" t-out="object.name or ''">INV/2021/05/0005</span>
        <t t-else="">
        <t t-if="object.invoice_origin">
            (with reference: <t t-out="object.invoice_origin or ''">SUB003</t>)
        amounting in <span style="font-weight:bold;" t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</span>
        from <t t-out="object.company_id.name or ''">YourCompany</t>.
        <t t-if="object.payment_state in ('paid', 'in_payment')">
            This invoice is already paid.
        <t t-else="">
            Please remit payment at your earliest convenience.
            <t t-if="object.payment_reference">
                <br /><br />
                Please use the following communication for your payment: <span style="font-weight:bold;" t-out="object.payment_reference or ''">INV/2021/05/0005</span>.
        <t t-if="hasattr(object, 'timesheet_count') and object.timesheet_count">
            <br /><br />
            PS: you can review your timesheets <a t-att-href="'my/timesheets?search_in=invoice&amp;search=%s' % object.name">from the portal.</a>
        <br /><br />
        Do not hesitate to contact us if you have any questions.
        <t t-if="not is_html_empty(object.invoice_user_id.signature)">
            <br /><br />
            <t t-out="object.invoice_user_id.signature or ''">--<br/>Mitchell Admin</t>
            <field name="report_template_ids" eval="[(4, ref('account.account_invoices'))]"/>
            <field name="lang">{{ object.partner_id.lang }}</field>
            <field name="auto_delete" eval="True"/>

From the above code snippet, we can see that the mail template is declared as "Invoice: Sending" and is associated with the account.model_account_move model. It includes various fields such as the sender's email, recipient's email, subject, description, body HTML, report template, report name, language, and auto delete setting.

Making the Mail Template Updatable

To make changes to the mail template, we need to modify the existing code. However, the noupdate="1" attribute prevents any modifications to the template. We can change this attribute to make the template editable.

Here's an example of how to make the template editable using the search and write functions:

<function name="write" model="ir.model.data">
  <function name="search" model="ir.model.data">
    <value eval="[('name', '=', 'email_template_edi_invoice'), ('module', '=', 'account')]" />
  <value eval="{'noupdate': False}" />

In the above code, we first search for the mail template with the id "email_template_edi_invoice" in the "account" module. Then, we set the noupdate attribute to False, allowing us to make changes to the template.

Modifying the Mail Template

Now that the mail template is updatable, we can proceed with making the necessary changes. In this example, let's say we want to include the invoice date in the email's subject and the report's name that will be attached to it.

To modify the mail template, we need to update the subject and report_name fields of the mail.template record. Here's the code snippet to achieve this:

<record id="account.email_template_edi_invoice" model="mail.template">
  <field name="subject">{{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }}) {{ object.invoice_date }}</field>
  <field name="report_name">Invoice_{{ (object.name or '').replace('/', '_') }}{{ object.state == 'draft' and '_draft' or '' }}_{{ object.invoice_date.strftime('%Y_%m_%d') }}</field>

In this code, we are updating the subject field to include the invoice date by using the object.invoice_date variable. We are also modifying the report_name field to include the invoice date in the desired format.

Setting noupdate to True

Once we have made the necessary modifications, it's important to return the mail template to its non-updatable state to avoid any unwanted changes in the future. Here's how you can do it:

<function name="write" model="ir.model.data">
  <function name="search" model="ir.model.data">
    <value eval="[('name', '=', 'email_template_edi_invoice'), ('module', '=', 'account')]" />
  <value eval="{'noupdate': True}" />

By setting the noupdate value to True, we ensure that the mail template remains non-updatable.


Inheriting and updating an existing mail template in Odoo 17 is a straightforward process. By making the template updatable, modifying the necessary fields, and returning it to a non-updatable state, you can customize the content of mail templates to suit your specific needs. Remember to implement these changes in a custom module to ensure proper organization and compatibility with future updates.

By following the steps outlined in this blog, you can inherit and update mail templates in Odoo 17, enabling you to create personalized and tailored email communications for your business needs.

To read more about inherit & update an existing mail template in Odoo 16, refer to our blog How to Inherit & Update an Existing Mail Template in Odoo 16

If you need any assistance in odoo, we are online, please chat with us.


Leave a comment




Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635



Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.



Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message