Send a weekly digest of unreplied emails
Surface inbox threads you haven't answered in a single Monday-morning summary.
Published Jul 22, 2025
A busy inbox quietly hides the threads that matter. An email gets read on a phone, marked for “later”, and slides down the list — and the sender is left waiting. By the time it resurfaces the reply is overdue and the relationship is a little frostier than it needed to be.
Awadesh at Northwind wanted to start every Monday knowing exactly which threads he still owed a reply on, without scrolling the whole inbox. This script builds that list for him. Once a week it searches for unread threads where the last message came from someone else, formats them into a short digest, and emails it to himself — a single, scannable to-do list waiting at 7am.
What you’ll need
- A Gmail account — the script runs as you and reads your own inbox.
- Nothing to set up in advance. The digest is sent to the address running the script, so there is no sheet, label, or template to create.
- Optional: a sense of which Gmail search filters fit your inbox, so you can tighten the query (see “Tighten the filter”).
The script
// How far back to look for threads that might still need a reply.
const LOOKBACK = 'newer_than:14d';
/**
* Builds a once-a-week digest of inbox threads where the most recent
* message came from someone other than you, then emails it to yourself.
*/
function weeklyUnrepliedDigest() {
// 1. Work out who "me" is, so we can spot our own replies.
const me = Session.getActiveUser().getEmail();
// 2. Find recent unread threads in the inbox that we did not start.
const threads = GmailApp.search(`in:inbox is:unread -from:me ${LOOKBACK}`);
// 3. Keep only threads whose last message is from the other side.
// This drops threads we have already answered.
const overdue = threads.filter((thread) => {
const messages = thread.getMessages();
const last = messages[messages.length - 1];
return last.getFrom() !== me;
});
// 4. Nothing outstanding — skip the email entirely.
if (overdue.length === 0) {
Logger.log('Inbox zero on replies — no digest sent.');
return;
}
// 5. Turn each overdue thread into a one-line, linked summary.
const lines = overdue.map((thread) => {
const lastMessage = thread.getMessages().slice(-1)[0];
const from = lastMessage.getFrom().replace(/<.+>/, '').trim();
const url = `https://mail.google.com/mail/u/0/#inbox/${thread.getId()}`;
return `• [${thread.getFirstMessageSubject()}](${url}) — ${from}`;
});
// 6. Send the digest to yourself.
GmailApp.sendEmail(
me,
`${overdue.length} threads still owe a reply`,
lines.join('\n'),
);
Logger.log(`Digest sent with ${overdue.length} thread(s).`);
}
How it works
Session.getActiveUser().getEmail()returns the address the script runs under, which is later used to recognise your own messages.- The Gmail search
in:inbox is:unread -from:me newer_than:14dcollects recent unread threads you did not send. The 14-dayLOOKBACKkeeps very old threads out of the digest. - For each thread the script inspects the last message. If that message is not from you, the thread still needs a reply. This neatly handles the case where you replied but the other side wrote back again.
- If nothing is outstanding, the script logs that and stops — no empty digest lands in your inbox.
- Each overdue thread becomes a bullet with a clickable link straight to the
thread, plus the sender’s display name (the
<address>part is stripped). GmailApp.sendEmailsends the assembled list to yourself with the count in the subject line.
Example run
Suppose three threads are unanswered when the digest runs on Monday morning. The email you receive looks like this:
Subject: 3 threads still owe a reply
• Q3 retainer renewal — Priya Shah • Logo files — final round? — Tom Reed • Invoice 1182 query — [email protected]
Each subject is a link straight into the thread, so clearing the list is three clicks rather than three searches.
Trigger it
This runs once a week, so set a time-driven trigger:
- In the Apps Script editor open Triggers (the clock icon).
- Add a trigger for
weeklyUnrepliedDigest, choose Time-driven, then Week timer, Every Monday, and the 7am to 8am slot. - Approve the authorisation prompt the first time it runs.
Monday at 7am means the digest is the first thing waiting when the working week starts.
Watch out for
is:unreadis doing real work here. If you read a thread without replying, it drops out of the digest — so the list reflects unread and unanswered, not every thread you owe. Dropis:unreadif you want a stricter list, but expect it to be longer.- The last-message check uses an exact
getFrom()string match. If you send mail from an alias, that alias will not equalmeand your own replies may be counted as the other side’s. Add the alias to the comparison if so. - Automated senders (newsletters, notifications) can clutter the digest. Use the filters below to exclude them.
- The links use mailbox
u/0. If you run multiple Google accounts in one browser, the digest may open the wrong mailbox — changeu/0to your account index.
Tighten the filter
- Add
label:supportto focus the digest on a single shared inbox or label. - Add
-from:(noreply OR notifications)to ignore machine-generated senders. - Add
is:importantto surface only the threads Gmail already flags as high-priority.
Related
Send meeting follow-ups with the notes attached
After a Calendar event ends, email attendees the linked notes Doc automatically.
Updated May 19, 2026
Embed inline charts in a status email
Render a Sheets chart as an image inside the email body, not as an attachment.
Updated May 12, 2026
Send HTML email from a Google Doc template
Use a styled Doc as the source for branded, on-brand HTML email — no design tool needed.
Updated May 5, 2026
Parse bank-alert emails into an expense ledger
Convert transaction alerts from Northwind's bank into categorised spend rows automatically.
Updated Apr 28, 2026
Generate a printable address book from contacts
Export Northwind's Google Contacts to a formatted Doc you can actually print.
Updated Apr 21, 2026