HubSpot + Outlook: send-ready drafts from messy leads
Your leads don’t arrive “CRM-ready.” They show up half-filled, duplicated, missing domains, and sprinkled across imports, form dumps, and list uploads. Then you spend your best hours cleaning fields, hunting emails, and trying to write outreach that doesn’t sound improvised.
This HubSpot Outlook drafts automation hits RevOps first, but SDRs and founder-led sales teams feel it too. You get verified contact data, consistent first-touch copy, and a ready-to-review Outlook draft without playing spreadsheet detective.
Below, you’ll see exactly what this workflow does, what you need to connect, and how the pieces fit together so you can ship cleaner outreach in minutes, not hours.
How This Automation Works
Here’s the complete workflow you’ll be setting up:
n8n Workflow Template: HubSpot + Outlook: send-ready drafts from messy leads
flowchart LR
subgraph sg0["Schedule Flow"]
direction LR
n11@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model1", pos: "b", h: 48 }
n12@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory1", pos: "b", h: 48 }
n13@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model2", pos: "b", h: 48 }
n14@{ icon: "mdi:cog", form: "rounded", label: "Create or update a contact i..", pos: "b", h: 48 }
n15@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model3", pos: "b", h: 48 }
n17@{ icon: "mdi:cog", form: "rounded", label: "Message a model in Perplexity1", pos: "b", h: 48 }
n18@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser1", pos: "b", h: 48 }
n22@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model6", pos: "b", h: 48 }
n23@{ icon: "mdi:wrench", form: "rounded", label: "Email Finder and verifier", pos: "b", h: 48 }
n24@{ icon: "mdi:wrench", form: "rounded", label: "Profile Scraper", pos: "b", h: 48 }
n25@{ icon: "mdi:wrench", form: "rounded", label: "Create Contacts", pos: "b", h: 48 }
n26@{ icon: "mdi:robot", form: "rounded", label: "Level 1 Orchestrator", pos: "b", h: 48 }
n43@{ icon: "mdi:database", form: "rounded", label: "Update row in sheet in Googl..", pos: "b", h: 48 }
n45@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory2", pos: "b", h: 48 }
n46@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory3", pos: "b", h: 48 }
n47@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory6", pos: "b", h: 48 }
n48@{ icon: "mdi:cog", form: "rounded", label: "create_update_contact", pos: "b", h: 48 }
n51@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser3", pos: "b", h: 48 }
n52@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model12", pos: "b", h: 48 }
n53@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model13", pos: "b", h: 48 }
n61@{ icon: "mdi:wrench", form: "rounded", label: "run actor", pos: "b", h: 48 }
n63@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet in Googl..", pos: "b", h: 48 }
n65@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet in Googl..", pos: "b", h: 48 }
n66@{ icon: "mdi:cog", form: "rounded", label: "email verifier", pos: "b", h: 48 }
n67@{ icon: "mdi:cog", form: "rounded", label: "email finder Hunter", pos: "b", h: 48 }
n68@{ icon: "mdi:wrench", form: "rounded", label: "profile details", pos: "b", h: 48 }
n69@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet in Googl..", pos: "b", h: 48 }
n70@{ icon: "mdi:database", form: "rounded", label: "Update row in sheet in Googl..", pos: "b", h: 48 }
n90@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger4", pos: "b", h: 48 }
n91["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Get many companies1"]
n92@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items4", pos: "b", h: 48 }
n61 -.-> n24
n12 -.-> n26
n45 -.-> n24
n46 -.-> n23
n47 -.-> n25
n66 -.-> n23
n25 -.-> n26
n24 -.-> n26
n68 -.-> n23
n92 --> n26
n90 --> n91
n91 --> n92
n67 -.-> n23
n26 --> n92
n48 -.-> n26
n11 -.-> n26
n13 -.-> n23
n15 -.-> n24
n22 -.-> n25
n52 -.-> n51
n53 -.-> n18
n23 -.-> n26
n18 -.-> n26
n51 -.-> n24
n17 -.-> n24
n70 -.-> n23
n14 -.-> n25
n63 -.-> n24
n65 -.-> n25
n69 -.-> n23
n43 -.-> n25
end
subgraph sg1["Schedule Flow"]
direction LR
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Get many companies"]
n3@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter", pos: "b", h: 48 }
n4@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
n5@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields1", pos: "b", h: 48 }
n6@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory", pos: "b", h: 48 }
n7@{ icon: "mdi:wrench", form: "rounded", label: "Calculator", pos: "b", h: 48 }
n8@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser", pos: "b", h: 48 }
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Update a company"]
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields2", pos: "b", h: 48 }
n16@{ icon: "mdi:cog", form: "rounded", label: "Message a model in Perplexity", pos: "b", h: 48 }
n20@{ icon: "mdi:cog", form: "rounded", label: "Wait", pos: "b", h: 48 }
n21@{ icon: "mdi:robot", form: "rounded", label: "ICP Agent", pos: "b", h: 48 }
n31@{ icon: "mdi:cog", form: "rounded", label: "Limit", pos: "b", h: 48 }
n32@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model", pos: "b", h: 48 }
n33@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model9", pos: "b", h: 48 }
n34@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet in Googl..", pos: "b", h: 48 }
n35@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model10", pos: "b", h: 48 }
n36@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory9", pos: "b", h: 48 }
n37@{ icon: "mdi:cog", form: "rounded", label: "Message a model in Perplexity5", pos: "b", h: 48 }
n38@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser2", pos: "b", h: 48 }
n39@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model11", pos: "b", h: 48 }
n40@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If2", pos: "b", h: 48 }
n41@{ icon: "mdi:robot", form: "rounded", label: "Adr finder", pos: "b", h: 48 }
n42["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Update a company1"]
n40 --> n41
n40 --> n42
n20 --> n3
n31 --> n21
n3 --> n31
n21 --> n40
n41 --> n10
n7 -.-> n21
n5 --> n20
n10 --> n9
n6 -.-> n21
n36 -.-> n41
n4 --> n1
n1 --> n5
n32 -.-> n21
n33 -.-> n8
n35 -.-> n41
n39 -.-> n38
n8 -.-> n21
n38 -.-> n41
n16 -.-> n21
n37 -.-> n41
n34 -.-> n21
end
subgraph sg2["Schedule Flow"]
direction LR
n19@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model4", pos: "b", h: 48 }
n27@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model5", pos: "b", h: 48 }
n28@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory5", pos: "b", h: 48 }
n29@{ icon: "mdi:robot", form: "rounded", label: "Level 2 Orchestrator", pos: "b", h: 48 }
n30@{ icon: "mdi:wrench", form: "rounded", label: "Email content", pos: "b", h: 48 }
n44@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory4", pos: "b", h: 48 }
n71@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger1", pos: "b", h: 48 }
n72@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet2", pos: "b", h: 48 }
n73@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items1", pos: "b", h: 48 }
n81@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser5", pos: "b", h: 48 }
n82["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Create an engagement"]
n83@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model7", pos: "b", h: 48 }
n84@{ icon: "mdi:database", form: "rounded", label: "Update row in sheet2", pos: "b", h: 48 }
n85["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>HTTP Request3"]
n86@{ icon: "mdi:cog", form: "rounded", label: "Extract from File", pos: "b", h: 48 }
n87@{ icon: "mdi:cog", form: "rounded", label: "Download file", pos: "b", h: 48 }
n88["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>HTTP Request6"]
n87 --> n86
n30 -.-> n29
n85 --> n87
n88 --> n73
n44 -.-> n29
n28 -.-> n30
n73 --> n29
n86 --> n88
n71 --> n72
n72 --> n73
n29 --> n85
n29 --> n84
n29 --> n82
n19 -.-> n29
n27 -.-> n30
n83 -.-> n81
n81 -.-> n29
end
subgraph sg3["When Executed by Another Workflow Flow"]
direction LR
n49@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Run an Actor1", pos: "b", h: 48 }
n50@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Get dataset items", pos: "b", h: 48 }
n54@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model14", pos: "b", h: 48 }
n55@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory10", pos: "b", h: 48 }
n56@{ icon: "mdi:play-circle", form: "rounded", label: "When Executed by Another Wor..", pos: "b", h: 48 }
n57@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser4", pos: "b", h: 48 }
n58@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model15", pos: "b", h: 48 }
n59@{ icon: "mdi:database", form: "rounded", label: "Append row in sheet", pos: "b", h: 48 }
n60@{ icon: "mdi:robot", form: "rounded", label: "apify_scraper", pos: "b", h: 48 }
n62@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet1", pos: "b", h: 48 }
n64@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields5", pos: "b", h: 48 }
n64 --> n49
n49 --> n50
n60 --> n62
n55 -.-> n60
n50 --> n59
n62 --> n64
n54 -.-> n60
n58 -.-> n57
n57 -.-> n60
n56 --> n60
end
subgraph sg4["Google Drive Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "Google Drive Trigger", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n74@{ icon: "mdi:cog", form: "rounded", label: "Limit1", pos: "b", h: 48 }
n75["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Create or update a contact"]
n76@{ icon: "mdi:database", form: "rounded", label: "Get row(s) in sheet", pos: "b", h: 48 }
n77@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter1", pos: "b", h: 48 }
n78["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/hubspot.svg' width='40' height='40' /></div><br/>Create a company"]
n79@{ icon: "mdi:database", form: "rounded", label: "Append row in sheet1", pos: "b", h: 48 }
n80@{ icon: "mdi:database", form: "rounded", label: "Update row in sheet1", pos: "b", h: 48 }
n89["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>HTTP Request7"]
n74 --> n2
n77 --> n74
n89 --> n2
n2 --> n78
n78 --> n75
n78 --> n89
n76 --> n77
n79 --> n80
n0 --> n76
n75 --> n79
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n90,n4,n71,n56,n0 trigger
class n18,n26,n51,n8,n21,n38,n41,n29,n81,n57,n60 ai
class n11,n13,n15,n22,n52,n53,n32,n33,n35,n39,n19,n27,n83,n54,n58 aiModel
class n23,n24,n25,n61,n68,n7,n30 ai
class n12,n45,n46,n47,n6,n36,n28,n44,n55 ai
class n3,n40,n49,n50,n77 decision
class n43,n63,n65,n69,n70,n34,n72,n84,n59,n62,n76,n79,n80 database
class n85,n88,n89 api
classDef customIcon fill:none,stroke:none
class n91,n1,n9,n42,n82,n85,n88,n75,n78,n89 customIcon
Why This Matters: Messy Leads Create Messy Revenue
Manual lead handling sounds harmless until you add it up. A “quick cleanup” turns into checking company domains, guessing job titles, deduping contacts, and rewriting the same email intro five different ways. Meanwhile, ownership is unclear, so follow-ups slip. And when your team is rushing, CRM hygiene is the first thing to go, which means reporting gets noisy and future sequences get worse. Honestly, the worst part is the mental load: you’re doing detective work when you should be selling.
It’s not one big failure. It’s lots of small friction points that stack together.
- Leads arrive with inconsistent fields (company names, domains, roles), so you burn time normalizing data before you can even qualify them.
- Email guesswork leads to bounces and wasted sends, and it also risks your domain reputation over time.
- Outreach copy drifts as different people “do their own thing,” so brand voice and compliance become a moving target.
- Updates get missed in HubSpot, which makes ownership and next steps harder to trust when you revisit the lead later.
What You’ll Build: From Lead Capture to Outlook Drafts
This workflow creates a reliable pipeline that starts with messy inbound leads and ends with a clean HubSpot record plus a send-ready Outlook draft waiting for review. It can trigger from new or updated HubSpot leads, or pull rows that are marked “ready” in Google Sheets, then processes them in controlled batches to avoid rate limits. Along the way it normalizes names, company and domain details, applies your ICP scoring rules, and enriches the lead by identifying likely decision-makers. Next, it finds and verifies a work email, logging confidence and timestamps immediately so you can audit what happened later. Finally, it generates compliant outreach using your approved HTML template, stores that content back in HubSpot, and creates an Outlook draft via Microsoft Graph (including your inline signature image from Google Drive).
It begins with lead intake (HubSpot or Sheets), then enrichment plus verification via HTTP lookups and AI-assisted logic. After that, the workflow composes the email using structured parsing so it stays on-template. The last stop is Outlook drafts and HubSpot updates, with follow-up tasks created automatically for the right owner.
What You’re Building
| What Gets Automated | What You’ll Achieve |
|---|---|
|
|
Expected Results
Say you process 20 inbound leads a day. Manually, even a “fast” routine is about 10 minutes to clean fields, 10 minutes to find and verify an email, and another 5 minutes to draft a decent first-touch message, which comes out to roughly 8 hours of work daily. With this workflow, you can let batching run in the background and spend about 5 minutes per lead reviewing the draft and making small tweaks. That’s about 6 hours back each day, plus far fewer data mistakes in HubSpot.
Before You Start
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- HubSpot for lead intake and CRM updates.
- Microsoft Outlook (Microsoft Graph) to create draft emails automatically.
- Google Sheets to track, queue, or log lead processing.
- Google Drive to host your signature image asset.
- OpenAI (or your LLM provider) to score, enrich, and generate compliant outreach.
- HubSpot app token (get it from HubSpot private app settings).
- Microsoft Graph OAuth (create an app registration in Azure).
- LLM API key (get it from your provider’s API dashboard).
Skill level: Intermediate. You will connect accounts, map a few HubSpot properties, and paste your approved HTML template.
Want someone to build this for you? Talk to an automation expert (free 15-minute consultation).
Step by Step
Lead intake and batching. A Cron schedule pulls “ready” rows from Google Sheets or checks HubSpot for new or updated leads. Items are processed sequentially in batches so you stay rate-safe across enrichment, verification, and email creation.
Normalization plus ICP scoring. The workflow cleans up names, company formatting, and domain hints, then applies your ICP rules. It writes the score and reasoning back to HubSpot (and/or Sheets), so your team can see why a lead was prioritized.
Enrichment and email verification. HTTP requests and AI-assisted lookups fill in company details and identify likely decision-makers. Then it finds a work email, checks deliverability, and logs confidence and timestamps to your tracking sheet.
Outreach composition and Outlook draft creation. Your approved HTML template is used to generate a structured email (personalized lightly, typically first name). Microsoft Graph creates an Outlook draft, and the signature image is fetched from Google Drive so the draft looks like your real outbound.
You can easily modify the scoring rules and the email template to match different ICPs, brands, or client accounts. See the full implementation guide below for customization options.
Troubleshooting Tips
- HubSpot credentials can expire or lack the right scopes. If contact updates fail, check your HubSpot private app permissions and token status first.
- Microsoft Graph OAuth can break if the Azure app consent or mailbox permissions change. When drafts stop appearing, review the app registration and confirm the account still has access to create drafts.
- If you’re using Wait nodes or external enrichment/verification services, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Quick Answers
About 45 minutes if your accounts and templates are ready.
No. You’ll connect HubSpot, Microsoft Graph, and Google tools, then map fields and paste your approved email HTML.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenAI API costs (often just a few dollars a month at moderate volume) and any paid email verification/enrichment services you connect via HTTP.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and you probably should. Most teams start by tweaking the ICP scoring rules (industry, region, size, tech stack) and the role/persona detection so the workflow targets the right decision-maker. You can swap the email template inside the “Email content” step, keep the Structured Output Parser validation, and still get predictable drafts. If you prefer Gmail, you can replace the Microsoft Graph draft creation with a Gmail node while keeping the same enrichment and verification sequence.
Usually it’s an expired token or missing scopes on the HubSpot private app. Regenerate the app token, update it in n8n, and double-check the workflow has permission to read/write contacts and any custom properties you mapped. If it only fails on certain leads, it can be a property type mismatch (for example, writing text into a numeric field) or a duplicate-handling edge case.
Most teams comfortably run a few hundred leads a day as long as batching and rate limits are configured sensibly.
Often, yes. This workflow leans on controlled batching, conditional logic, strict structured parsing, and idempotent “don’t create duplicates” writes, which are doable in Zapier/Make but get fiddly and expensive as the logic grows. n8n also gives you more transparency when something fails, so RevOps can actually debug what happened instead of guessing. If you only need “new lead → create draft email” with no enrichment, verification, or scoring, Zapier or Make can be perfectly fine. When you care about auditability and consistent output, n8n tends to win. Talk to an automation expert if you want help choosing.
Clean records, verified emails, and drafts your team can actually send. Set it up once, then let the workflow do the boring parts while you focus on the conversations.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.