The From field resolves through a fallback chain. The To field resolves through a single checkbox. The Subject field doesn't resolve through a decision at all. It's concatenation: a handful of pieces stitched together into one line, no candidates, no default recipient, just text plus text plus text. The one exception is worth pulling apart, because it's the only place in this whole system where the subject line itself runs real logic instead of just echoing a name off the record.
Same Example: Sales: Send Quotation
Here's the subject Odoo 19 ships on the standard "Sales: Send Quotation" template, the same one covered in the From and To posts:
{{ object.company_id.name }} {{ object.state in ('draft', 'sent') and 'Quotation' or 'Order' }} (Ref {{ object.name or 'n/a' }})
Read it in three pieces:
object.company_id.name: the company's name, always, first.object.state in ('draft', 'sent') and 'Quotation' or 'Order': a live conditional. While the record is still a draft or has just been sent, the subject reads "Quotation." The moment someone confirms it into an order, the exact same template starts producing "Order" instead, with nothing edited by hand.(Ref {{ object.name or 'n/a' }}): the record's own reference number in parentheses, falling back to "n/a" on the rare record that doesn't have one yet.
Put together, a still-open quote for Acme Corp reads "Acme Corp Quotation (Ref S00042)." Confirm that same record, and the next email about it reads "Acme Corp Order (Ref S00042)," same template, same code, different word, because the state changed underneath it. Everywhere else on this list, the subject is just pulling a name or a reference off the record. Here, it's actually branching on the record's status.
Every Template's Subject Field, Broken Down
Everything below is stock Odoo 19, pulled directly off a fresh install, no 19 Prince customization. Same template order as the From and To breakdowns: customer-facing first, internal/system notifications at the bottom.
| Template | Subject | Plain English |
|---|---|---|
| Sales: Send Quotation | {{ object.company_id.name }} {{ object.state in ('draft', 'sent') and 'Quotation' or 'Order' }} (Ref {{ object.name or 'n/a' }}) | Company name + "Quotation" or "Order" depending on quote status + ref. |
| Sales: Order Confirmation | {{ object.company_id.name }} {{ (object.get_portal_last_transaction().state == 'pending') and 'Pending Order' or 'Order' }} (Ref {{ object.name or 'n/a' }}) | Company name + "Pending Order" or "Order" depending on payment status + order ref. |
| Sales: Payment Done | {{ object.company_id.name }} {{ (object.get_portal_last_transaction().state == 'pending') and 'Pending Order' or 'Order' }} (Ref {{ object.name or 'n/a' }}) | Company name + "Pending Order" or "Order" depending on payment status + order ref. |
| Sales: Send Proforma | {{ object.company_id.name }} {{ object.state in ('draft', 'sent') and 'Proforma' or 'Order'}} (Ref {{ object.name or 'n/a' }}) | Company name + "Proforma" or "Order" depending on quote status + ref. |
| Ecommerce: Cart Recovery | You left items in your cart! | Static text. |
| Invoice: Sending | {{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }}) | Company name + "Invoice" + invoice number. |
| Credit Note: Sending | {{ object.company_id.name }} Credit Note (Ref {{ object.name or 'n/a' }}) | Company name + "Credit Note" + the credit note's reference number. |
| Self-billing invoice: Sending | {{ object.company_id.name }} Self-billing invoice (Ref {{ object.name or 'n/a' }}) | Company name + "Self-billing invoice" + ref. |
| Self-billing credit note: Sending | {{ object.company_id.name }} Self-billing credit note (Ref {{ object.name or 'n/a' }}) | Company name + "Self-billing credit note" + ref. |
| Payment: Payment Receipt | {{ object.company_id.name }} Payment Receipt (Ref {{ object.name or 'n/a' }}) | Company name + "Payment Receipt" + payment reference number. |
| Customer Statement | {{ (object.company_id or object._get_followup_responsible().company_id).name }} Statement - {{ object.commercial_company_name }} | Company name + "Statement" + the customer's company name. |
| Follow Up Report | {{ (object.company_id or object._get_followup_responsible().company_id).name }} Follow Up - {{ object.commercial_company_name }} | Company name + "Follow Up" + the customer's company name. |
| Payment Reminder | {{ (object.company_id or object._get_followup_responsible().company_id).name }} Payment Reminder - {{ object.commercial_company_name }} | Company name + "Payment Reminder" + customer's company name. |
| Second reminder followup | {{ (object.company_id or object._get_followup_responsible().company_id).name }} Payment Reminder - {{ object.commercial_company_name }} | Company name + "Payment Reminder" + customer's company name. |
| Settings: New Portal Sign Up | Welcome to {{ object.company_id.name }}! | Company name welcome message. |
| Settings: New Portal User Invite | Your account at {{ object.company_id.name }} | Company name + generic account notice. |
| New eInvoices Notification | New Electronic Invoices Received | Static text. |
| Journal Notification | {{ object.company_id.name }} - New invoice in {{ object.journal_id.display_name or 'Invoices' }} journal | Company name + which accounting journal the invoice landed in. |
| Bank connection expiration reminder | Your bank connection is expiring soon | Static text. |
| Tax Return Deadline | Reminder: Upcoming {{ object.name }} Deadline - Action Required | Names the specific tax return + urgency framing. |
| Tax payment | Tax return payment instructions | Static text. |
| Settings: New User Invite | {{ object.create_uid.name }} from {{ object.company_id.name }} invites you to connect to Odoo | Names the specific person who sent the invite + company name. |
| Settings: 2Fa Invitation | Invitation to activate two-factor authentication on your Odoo account | Static text. |
| Settings: 2Fa New Login | Your two-factor authentication code | Static text. |
| Settings: Unregistered User Reminder | Reminder for unregistered users | Static text. |
| Mail: Install Request | Module Activation Request for "{{ object.module_id.shortdesc }}" | Names the specific app/module being requested. |
| IAP Extract Notification | IAP Extract Notification | Static text. |
Most of these rows are static or a straight name-swap, nothing to debug. The one pattern worth carrying with you: whenever a subject line seems to change wording on its own, on the same record, with no one touching the template, go looking for a conditional like the one on the quotation template. Odoo isn't reacting to an edit. It's just running a check against the record's current state, every single time it renders.
— Darren from 19 Prince