Running an HVAC business with Odoo

How do I set up email for Odoo quotations and invoices?

Workflow overview: How do I set up email for Odoo quotations and invoices?
Workflow overview. Instructional screenshots show the actual demo interface.

Set up an Odoo outgoing mail server and verify a quotation email, recipient and PDF in a local training mailbox.

Alex wants to know that his quotation reaches the intended recipient with the correct PDF. This guide configures Odoo's outgoing mail server, tests the connection and verifies one actual quotation message in a local training mailbox.

Alex Rivera and Demo Air HVAC are fictional training examples. Prices, dates, quantities and business situations in this guide are illustrative.

Before you begin

Tested in stock Odoo 20.0-20260926 Community as the demo owner administrator, with official modules and standard configuration. Use an administrator account with access to Settings → Technical, and the official Mail and Sales modules from H02. For the document check, use the customer from H08, saved quotation S00001 from H23, and reviewed document layout from H05. A local Mailpit sink is already running: Odoo can reach demoair-mailpit:1025, and its inbox is at http://127.0.0.1:8025. Its SMTP defaults are documented by Mailpit. This guide verifies quotation delivery; sending an actual customer invoice remains a later check. Provider accounts, production-domain authentication and external inbox delivery are outside this local test.

Step-by-step workflow

Stock Odoo 20.0-20260926 Community; one local SMTP route, refused/successful connection tests and one actual quotation email in an isolated Mailpit inbox. Blank credentials/None encryption belong to this local sink. Invoice email, external providers, public deliverability and timed queue processing remain unverified.

Step 1. Check the training mailbox and current queue

Open the local Mailpit Inbox and check its starting message count; ours was zero. The sink runs on the internal training network with its web UI bound to the local machine. Scheduled background jobs remain disabled in this demo. In Odoo, Settings → Technical → Emails shows four older Delivery Failed records at this checkpoint. Leave those records alone while testing the intended quotation.

Action 1: Open the app menu. The actual target is highlighted in gold.
Open the app menu.
Action 2: Choose Settings as the demo administrator. The actual target is highlighted in gold.
Choose Settings as the demo administrator.
Action 3: Open Technical in developer mode. The actual target is highlighted in gold.
Open Technical in developer mode.
Action 4: Inspect Emails before testing. The actual target is highlighted in gold.
Inspect Emails before testing.
Action 5: Leave the four older Delivery Failed messages alone. The actual target is highlighted in gold.
Leave the four older Delivery Failed messages alone.
Action 6: The isolated local inbox starts empty. The actual target is highlighted in gold.
The isolated local inbox starts empty.

Step 2. Open outgoing mail servers

Open Settings → Technical → Outgoing Mail Servers and click New. The tested administrator already had the Technical menu. If yours is hidden, use Activate the developer mode in General Settings, then return to Technical. There were no outgoing-server records before this lesson.

Action 7: Open Technical again. The actual target is highlighted in gold.
Open Technical again.
Action 8: Choose Outgoing Mail Servers. The actual target is highlighted in gold.
Choose Outgoing Mail Servers.
Action 9: Create the local training route. The actual target is highlighted in gold.
Create the local training route.

Step 3. Enter the local SMTP route

Enter Demo Air local mail H07 as Name, demoair.example.invalid as FROM Filtering, and leave Priority at 10. Set SMTP Server to demoair-mailpit and SMTP Port to 1025. Keep Connection Encryption: None. The Authenticate with: Username option stays selected, with both Username and Password empty for this sink. Leave Owner empty. These settings belong to the isolated test destination; use your provider's own requirements for a production account.

Action 10: Give the route its training name. The actual target is highlighted in gold.
Give the route its training name.
Action 11: Set the fictional sender-domain filter. The actual target is highlighted in gold.
Set the fictional sender-domain filter.
Action 12: Leave Priority at 10. The actual target is highlighted in gold.
Leave Priority at 10.
Action 13: Point SMTP Server at the isolated Mailpit sink. The actual target is highlighted in gold.
Point SMTP Server at the isolated Mailpit sink.
Action 14: Use wrong local port 1026 for the negative check. The actual target is highlighted in gold.
Use wrong local port 1026 for the negative check.
Action 15: None encryption is specific to this internal sink. The actual target is highlighted in gold.
None encryption is specific to this internal sink.
Action 16: Keep Username authentication for this local sink. The actual target is highlighted in gold.
Keep Username authentication for this local sink.
Action 17: This sink uses blank credentials; leave Owner empty. The actual target is highlighted in gold.
This sink uses blank credentials; leave Owner empty.

Step 4. Save and test the connection

Click Save manually, then Test Connection. Check for Connection Test Successful!. Our negative check using port 1026 produced Connection refused; restoring 1025 succeeded. The inbox still contained zero messages after connection testing. A working connection is one check; it does not establish delivery of your quotation.

Action 18: Save the test route manually. The actual target is highlighted in gold.
Save the test route manually.
Action 19: Test the intentionally wrong local port. The actual target is highlighted in gold.
Test the intentionally wrong local port.
Action 20: Check the Connection refused error. The actual target is highlighted in gold.
Check the Connection refused error.
Action 21: Close the failed-connection message. The actual target is highlighted in gold.
Close the failed-connection message.
Action 22: Correct SMTP Port to 1025. The actual target is highlighted in gold.
Correct SMTP Port to 1025.
Action 23: Save the corrected port on the same route. The actual target is highlighted in gold.
Save the corrected port on the same route.
Action 24: Test the corrected local SMTP connection. The actual target is highlighted in gold.
Test the corrected local SMTP connection.
Action 25: Connection success does not establish message delivery. The actual target is highlighted in gold.
Connection success does not establish message delivery.

Step 5. Give the training customer an email address

Open Contacts → Demo Property H08. Enter quotes@demoair.example.invalid in Email, then Save manually. Reopen to check the saved value. Leave the separate billing and service-address records unchanged. The demo sender is owner@demoair.example.invalid, which matches the server's FROM Filtering domain.

Action 26: Open the app menu. The actual target is highlighted in gold.
Open the app menu.
Action 27: Choose Contacts. The actual target is highlighted in gold.
Choose Contacts.
Action 28: Open the existing Demo Property H08 parent. The actual target is highlighted in gold.
Open the existing Demo Property H08 parent.
Action 29: Enter the fictional local training recipient. The actual target is highlighted in gold.
Enter the fictional local training recipient.
Action 30: Save the customer email manually. The actual target is highlighted in gold.
Save the customer email manually.
Action 31: Return to Contacts. The actual target is highlighted in gold.
Return to Contacts.
Action 32: Reopen the same customer. The actual target is highlighted in gold.
Reopen the same customer.
Action 33: Check the retained recipient address. The actual target is highlighted in gold.
Check the retained recipient address.

Step 6. Send the reviewed quotation once

From the customer's Sales button, open S00001. Check the two service/labor lines, $275.60 total, addresses and scope. Click Send. In the dialog, confirm To: Demo Property H08, inspect the message and attached Quotation - S00001.pdf, and set Subject to Demo Air HVAC Quotation S00001 - H07 local test. Click the dialog's Send once. The quotation changes to Quotation Sent; it has not been accepted or invoiced.

Action 34: Open the customer Sales records. The actual target is highlighted in gold.
Open the customer Sales records.
Action 35: Open the existing S00001 quotation. The actual target is highlighted in gold.
Open the existing S00001 quotation.
Action 36: Review the existing service lines and scope before Send. The actual target is highlighted in gold.
Review the existing service lines and scope before Send.
Action 37: Open Send for this reviewed quotation. The actual target is highlighted in gold.
Open Send for this reviewed quotation.
Action 38: Check To is Demo Property H08. The actual target is highlighted in gold.
Check To is Demo Property H08.
Action 39: Set the exact local-test subject. The actual target is highlighted in gold.
Set the exact local-test subject.
Action 40: Check the attached Quotation - S00001.pdf. The actual target is highlighted in gold.
Check the attached Quotation - S00001.pdf.
Action 41: Send this quotation once to the local sink. The actual target is highlighted in gold.
Send this quotation once to the local sink.
Action 42: Quotation Sent is separate from acceptance and delivery proof. The actual target is highlighted in gold.
Quotation Sent is separate from acceptance and delivery proof.

Step 7. Inspect the received email and PDF

Return to Mailpit. Open the one new message with that exact subject. Check From: owner@demoair.example.invalid, To: quotes@demoair.example.invalid, and the single PDF attachment. Open/download the PDF and check S00001, the service/labor lines, billing/service addresses and $275.60 total. Our received file had the same bytes and checksum as Odoo's saved attachment, confirming that the intended PDF arrived.

Action 43: Check there is one matching local quotation message. The actual target is highlighted in gold.
Check there is one matching local quotation message.
Action 44: Open the message with the exact test subject. The actual target is highlighted in gold.
Open the message with the exact test subject.
Action 45: Verify From is the fictional demo sender. The actual target is highlighted in gold.
Verify From is the fictional demo sender.
Action 46: Verify To is the intended training recipient. The actual target is highlighted in gold.
Verify To is the intended training recipient.
Action 47: Check the single received quotation PDF. The actual target is highlighted in gold.
Check the single received quotation PDF.
Action 48: Open the actual received PDF attachment. The actual target is highlighted in gold.
Open the actual received PDF attachment.
Action 49: Check S00001, addresses, service lines and the 275.60 total. The actual target is highlighted in gold.
Check S00001, addresses, service lines and the 275.60 total.

Step 8. Check the recipient's delivery details

Reload S00001 and find the sent message in its chatter. Click the envelope icon beside the author. The recipient details showed Demo Property H08 (quotes@demoair.example.invalid) with Delivered. The saved email notification also had status sent. That status and the received message are the delivery checks; the quotation's Sent status alone is insufficient.

Action 50: Reloaded S00001 remains Quotation Sent. The actual target is highlighted in gold.
Reloaded S00001 remains Quotation Sent.
Action 51: Open the sent message recipient details. The actual target is highlighted in gold.
Open the sent message recipient details.
Action 52: Check the intended customer and email in the popover. The actual target is highlighted in gold.
Check the intended customer and email in the popover.
Action 53: Check Delivered on the recipient status icon. The actual target is highlighted in gold.
Check Delivered on the recipient status icon.

Step 9. Check the queue before considering a retry

Open Settings → Technical → Emails again. In this case only the same four older failures remained; the successful quotation message was retained in the document's chatter and recipient notification, rather than as a sent row in this list. Recheck the local inbox: there is still one matching message. Do not resend a successful message simply because its outgoing queue row is absent. For an actual failure, inspect the relevant recipient, server and error before retrying that specific message.

Action 54: Return to the app menu. The actual target is highlighted in gold.
Return to the app menu.
Action 55: Open Settings to check the queue. The actual target is highlighted in gold.
Open Settings to check the queue.
Action 56: Open Technical. The actual target is highlighted in gold.
Open Technical.
Action 57: Choose Emails. The actual target is highlighted in gold.
Choose Emails.
Action 58: Only the same four older failures remain; do not resend. The actual target is highlighted in gold.
Only the same four older failures remain; do not resend.
Action 59: The inbox still has one matching message; delivery is checked. The actual target is highlighted in gold.
The inbox still has one matching message; delivery is checked.

Check the result

One S00001 quotation email reached the local sink with the intended sender, recipient, subject and one matching PDF. S00001 is Quotation Sent at $275.60, with no sales-order acceptance, delivery or invoice. The recipient details show Delivered and the saved notification is sent. The four pre-existing failed emails retain the same identities and states. Other quotation totals, stock balances and finance records are preserved.

If your screen differs

The envelope button's accessible label read Delivery failure even though its recipient popover showed Delivered and the saved notification was sent. Use the recipient details and actual mailbox evidence when assessing this case. The successful message did not remain as a sent row in Emails; absence there was not a reason to retry. Only this local quotation route was exercised. Invoice emailing, Microsoft/Google authentication, domain policies, public deliverability, queued scheduling and automatic retry timing remain unverified. Blank credentials and None encryption are specific to this internal sink.

Frequently asked questions

How do I configure an outgoing mail server in Odoo?

As an administrator, open Settings → Technical → Outgoing Mail Servers → New. Enter the server, port, sender filter and the authentication/encryption required by the selected destination. Save and use Test Connection, then verify a real document message. Our local sink used demoair-mailpit:1025, None encryption and empty credentials; those are training settings, not a production-provider configuration.

Why are Odoo quotations not sending by email?

Check the customer's saved email, the Send dialog recipient, the outgoing server and the relevant entry under Settings → Technical → Emails. This test's wrong port produced Connection refused. After correcting it, we verified one message in the sink and a sent recipient notification. A missing sent queue row did not mean failure, so check the chatter's recipient details and mailbox before retrying.

Does an Odoo mail server connection test prove email delivery?

No. Our successful connection test left the local inbox empty. The separate Send action produced one quotation email with the expected recipient and PDF; Odoo's recipient details showed Delivered. The file's checksum matched the saved quotation attachment. This proves the stated local delivery case, while actual invoice delivery and external inbox placement remain untested.

Continue building the business

For the next mail-dependent workflow, see H26: How can customers view and accept an Odoo quotation online?. It has its own customer-access and acceptance checks; sending the email did not confirm the job.

Talk to an Odoo partner

Bring your current process and the result you need to Onward to plan your Odoo workflow. Talk to an Odoo partner.