Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,24 @@ List all unsubscribe groups.
// No parameters required
```

#### create_suppression_group
Create an unsubscribe (ASM suppression) group. Emails sent with the group get a working unsubscribe link and SendGrid enforces the suppression list.
```typescript
{
name: string; // Required: Shown to recipients on the unsubscribe page (max 30 chars)
description: string; // Required: What kind of emails this covers (max 100 chars)
is_default?: boolean; // Optional: Use when a send specifies no group (default false)
}
```

#### delete_suppression_group
Delete an unsubscribe group by its numeric ID.
```typescript
{
group_id: number; // Required: Numeric suppression group ID
}
```

## Installation

```bash
Expand Down
118 changes: 117 additions & 1 deletion src/services/sendgrid.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Client } from '@sendgrid/client';
import sgMail from '@sendgrid/mail';
import { SendGridContact, SendGridList, SendGridTemplate, SendGridStats, SendGridSingleSend } from '../types/index.js';
import { SendGridContact, SendGridList, SendGridTemplate, SendGridStats, SendGridSingleSend, SendGridDesign } from '../types/index.js';

export class SendGridService {
private client: Client;
Expand Down Expand Up @@ -308,6 +308,122 @@ export class SendGridService {
return response.body;
}

async createSuppressionGroup(params: {
name: string;
description: string;
is_default?: boolean;
}): Promise<{ id: number; name: string; description: string; is_default: boolean }> {
const [response] = await this.client.request({
method: 'POST',
url: '/v3/asm/groups',
body: params
});
return response.body as { id: number; name: string; description: string; is_default: boolean };
}

async deleteSuppressionGroup(groupId: number) {
const [response] = await this.client.request({
method: 'DELETE',
url: `/v3/asm/groups/${groupId}`
});
return response.body;
}

// Design Management
async listDesigns(pageSize: number = 100): Promise<SendGridDesign[]> {
const allDesigns: SendGridDesign[] = [];
let pageToken: string | undefined;

do {
const qs: Record<string, any> = { page_size: pageSize };
if (pageToken) {
qs.page_token = pageToken;
}

const [response] = await this.client.request({
method: 'GET',
url: '/v3/designs',
qs
});

const body = response.body as {
result: SendGridDesign[];
_metadata: { self: string; count: number; next?: string };
};
allDesigns.push(...(body.result || []));

// Extract page_token from next URL if present
if (body._metadata?.next) {
const url = new URL(body._metadata.next, 'https://api.sendgrid.com');
pageToken = url.searchParams.get('page_token') || undefined;
} else {
pageToken = undefined;
}
} while (pageToken);

return allDesigns;
}

async getDesign(designId: string): Promise<SendGridDesign> {
const [response] = await this.client.request({
method: 'GET',
url: `/v3/designs/${designId}`
});
return response.body as SendGridDesign;
}

async createDesign(params: {
name: string;
html_content: string;
plain_content?: string;
subject?: string;
editor?: string;
generate_plain_content?: boolean;
categories?: string[];
}): Promise<SendGridDesign> {
const [response] = await this.client.request({
method: 'POST',
url: '/v3/designs',
body: params
});
return response.body as SendGridDesign;
}

async updateDesign(designId: string, params: {
name?: string;
html_content?: string;
plain_content?: string;
subject?: string;
categories?: string[];
generate_plain_content?: boolean;
}): Promise<SendGridDesign> {
const [response] = await this.client.request({
method: 'PATCH',
url: `/v3/designs/${designId}`,
body: params
});
return response.body as SendGridDesign;
}

async deleteDesign(designId: string): Promise<void> {
await this.client.request({
method: 'DELETE',
url: `/v3/designs/${designId}`
});
}

async duplicateDesign(designId: string, params?: {
name?: string;
editor?: string;
}): Promise<SendGridDesign> {
const [response] = await this.client.request({
method: 'POST',
url: `/v3/designs/${designId}`,
body: params || {}
});
return response.body as SendGridDesign;
}

// Verified Senders
async getVerifiedSenders() {
const [response] = await this.client.request({
Expand Down
Loading