The GmailBuilder class provides a fluent, chainable API for working with Google Apps Script’s GmailApp. It simplifies sending emails with recipients, attachments, HTML content, and thread operations.
Constructor
const mail = new GmailBuilder(appsql)
Optional APPSQL instance for context
Recipients
to()
Add primary recipients.
Email address(es) of primary recipients. Can be multiple arguments or arrays
Example:
cc()
Add CC (carbon copy) recipients.
bcc()
Add BCC (blind carbon copy) recipients.
Email address(es) for BCC
Email Content
subject()
Set the email subject.
Subject line of the email
body()
Set the plain text body.
Plain text body of the email
Always include a plain text body even when using HTML, as some email clients don’t support HTML rendering.
html()
Set the HTML body.
Example:
const mail = new GmailBuilder();
mail
.to("[email protected]")
.subject("Welcome!")
.body("Welcome to our service.") // Fallback for non-HTML clients
.html("<h1>Welcome!</h1><p>Welcome to our service.</p>");
Attachments and Images
attach()
Attach files to the email.
blobOrId
BlobSource | string | array
required
File to attach. Can be a BlobSource, Drive file ID, or array of either
Example:
// Attach from Drive file ID
mail.attach("DRIVE_FILE_ID");
// Attach blob source
const file = DriveApp.getFileById("FILE_ID");
mail.attach(file.getBlob());
// Attach multiple files
mail.attach(["FILE_ID_1", "FILE_ID_2"]);
inline()
Add inline images for HTML emails.
Reference name for the image (used in HTML as cid:name)
Example:
const logo = DriveApp.getFileById("LOGO_ID").getBlob();
mail
.to("[email protected]")
.subject("Newsletter")
.html('<img src="cid:logo" /><p>Check out our logo!</p>')
.inline("logo", logo);
Advanced Options
option()
Set additional GmailApp options.
Option key (e.g., “name”, “replyTo”)
Example:
Sending and Drafting
send()
Send the email immediately.
At least one recipient in to() is required to send an email.
Example:
const mail = new GmailBuilder();
mail
.to("[email protected]")
.subject("Hello from ServiceSQL")
.body("This is a test email.")
.send();
draft()
Create a draft instead of sending immediately.
Example:
const draft = new GmailBuilder()
.to("[email protected]")
.subject("Draft email")
.body("Review this before sending.")
.draft();
Thread Operations
thread()
Specify a thread ID for reply or forward operations.
reply()
Reply to a thread.
mail.reply(body, options)
Additional options for the reply
Example:
const mail = new GmailBuilder();
mail
.thread("THREAD_ID")
.reply("Thank you for your message.");
forward()
Forward a thread to another recipient.
mail.forward(to, options)
Email address to forward to
Additional options for forwarding
Example:
Thread Search
searchThreads()
Search for email threads.
mail.searchThreads(query, max)
Maximum number of threads to return
Example:
const mail = new GmailBuilder();
// Search for unread emails from a specific sender
const threads = mail.searchThreads(
"from:[email protected] is:unread",
20
);
getThread()
Get a specific thread by ID.
Complete Examples
Simple Email
function sendWelcomeEmail(userEmail, userName) {
const mail = new GmailBuilder();
mail
.to(userEmail)
.subject("Welcome to Our Service!")
.body(`Hi ${userName},\n\nWelcome to our platform!`)
.send();
}
HTML Email with Attachments
function sendDailyReport(recipients, reportFileId) {
const mail = new GmailBuilder();
const logo = DriveApp.getFileById("LOGO_ID").getBlob();
mail
.to(recipients)
.cc("[email protected]")
.subject("Daily Report - " + new Date().toLocaleDateString())
.body("Please see the attached daily report.")
.html(`
<img src="cid:logo" style="width: 150px;" />
<h1>Daily Report</h1>
<p>Please review the attached report for today's metrics.</p>
`)
.inline("logo", logo)
.attach(reportFileId)
.send();
}
Model Integration - Notifications
class Order extends Model {
static _table = "Orders";
sendConfirmation() {
const customer = this.customer(); // Relationship method
const mail = new GmailBuilder();
mail
.to(customer.email)
.subject(`Order Confirmation #${this.id}`)
.body(`
Thank you for your order!
Order ID: ${this.id}
Total: $${this.total}
We'll send you updates as your order is processed.
`)
.html(`
<h2>Thank you for your order!</h2>
<p><strong>Order ID:</strong> ${this.id}</p>
<p><strong>Total:</strong> $${this.total}</p>
<p>We'll send you updates as your order is processed.</p>
`)
.send();
}
}
Order.use(db);
// Usage
const order = Order.create({
customer_id: 1,
total: 99.99,
status: "pending"
});
order.sendConfirmation();
Automated Response System
function processIncomingEmails() {
const mail = new GmailBuilder();
// Search for unread emails with specific label
const threads = mail.searchThreads("label:support is:unread", 50);
threads.forEach(thread => {
const messages = thread.getMessages();
const firstMessage = messages[0];
// Auto-reply
mail
.thread(thread.getId())
.reply(`
Thank you for contacting support!
Your ticket has been received and will be reviewed shortly.
Reference: ${thread.getId()}
`);
// Mark as read and add processed label
thread.markRead();
thread.addLabel(GmailApp.getUserLabelByName("Processed"));
});
}
Best Practices
DO: Always provide both plain text and HTML versionsmail
.body("Plain text version")
.html("<p>HTML version</p>");
DO: Use descriptive subject lines// ✅ Good
mail.subject("Order #1234 Confirmation");
// ❌ Bad
mail.subject("Notification");
DO: Centralize email logic in services or models// ✅ Good - in a service/model method
class EmailService {
static sendWelcome(user) {
return new GmailBuilder()
.to(user.email)
.subject("Welcome!")
.body("...")
.send();
}
}
DON’T: Send emails without recipients// ❌ Throws error: Recipient (to) required
new GmailBuilder()
.subject("No recipient")
.send();
// ✅ Correct
new GmailBuilder()
.to("[email protected]")
.subject("Has recipient")
.send();
DON’T: Mix business logic with email constructionKeep the logic of when/why to send separate from how to construct the email.
Method Summary
| Category | Methods |
|---|
| Recipients | to(), cc(), bcc() |
| Content | subject(), body(), html(), option() |
| Attachments | attach(), inline() |
| Actions | send(), draft() |
| Threads | thread(), reply(), forward(), searchThreads(), getThread() |