Every Odoo project I've run eventually hits the same moment: a client asks why an invoice or a quote showed up in their customer's inbox from the wrong person. Not a bounce, not a spam filter. The email arrived fine, it just said "From: Dave" when Dave had nothing to do with it. Nobody configured that. Odoo just decided.
The reason is that Odoo doesn't treat "who sent this email" as one field you fill in. It's a fallback chain: a short list of candidates, checked top to bottom, and the first one with an actual email address wins. Untangling which candidate wins on which template is most of the work of getting Odoo's outbound email right for a client.
Start With One Template: Sales: Send Quotation
Here's the actual expression Odoo 19 ships on the standard "Sales: Send Quotation" template, the one that fires when someone clicks Send on a quote:
{{ (object.user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }}
Read left to right, that's three checks, in order:
object.user_id.email_formatted: is there a salesperson assigned to this quote, and do they have an email on file? If yes, they're the sender.object.company_id.email_formatted: if not, does the company itself have an email address configured? If yes, the customer sees the company brand as sender instead of a person.user.email_formatted: if neither of those resolved to anything, fall back to whoever is actually logged in and clicking Send.
The "or" here doesn't mean "any of these." It means first-match-wins. Odoo checks candidate one, and only moves to candidate two if candidate one comes back empty. That's the entire mental model for reading any of these expressions: read it as a waterfall, not a set.
That same shape (salesperson, then company, then logged-in user, with small variations) repeats across almost every customer-facing template Odoo ships. A few skip a step. One template runs the order backwards. None of it is arbitrary once you know to look for the chain.
Every Template's From Field, Broken Down
Everything below is stock Odoo 19, pulled directly off a fresh install, no 19 Prince customization. Customer-facing templates first, internal/system notifications at the bottom.
| Template | Send From | Plain English |
|---|---|---|
| Sales: Send Quotation | {{ (object.user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | Assigned salesperson first, then company brand, then logged-in user. |
| Sales: Order Confirmation | {{ (object.user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | Assigned salesperson first, then company brand, then logged-in user. |
| Sales: Payment Done | {{ (object.user_id.email_formatted or user.email_formatted) }} | Assigned salesperson first, then logged-in user — notably skips the company-brand fallback. |
| Sales: Send Proforma | {{ (object.user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | Assigned salesperson first, then company brand, then logged-in user. |
| Ecommerce: Cart Recovery | {{ (object.user_id.email_formatted or object.company_id.email_formatted or user.email_formatted or '') }} | Assigned salesperson first, then company, then logged-in user, else blank. |
| Invoice: Sending | {{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | Invoice's salesperson first, then company brand, then logged-in user. |
| Credit Note: Sending | {{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | The invoice's assigned salesperson first, then company brand, then whoever's logged in. |
| Self-billing invoice: Sending | {{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | Invoice's salesperson first, then company brand, then logged-in user. |
| Self-billing credit note: Sending | {{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }} | Invoice's salesperson first, then company brand, then logged-in user. |
| Payment: Payment Receipt | (blank) | No From set at all — Odoo falls back to the system/alias-domain default. |
| Customer Statement | {{ object._get_followup_responsible().email_formatted }} | Whoever is assigned as this customer's collections/follow-up contact. |
| Follow Up Report | {{ object._get_followup_responsible().email_formatted }} | Whoever is assigned as this customer's collections/follow-up contact. |
| Payment Reminder | {{ object._get_followup_responsible().email_formatted }} | The follow-up/collections contact. |
| Second reminder followup | {{ object._get_followup_responsible().email_formatted }} | The follow-up/collections contact. |
| Settings: New Portal Sign Up | {{ (object.company_id.email_formatted or user.email_formatted) }} | Company brand first, then whoever's logged in. |
| Settings: New Portal User Invite | {{ (object.company_id.email_formatted or user.email_formatted) }} | Company brand first, then whoever's logged in. |
| New eInvoices Notification | {{ object.company_id.email_formatted }} | Always the company brand identity — no fallback. |
| Journal Notification | {{ object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted }} | Invoice's salesperson first, then company brand, then logged-in user. |
| Bank connection expiration reminder | {{ object.company_id.email_formatted or user.email_formatted }} | Company brand identity first; falls back to whoever's logged in if the company has no email set. |
| Tax Return Deadline | (blank) | No From set at all — falls back to the system/alias-domain default. |
| Tax payment | {{ (user.email_formatted or object.company_id.email_formatted) }} | Whoever's logged in first, then company brand — the one template that reverses the usual priority. |
| Settings: New User Invite | {{ (object.company_id.email_formatted or user.email_formatted) }} | Company brand first, then whoever's logged in. |
| Settings: 2Fa Invitation | {{ (object.company_id.email_formatted or user.email_formatted) }} | Company brand first, then whoever's logged in. |
| Settings: 2Fa New Login | {{ (object.company_id.email_formatted or user.email_formatted) }} | Company brand first, then whoever's logged in. |
| Settings: Unregistered User Reminder | {{ (object.company_id.email_formatted or user.email_formatted) }} | Company brand first, then whoever's logged in. |
| Mail: Install Request | {{ object.user_id.email_formatted or user.email_formatted }} | The person who requested the module install, else whoever's logged in. |
| IAP Extract Notification | [email protected] | Hardcoded Odoo address — not client-branded at all. |
If your customers have ever asked "why did this come from someone who doesn't work here anymore," the answer is almost always sitting in one of these rows. Fixing it isn't a rebuild. It's usually a one-line change to the right template, once you know which candidate in the chain is actually winning.
— Darren from 19 Prince