Summarises new customer email and logs the summary on the matching Odoo lead or opportunity.
Uses
Claude
GmailOdoo
Summarise customer emails onto their Odoo record
Every hour, the recent mail in your Gmail inbox is read and each sender's address is looked up among the leads and opportunities in your Odoo CRM. When the address belongs to one, the AI writes a short note capturing what the email says, following the brief you give it, and the note is posted to that record's chatter. Mail from an address Odoo does not know is left completely alone.
You end up with a CRM that reflects the conversation without anyone copying it across by hand. No lead or opportunity is ever created, renamed or overwritten: the only thing written is a new chatter message on an existing record, so an unexpected match costs you a note you can delete rather than a bad record. An email with nothing worth recording is left unfiled. Each filed message gets a Gmail label and labelled mail is excluded from the next search, so the same email is never summarised twice; if the label cannot be applied the run says so and names the message.
noteBrief to blank.Set noteBrief to blank.filedLabel to Filed to Odoo.Set filedLabel to Filed to Odoo.mailSearch to newer_than:2d.Set mailSearch to newer_than:2d.maxEmails to 25.Set maxEmails to 25.inboxQuery to mailSearch -label:@filedLabel.Set inboxQuery to mailSearch -label:@filedLabel.inboxQuery. Save it as inbox.List emails matching inboxQuery. Save it as inbox.messages to inbox.emails.Set messages to inbox.emails.filedCount to 0.Set filedCount to 0.unmatchedCount to 0.Set unmatchedCount to 0.email in messages:For each email in messages:emailErrorIf a step below fails, save the error as emailErroremail.id and save it as messageId.Trim email.id and save it as messageId.email.from and save it as fromHeader.Trim email.from and save it as fromHeader.senderAddress to fromHeader.Set senderAddress to fromHeader.fromHeader contains <If fromHeader contains <fromHeader split by < split by > and save it as senderAddress.Trim the first item of the last item of fromHeader split by < split by > and save it as senderAddress.senderAddress contains @If senderAddress contains @found.Search crm.lead records. Save it as found.matches to found.records.Set matches to found.records.matches isn't emptyIf matches isn't emptymatches and save it as record.Get the first item of matches and save it as record.recordId to record.id.Set recordId to record.id.record.name and save it as recordName.Trim record.name and save it as recordName.email.subject and save it as subject.Trim email.subject and save it as subject.email.body and save it as emailBody.Trim email.body and save it as emailBody.prompt to You are writing one short note for a CRM record about an email a customer has just sent.Set prompt to You are writing one short note for a CRM record about an email a customer has just sent.
What the note should capture:
noteBrief
Rules:
- Reply with the note text only. No greeting, no preamble, no sign-off, no heading.
- Keep it under 120 words.
- Say only what this email actually says. Do not guess at anything it does not state, and do not add advice.
- If the email says nothing worth recording, reply with the single word none.
CRM record: recordName
From: senderAddress
Subject: subject
Email:
emailBody.prompt. Save it as written.Ask Claude: prompt. Save it as written.
Maximum response length: 400written.response_text and save it as summary.Trim written.response_text and save it as summary.summary isn't empty and summary is not noneIf summary isn't empty and summary is not nonenoteSubject to Email from senderAddress.Set noteSubject to Email from senderAddress.subject isn't emptyIf subject isn't emptynoteSubject to Email: subject.Change noteSubject to Email: subject.noteBody to <p>summary with "Set noteBody to <p>summary with
replaced by <br/></p><p><i>Emailed by senderAddress — Gmail message messageId</i></p>.filedCount.Add 1 to filedCount.labelErrorIf a step below fails, save the error as labelErrorfiledLabel to email messageId.Add label filedLabel to email messageId.messageId, so the next run may file it again. Add the label by hand to stop that: filedLabel.Show in the output: Filed a summary on '@recordName' but could not label Gmail message messageId, so the next run may file it again. Add the label by hand to stop that: filedLabel.senderAddress - left it unfiled.Show in the output: Nothing worth recording in the email from senderAddress - left it unfiled.unmatchedCount.Add 1 to unmatchedCount.senderAddress - nothing was created and the message was left unlabelled.Show in the output: No open Odoo lead or opportunity has the email senderAddress - nothing was created and the message was left unlabelled.email.id as text: emailError as text.Show in the output: Could not file the email email.id as text: emailError as text.filedCount as text email summaries onto Odoo records; unmatchedCount as text sender(s) had no matching lead or opportunity.Show in the output: Filed filedCount as text email summaries onto Odoo records; unmatchedCount as text sender(s) had no matching lead or opportunity.