BDS0.1

Legacy — Email Logging

Superseded by Email Capture on 2026-11-06. Old per-mailbox design; inactive, never published.

Reviewed 2026-11-06Markdown
Platform
n8n · Open in n8n
Status
Inactive
Workflow ID
YDwJwKWtayHrH0mC
Nodes
24
n8n version
ef290697-9cbf-46c6-ad18-73a6f6980857
Last saved in n8n
2026-11-06T16:58:26.654Z

Email Logging keeps a record of e-mail with customers. Every message in one Gmail mailbox, received or sent, becomes a Message in Communication. When the other person has an open Relationship in the CRM, the whole thread also becomes one Interaction on that Relationship, and the follow-up date moves: reply today when they wrote, check again in three days after the first message you sent. Mail between internal addresses and automatic senders is skipped. The workflow never creates a person.

The workflow is inactive. It has never been published in n8n, so nothing on this page is running yet. Before activating lists what has to be in place first. One copy of the workflow serves one mailbox.

Superseded. On 2026-11-06 this design was replaced by Email Capture and its two sub-workflows, which read one capture mailbox (non-reply@snackprompt.com) fed by Google Workspace routing instead of one Gmail credential per seller, and write Deals instead of Relationships. This workflow stays saved and inactive in n8n; this page describes it as saved, Relationship steps included, and will be removed when the workflow is deleted.

The Communication maintainer owns the Message records and the mailbox setup; the CRM maintainer owns the Interactions and the follow-up rules.

Flow

Generated from the n8n version in the box above: every box is a node and every arrow is a connection in n8n. Pink pills are triggers, yellow hexagons are If and Switch nodes with their outputs on the arrows, blue cylinders read (Airtable, Data Table, HTTP GET), green cylinders write, purple boxes call another workflow, and dashed arrows are error outputs.

CRM Interaction

Communication Message

Resolve the context

Read the mailbox

true

false

true

true

false

Gmail Trigger

Config

Normalize

Find Mailbox Account
GET Tooling Tool Account

Resolve Seller

Find Membership (CRM)
GET CRM Membership

Find Membership (Communication)
GET Communication Membership

Find Channel
GET Communication Channel

Find Person (CRM)
GET CRM People

Resolve Person

Find Person (Communication)
GET Communication Person

Find Message
GET Communication Message

Find Interaction
GET CRM Interaction

Find Relationships
GET CRM Relationship

Prepare

Message Exists?

Update Message
PATCH Communication Message

Create Message
POST Communication Message

Continue

Has Relationship?

Interaction Exists?

Update Interaction
PATCH CRM Interaction

Create Interaction
POST CRM Interaction

Mermaid source
flowchart TD
  subgraph g0["Read the mailbox"]
    n13(["Gmail Trigger"]):::trigger
    n0["Config"]:::logic
    n17["Normalize"]:::logic
  end
  subgraph g1["Resolve the context"]
    n6[("Find Mailbox Account<br/><small>GET Tooling Tool Account</small>")]:::read
    n20["Resolve Seller"]:::logic
    n8[("Find Membership (CRM)<br/><small>GET CRM Membership</small>")]:::read
    n7[("Find Membership (Communication)<br/><small>GET Communication Membership</small>")]:::read
    n4[("Find Channel<br/><small>GET Communication Channel</small>")]:::read
    n11[("Find Person (CRM)<br/><small>GET CRM People</small>")]:::read
    n19["Resolve Person"]:::logic
    n10[("Find Person (Communication)<br/><small>GET Communication Person</small>")]:::read
    n9[("Find Message<br/><small>GET Communication Message</small>")]:::read
    n5[("Find Interaction<br/><small>GET CRM Interaction</small>")]:::read
    n12[("Find Relationships<br/><small>GET CRM Relationship</small>")]:::read
    n18["Prepare"]:::logic
  end
  subgraph g2["Communication Message"]
    n16{{"Message Exists?"}}:::decision
    n22[("Update Message<br/><small>PATCH Communication Message</small>")]:::write
    n3[("Create Message<br/><small>POST Communication Message</small>")]:::write
    n1["Continue"]:::logic
  end
  subgraph g3["CRM Interaction"]
    n14{{"Has Relationship?"}}:::decision
    n15{{"Interaction Exists?"}}:::decision
    n21[("Update Interaction<br/><small>PATCH CRM Interaction</small>")]:::write
    n2[("Create Interaction<br/><small>POST CRM Interaction</small>")]:::write
  end
  n13 --> n0
  n0 --> n17
  n17 --> n6
  n6 --> n20
  n20 --> n8
  n8 --> n7
  n7 --> n4
  n4 --> n11
  n11 --> n19
  n19 --> n10
  n10 --> n9
  n9 --> n5
  n5 --> n12
  n12 --> n18
  n18 --> n16
  n16 -->|true| n22
  n16 -->|false| n3
  n22 --> n1
  n3 --> n1
  n1 --> n14
  n14 -->|true| n15
  n15 -->|true| n21
  n15 -->|false| n2
  classDef trigger fill:#fde7f3,stroke:#d6409f,color:#111
  classDef decision fill:#fff7e0,stroke:#c99a00,color:#111
  classDef read fill:#e8f1ff,stroke:#3b82f6,color:#111
  classDef write fill:#e7f8ee,stroke:#16a34a,color:#111
  classDef subflow fill:#f3e8ff,stroke:#9333ea,color:#111
  classDef wait fill:#f1f1f1,stroke:#888,color:#111
  classDef logic fill:#ffffff,stroke:#999,color:#111

Systems it touches

System Table Reads Writes
Tooling and Access Tool Account Find Mailbox Account Nothing
CRM Membership (mirror) Find Membership (CRM) Nothing
CRM People (mirror) Find Person (CRM) Nothing
CRM Relationship Find Relationships Nothing
CRM Interaction Find Interaction Create Interaction, Update Interaction
Communication Membership (mirror) Find Membership (Communication) Nothing
Communication Channel Find Channel Nothing
Communication Person (mirror) Find Person (Communication) Nothing
Communication Message Find Message Create Message, Update Message

Every Airtable call is an HTTP Request node with one Airtable token credential. Reads filter by field name: {Login Alias} and {Tool} in Tool Account, {Membership #} in the CRM Membership mirror, {Membership ID} in the Communication Membership mirror, {External Identifier} in Channel, {Email} in both People mirrors, {External Message Id} in Message and {Evidence URL} in Interaction. Writes use field IDs. Renaming one of those fields breaks its lookup without an error: the node returns no record and the flow goes on as if nothing matched.

The CRM and Communication pages describe the records this workflow fills: Communication, CRM and Tooling and Access, where the mailbox’s Tool Account and its membership binding live.

Trigger and mailbox

Gmail Trigger polls the mailbox of its Gmail credential every minute with the search in:inbox OR in:sent, read and unread, and returns full messages (not the simplified format). Each new message is one item.

Config sets two values that every later node reads: mailbox, the address of this copy’s mailbox, and internalDomains, a comma-separated list of the company’s own e-mail domains. The mailbox in Config must be the same mailbox as the Gmail credential; nothing checks that they match.

What Normalize keeps

Normalize turns each message into one item and drops the ones that are not customer contact.

Value How it is set
Direction Outbound when the sender is the mailbox or Gmail labels the message SENT; Inbound otherwise
Counterparty Inbound: the sender. Outbound: the first address in To, then Cc, that is not on an internal domain. Other recipients are ignored
Skipped No counterparty, a counterparty on an internal domain, or an address matching no-reply, noreply, mailer-daemon, notification or notifications
Gmail id and thread id Gmail’s id and threadId; the thread id falls back to the message id
Subject subject, cut to 250 characters; “(no subject)” when missing
Sent at The message date; the processing time when the date cannot be read
Body The plain-text part, or the Gmail snippet, cut to 20,000 characters
Snippet The Gmail snippet, or the body, on one line and cut to 300 characters
Thread link https://mail.google.com/mail/u/0/#all/ followed by the thread id

When every message of a poll is skipped, the execution ends at Normalize.

Resolve the context

Each kept message runs nine lookups in a row, one HTTP call each.

  1. Mailbox account. Find Mailbox Account looks in Tooling for the Tool Account whose Login Alias is the mailbox and whose Tool contains Google Workspace. Resolve Seller reads its Bound Membership ID.
  2. Memberships. Find Membership (CRM) looks for the CRM Membership whose Membership # starts with that number followed by “ - “. Its Business Unit becomes the accountable company. Find Membership (Communication) looks for the Communication Membership with that Membership ID. With no Bound Membership ID, both lookups find nothing.
  3. Channel. Find Channel looks for the Communication Channel whose External Identifier is the mailbox.
  4. People. Find Person (CRM) looks for the counterparty’s e-mail in the CRM People mirror and Resolve Person collects the Relationships linked to it. Find Person (Communication) looks for the same e-mail in the Communication Person mirror.
  5. Existing records. Find Message looks for a Message whose External Message Id is the Gmail id. Find Interaction looks for an Interaction whose Evidence URL is the thread link.
  6. Relationship. Find Relationships reads the person’s Relationships. Prepare keeps the ones whose Stage* is not Lost or Disqualified and takes the first whose Accountable (Company)* contains the accountable company, then the first whose Accountable (Membership)* contains the membership, then the first open one.

Prepare then builds both records and adds a note when something is missing: no Tool Account for the mailbox, no membership, the counterparty not in the CRM People mirror, or no open Relationship. The notes go into the Message’s Failure Reason.

Write the Message

Message Exists? sends the item to Update Message when Find Message found one, and to Create Message otherwise. Both send the same fields, so processing a message again overwrites its Message with the same values. Continue then hands the prepared item to the CRM part.

The Message is written even when the person or the Relationship is missing; that is the only record such a message gets.

Write the Interaction

Has Relationship? stops the item unless Prepare found an open Relationship. Interaction Exists? then sends it to Update Interaction when an Interaction already has this thread link, and to Create Interaction otherwise. One thread is one Interaction: its Date* and Result follow the latest message processed.

Message Result Next Contact Date° Next Action°
Inbound, any Answered Today “Reply to <name>: <subject>”
Outbound, first in the thread No answer Today plus three days “Follow up if no reply: <subject>”
Outbound, later in the thread No answer Not changed Not changed

“Today” is the UTC date at processing time.

Fields written

Communication Message (Create Message and Update Message)

Field Value
Name Subject
Body Plain-text body, up to 20,000 characters
Sent At Sent at
Status Received for inbound, Sent for outbound
External Message Id Gmail id
Direction Inbound or Outbound
Thread Id Gmail thread id
Context Base CRM
About Keys One line each: email: counterparty, mailbox: mailbox, gmail: Gmail id, and rfc: Message-ID when present
Context Key Relationship/ followed by the Relationship record ID, when an open Relationship was found
Channel The mailbox’s Channel, when found
Recipients (Person) Outbound only: the counterparty in the Communication Person mirror, when found
Recipients (Membership) Inbound only: the mailbox’s membership in the Communication Membership mirror, when found
Failure Reason The notes from Prepare, when there are any

CRM Interaction

Field Create Interaction Update Interaction
Person (link to Relationship; deleted on 2026-11-04) The open Relationship Not changed
Date* Sent at Sent at of this message
Title* Subject Not changed
Type Email Not changed
Description° “E-mail thread with <name> <e-mail> via <mailbox>. First message (<direction>): <snippet>” Not changed
Result Answered or No answer Answered or No answer
Evidence URL Thread link Thread link
Next Contact Date° See the table above See the table above
Next Action° See the table above See the table above
Accountable (Membership) The membership, when found Not changed
Accountable (Company) The membership’s Business Unit, when found Not changed

In the Interaction table, the field named Person was the link to Relationship; it was deleted with that table on 2026-11-04. Every write sends typecast: true: a select value that does not exist yet is created as a new option. Message Status has no Received option today, so the first inbound message creates it.

Nodes

The workflow has 24 nodes: 23 that run and one sticky note. For an If node, output 0 is true and output 1 is false.

Node Type What it does
Gmail Trigger gmailTrigger Polls the mailbox every minute for inbox and sent mail
Config set Sets the mailbox address and the internal domains
Normalize code One item per e-mail; drops internal and no-reply mail
Find Mailbox Account httpRequest Tooling Tool Account of the mailbox
Resolve Seller code Reads Bound Membership ID and builds the membership lookups
Find Membership (CRM) httpRequest CRM Membership mirror by membership number
Find Membership (Communication) httpRequest Communication Membership mirror by Membership ID
Find Channel httpRequest Communication Channel of the mailbox
Find Person (CRM) httpRequest CRM People mirror by counterparty e-mail
Resolve Person code Builds the lookup of the person’s Relationships
Find Person (Communication) httpRequest Communication Person mirror by counterparty e-mail
Find Message httpRequest Message with the same External Message Id
Find Interaction httpRequest Interaction with the same thread link in Evidence URL
Find Relationships httpRequest The person’s CRM Relationships
Prepare code Picks the Relationship and builds the Message and Interaction bodies
Message Exists? if Update or create the Message
Update Message httpRequest PATCH the existing Message
Create Message httpRequest POST a new Message
Continue code Hands the prepared item on after the Message write
Has Relationship? if Stop unless an open Relationship was found
Interaction Exists? if Update or create the Interaction
Update Interaction httpRequest PATCH the thread Interaction
Create Interaction httpRequest POST the thread Interaction
Sticky Note stickyNote Setup note on the canvas; does not run

Connections

From Output To
Gmail Trigger 0 Config
Config 0 Normalize
Normalize 0 Find Mailbox Account
Find Mailbox Account 0 Resolve Seller
Resolve Seller 0 Find Membership (CRM)
Find Membership (CRM) 0 Find Membership (Communication)
Find Membership (Communication) 0 Find Channel
Find Channel 0 Find Person (CRM)
Find Person (CRM) 0 Resolve Person
Resolve Person 0 Find Person (Communication)
Find Person (Communication) 0 Find Message
Find Message 0 Find Interaction
Find Interaction 0 Find Relationships
Find Relationships 0 Prepare
Prepare 0 Message Exists?
Message Exists? 0 Update Message
Message Exists? 1 Create Message
Update Message 0 Continue
Create Message 0 Continue
Continue 0 Has Relationship?
Has Relationship? 0 Interaction Exists?
Interaction Exists? 0 Update Interaction
Interaction Exists? 1 Create Interaction

Settings and error handling

Setting Value
Status Inactive; never published
Execution order v1
Error workflow None
Retry on fail On every HTTP Request node, 3 tries
On error Stop the workflow (default) on every node
Caller policy Workflows from the same owner
Available in MCP No
Execution data retention Instance default; this workflow sets none

The schedule is the Gmail Trigger poll, every minute. A call that still fails after three tries stops the execution; the items already written in that execution stay written.

Before activating

Check each item in the systems, then publish the workflow in n8n.

Step Where State at the last review
The Gmail credential on Gmail Trigger belongs to the mailbox this copy logs n8n A credential is selected
Config mailbox is that mailbox and internalDomains lists every company domain n8n Filled
Find Relationships, Prepare and the Interaction writes use Deals instead of the deleted Relationship table and Person field n8n Pending; the nodes still read Relationship
The mailbox has a Tool Account with Login Alias = mailbox, Tool = Google Workspace and a Bound Membership ID Tooling and Access The Tool Account exists; Bound Membership ID is empty, so every Message would carry a “no active Identity Binding” note and Interactions would have no Accountable
A Channel with External Identifier = mailbox Communication Missing; Messages would have no Channel
Message Status has the option Received Communication Missing; the first inbound message creates it through typecast
A second mailbox gets its own copy, with its own credential and Config n8n One copy exists

Known gaps

The workflow has never run. These come from the node configuration.

Gap Effect
Gmail thread ids are per mailbox Two logged mailboxes on the same conversation make two Interactions
The thread link always uses /u/0/ It opens the thread only when the mailbox is the first Google account signed in to the browser
Every outbound message sets Result to No answer A reply you send after the customer answered turns an Answered Interaction back to No answer
The Relationship falls back to the first open one With no company or membership match, the thread lands on any open Relationship of that person, even another seller’s
Only the first external recipient counts A message to several customers is logged for one of them
“Today” and “plus three days” use the UTC date Mail processed late in the evening in Brazil gets the next day
Failure Reason holds informational notes A Message that was delivered fine shows text in a field named Failure Reason
The warning for a missing CRM person says “not a Person in Core” The lookup is on the CRM People mirror; the person may exist in Core and not be mirrored yet
Find nodes read one page (up to 100 records) A person with more than 100 Relationships can be matched to the wrong one
Up to eleven Airtable calls per message A large first poll can hit Airtable’s rate limit; the three retries absorb short bursts only
The Message is never linked to its Interaction Context Key holds the Relationship, not the Interaction

Recover a partial write

Look at what was saved before you process a message again.

What was saved What to do
Message written, Interaction failed Run it again; the Message is updated in place and the Interaction is created or updated by thread link
Message with “no open Relationship” Log the Interaction by hand on the Deal; the Relationship table no longer exists
Message with a membership warning Fill Bound Membership ID on the mailbox’s Tool Account, then set Accountable on the Interactions created meanwhile
Two Interactions for one thread Keep one, keep its Evidence URL, then delete the other

Keep this page in sync

The box at the top shows the n8n version this page describes. Open the workflow in n8n: when its last save is newer than the date in the box, this page is out of date until the next review. Every node and every connection of that version is listed in Nodes and Connections.