Disclosure: Signatoro's founder built the Signatoro Zapier app and invited me to its beta so I could build the lesson this post extends. I'm not paid by Signatoro and there's no affiliate link.
Every inquiry email that waits for an answer is a lead that might book somewhere else. That's the business case for a Zap that drafts the reply before anyone opens the email. My free lesson builds that Zap for Brookside Dental, a made-up family practice: four steps, and a person still checks every draft before it goes.
Once you run it on a real inbox, though, you notice the input is messier than the test email. People reply on top of a three-month-old thread. Their phone adds "Sent from my iPhone" and a 12-line signature. An out-of-office auto-reply comes in and gets a warm, personal response.
The AI isn't the problem in any of those cases. The text you hand it is. So I add one small step before the AI step that cleans the email. This post is that step.
The Zap from the lesson
- New Email in Gmail (a polling trigger that checks the inbox every few minutes).
- Conversation in ChatGPT (OpenAI), with the prompt and the email's Body Plain inserted.
- Get Signature in Signatoro (1.0.0), which adds the sender's real signature after ChatGPT's reply.
- Create Draft Reply in Gmail, in the same thread, with Body Type set to HTML.
The model writes the message and never signs it, so every draft carries the right name, title and phone number. The Signatoro app is invite-only while it's in beta.
What follows is my addition, not part of the lesson: a Code by Zapier step between 1 and 2, and a Filter right after it. That makes it a six-step Zap. Zapier's free plan runs two-step Zaps, so you're on the free trial or a paid plan for this one either way.
What the cleanup does
- Cuts the quoted thread ("On Tue, Oct 14, ... wrote:" and lines starting with
>). - Cuts the sender's signature block where it's marked with the standard
--line, plus common phone footers. - Collapses blank lines and caps the length, so a pasted 40-page document doesn't become a huge AI call.
- Pulls a first name from the sender's display name, for the greeting.
- Flags auto-replies, so a Filter can stop the Zap before ChatGPT runs.
The Code by Zapier step (JavaScript)
Add an action, pick Code by Zapier, choose Run JavaScript. Under Input Data, map three fields from the Gmail trigger: body (Body Plain), fromName (the sender's name) and subject.
Code by Zapier hands those to your code as inputData, and whatever object you return becomes the step's output fields:
const raw = String(inputData.body || '');
const subject = String(inputData.subject || '');
const fromName = String(inputData.fromName || '').trim();
// 1. Cut the quoted thread: everything from "On ... wrote:" or a "From:" header down
const cutMarkers = [
/^On .+wrote:\s*$/m,
/^-{2,}\s*Original Message\s*-{2,}/mi,
/^From:\s.+$/m,
];
let body = raw;
for (const re of cutMarkers) {
const m = body.match(re);
if (m && m.index > 0) body = body.slice(0, m.index);
}
// 2. Drop quoted lines and common footers
body = body
.split('\n')
.filter(line => !line.trim().startsWith('>'))
.join('\n');
const sigIndex = body.search(/^--\s*$/m); // standard "-- " signature line
if (sigIndex > 0) body = body.slice(0, sigIndex);
body = body.replace(/^Sent from my .+$/gmi, '');
// 3. Tidy whitespace and cap length
body = body.replace(/\n{3,}/g, '\n\n').trim();
const MAX_CHARS = 4000;
const truncated = body.length > MAX_CHARS;
if (truncated) body = body.slice(0, MAX_CHARS);
// 4. First name for the greeting ("Dana Whitfield" -> "Dana"; "Whitfield, Dana" -> "Dana")
let firstName = '';
if (fromName.includes(',')) {
firstName = fromName.split(',')[1].trim().split(/\s+/)[0] || '';
} else {
firstName = fromName.split(/\s+/)[0] || '';
}
firstName = firstName.replace(/[^\p{L}'-]/gu, '');
// 5. Auto-replies should not get an AI answer
const autoReply = /\b(out of (the )?office|automatic reply|auto-?reply|away from my desk)\b/i
.test(subject + ' ' + raw.slice(0, 500));
return {
cleanBody: body,
firstName,
truncated,
isAutoReply: autoReply,
};
Test the step with a real email from your inbox, not a tidy one you wrote yourself. Look at cleanBody in the test output and check that the customer's actual question is still there. If a regular sender's mail client quotes threads differently, add their marker to cutMarkers.
The same step in Python
If you'd rather use Run Python, the input is input_data and the result goes in a variable called output:
import re
raw = input_data.get('body') or ''
subject = input_data.get('subject') or ''
from_name = (input_data.get('fromName') or '').strip()
body = raw
for pattern in [r'^On .+wrote:\s*$', r'^-{2,}\s*Original Message\s*-{2,}', r'^From:\s.+$']:
m = re.search(pattern, body, flags=re.M | re.I)
if m and m.start() > 0:
body = body[:m.start()]
body = '\n'.join(l for l in body.split('\n') if not l.strip().startswith('>'))
sig = re.search(r'^--\s*$', body, flags=re.M)
if sig and sig.start() > 0:
body = body[:sig.start()]
body = re.sub(r'^Sent from my .+$', '', body, flags=re.M | re.I)
body = re.sub(r'\n{3,}', '\n\n', body).strip()
truncated = len(body) > 4000
body = body[:4000]
if ',' in from_name:
parts = from_name.split(',')[1].split()
else:
parts = from_name.split()
first_name = parts[0] if parts else ''
auto = re.search(r'\b(out of (the )?office|automatic reply|auto-?reply|away from my desk)\b',
subject + ' ' + raw[:500], flags=re.I) is not None
output = {'cleanBody': body, 'firstName': first_name, 'truncated': truncated, 'isAutoReply': auto}
The Filter, then the AI step
Right after the Code step, add Filter by Zapier: only continue if isAutoReply is false. An out-of-office message now ends the Zap quietly, and you don't pay for an AI call to answer a robot.
Then, in ChatGPT's Configure tab, insert cleanBody and firstName from the Code step instead of the raw Body Plain. The lesson's prompt only needs two small edits at the end:
You are the front desk at Brookside Dental, a friendly family dental practice.
Write a short email reply to a patient who just emailed us. Greet them by first
name and thank them. Respond to what they asked in one or two warm sentences.
Say we will call within one business day to book a time. No medical advice, no
prices, no promises about treatment. End with a short closing line such as
"Kind regards," and no name or signature: the signature is added after the
email. Write only the email body, as simple HTML with each paragraph in p tags.
The patient's first name: (insert firstName from the Code step)
The patient's email: (insert cleanBody from the Code step)
If firstName comes back empty (a sender named "info"), the model just greets them without a name. I'd rather that than a guess.
Why clean before the AI, not after
You could ask ChatGPT to "ignore quoted text and signatures." Sometimes it does. But code is cheaper, it does the same thing every run, and you can read exactly what it removed in the step's test output. I keep the AI step for the part that actually needs judgment: writing a warm reply to what the person asked.
The rest of the lesson's advice still holds. Keep the Signatoro and OpenAI keys in Zapier's connections, never in the prompt. Don't also pick a Gmail signature in Create Draft Reply, or the reply is signed twice. And keep it a draft reply until the drafts have been right for a few weeks.
Try it free
The lesson, Zapier: ChatGPT Drafts Every Reply, Signatoro Signs It, builds the four-step Zap in 35 steps on real Zapier and Signatoro screens. Add the Code step from this post once the basic Zap works.
Practice it step by step, free: https://learn.ynteractive.com/content/zapier-chatgpt-gmail-reply-signatoro-signature
Top comments (0)