Gmail / Google Workspace provider for the MemberJunction Communication Framework. This provider enables full mailbox operations -- sending, receiving, searching, managing labels, attachments, drafts, and more -- through the Gmail API with OAuth2 authentication.
graph TD
subgraph gmail["@memberjunction/communication-gmail"]
GP["GmailProvider"]
AUTH["Auth Module\n(OAuth2 Client)"]
CFG["Config Module\n(Environment Variables)"]
CRED["GmailCredentials"]
end
subgraph google["Google APIs"]
OAUTH["Google OAuth2"]
GAPI["Gmail API v1\n(/users/me/...)"]
MAILBOX["Gmail Mailbox"]
end
subgraph base["@memberjunction/communication-types"]
BCP["BaseCommunicationProvider"]
end
BCP --> GP
GP --> AUTH
GP --> CFG
GP --> CRED
AUTH --> OAUTH
GP --> GAPI
GAPI --> MAILBOX
style gmail fill:#2d6a9f,stroke:#1a4971,color:#fff
style google fill:#7c5295,stroke:#563a6b,color:#fff
style base fill:#2d8659,stroke:#1a5c3a,color:#fff
npm install @memberjunction/communication-gmail
Set the following environment variables:
GMAIL_CLIENT_ID=your-oauth2-client-id
GMAIL_CLIENT_SECRET=your-oauth2-client-secret
GMAIL_REDIRECT_URI=your-redirect-uri
GMAIL_REFRESH_TOKEN=your-refresh-token
GMAIL_SERVICE_ACCOUNT_EMAIL=noreply@yourdomain.com # optional default sender
https://www.googleapis.com/auth/gmail.sendhttps://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/gmail.composeThis provider supports all 14 operations defined in BaseCommunicationProvider:
| Operation | Gmail Implementation |
|---|---|
SendSingleMessage |
Send via users.messages.send |
GetMessages |
List and fetch with Gmail search query support |
GetSingleMessage |
Fetch single message by ID |
ForwardMessage |
Reconstruct and send as RFC 822 attachment |
ReplyToMessage |
Send in same thread via threadId |
CreateDraft |
Create via users.drafts.create |
DeleteMessage |
Trash or permanently delete |
MoveMessage |
Add/remove labels via users.messages.modify |
ListFolders |
List labels with optional message/unread counts |
MarkAsRead |
Add/remove UNREAD label (batch) |
ArchiveMessage |
Remove INBOX label |
SearchMessages |
Gmail query syntax with date filters |
ListAttachments |
Parse message parts recursively for attachments |
DownloadAttachment |
Download via users.messages.attachments.get |
import { CommunicationEngine } from '@memberjunction/communication-engine';
import { Message } from '@memberjunction/communication-types';
const engine = CommunicationEngine.Instance;
await engine.Config(false, contextUser);
const message = new Message();
message.From = 'sender@gmail.com';
message.To = 'recipient@example.com';
message.Subject = 'Hello from Gmail';
message.HTMLBody = '<h1>Hello</h1>';
message.CCRecipients = ['cc@example.com'];
const result = await engine.SendSingleMessage('Gmail', 'Email', message);
Override credentials for multi-user scenarios:
import { GmailCredentials } from '@memberjunction/communication-gmail';
const result = await provider.SendSingleMessage(processedMessage, {
clientId: 'other-client-id',
clientSecret: 'other-secret',
redirectUri: 'other-redirect',
refreshToken: 'user-specific-refresh-token'
} as GmailCredentials);
const provider = engine.GetProvider('Gmail');
const result = await provider.GetMessages({
NumMessages: 10,
UnreadOnly: true,
ContextData: {
query: 'from:important@example.com', // Gmail search syntax
MarkAsRead: true
}
});
result.Messages.forEach(msg => {
console.log(`${msg.From}: ${msg.Subject}`);
console.log(`Thread: ${msg.ThreadID}`);
});
const result = await provider.CreateDraft({ Message: processedMessage });
if (result.Success) {
console.log(`Draft ID: ${result.DraftID}`);
// Draft appears in Gmail drafts folder
}
const result = await provider.SearchMessages({
Query: 'has:attachment',
FromDate: new Date('2025-01-01'),
ToDate: new Date('2025-06-01'),
FolderID: 'INBOX', // Gmail label ID
MaxResults: 50
});
const folders = await provider.ListFolders({ IncludeCounts: true });
folders.Folders.forEach(f => {
console.log(`${f.Name} (${f.ID}): ${f.MessageCount} messages`);
console.log(` System: ${f.IsSystemFolder}, Type: ${f.SystemFolderType}`);
});
const attachments = await provider.ListAttachments({ MessageID: 'msg-id' });
for (const att of attachments.Attachments) {
const download = await provider.DownloadAttachment({
MessageID: 'msg-id',
AttachmentID: att.ID
});
// download.Content is a Buffer
// download.ContentBase64 is base64 string
// download.Filename, download.ContentType available
}
Gmail uses labels instead of traditional folders. The provider maps system labels to standard folder types:
| Gmail Label | SystemFolderType |
|---|---|
INBOX |
inbox |
SENT |
sent |
DRAFT |
drafts |
TRASH |
trash |
SPAM |
spam |
| User labels | undefined |
The provider caches Gmail API client instances for performance. Environment credential clients are shared across all calls; per-request credential clients are cached by a key derived from clientId and refreshToken.
| Package | Purpose |
|---|---|
@memberjunction/communication-types |
Base provider class and type definitions |
@memberjunction/core |
Logging utilities |
@memberjunction/global |
RegisterClass decorator |
googleapis |
Google APIs Node.js client |
dotenv |
Environment variable loading |
env-var |
Environment variable validation |
npm run build # Compile TypeScript
npm run clean # Remove dist directory