@memberjunction/communication-ms-graph 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -0
- package/package.json +9 -9
package/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# @memberjunction/communication-ms-graph
|
|
2
|
+
|
|
3
|
+
Microsoft Graph (Office 365 / Exchange Online) provider for the MemberJunction Communication Framework. This provider enables full mailbox operations -- sending, receiving, searching, managing folders, attachments, drafts, and more -- through the Microsoft Graph API with Azure AD application authentication.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TD
|
|
9
|
+
subgraph msgraph["@memberjunction/communication-ms-graph"]
|
|
10
|
+
MSP["MSGraphProvider"]
|
|
11
|
+
AUTH["Auth Module\n(ClientSecretCredential)"]
|
|
12
|
+
CFG["Config Module\n(Environment Variables)"]
|
|
13
|
+
CRED["MSGraphCredentials"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
subgraph azure["Azure / Microsoft"]
|
|
17
|
+
AAD["Azure AD\n(OAuth2 Client Credentials)"]
|
|
18
|
+
GRAPH["Microsoft Graph API\n(/users/email/...)"]
|
|
19
|
+
MAIL["Exchange Online\nMailbox"]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
subgraph base["@memberjunction/communication-types"]
|
|
23
|
+
BCP["BaseCommunicationProvider"]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
BCP --> MSP
|
|
27
|
+
MSP --> AUTH
|
|
28
|
+
MSP --> CFG
|
|
29
|
+
MSP --> CRED
|
|
30
|
+
AUTH --> AAD
|
|
31
|
+
MSP --> GRAPH
|
|
32
|
+
GRAPH --> MAIL
|
|
33
|
+
|
|
34
|
+
style msgraph fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
35
|
+
style azure fill:#7c5295,stroke:#563a6b,color:#fff
|
|
36
|
+
style base fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @memberjunction/communication-ms-graph
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
Set the following environment variables:
|
|
48
|
+
|
|
49
|
+
```env
|
|
50
|
+
AZURE_TENANT_ID=your-azure-tenant-id
|
|
51
|
+
AZURE_CLIENT_ID=your-azure-app-client-id
|
|
52
|
+
AZURE_CLIENT_SECRET=your-azure-app-client-secret
|
|
53
|
+
AZURE_ACCOUNT_EMAIL=mailbox@yourdomain.com
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Required Azure AD App Permissions (Application type)
|
|
57
|
+
|
|
58
|
+
| Permission | Operations |
|
|
59
|
+
|-----------|------------|
|
|
60
|
+
| `Mail.Send` | SendSingleMessage, ForwardMessage, ReplyToMessage |
|
|
61
|
+
| `Mail.Read` | GetMessages, GetSingleMessage, SearchMessages, ListFolders, ListAttachments, DownloadAttachment |
|
|
62
|
+
| `Mail.ReadWrite` | CreateDraft, DeleteMessage, MoveMessage, MarkAsRead, ArchiveMessage |
|
|
63
|
+
| `User.Read.All` | GetServiceAccount (user lookup, optional) |
|
|
64
|
+
|
|
65
|
+
## Supported Operations
|
|
66
|
+
|
|
67
|
+
This provider supports all 14 operations defined in `BaseCommunicationProvider`:
|
|
68
|
+
|
|
69
|
+
| Operation | Description |
|
|
70
|
+
|-----------|-------------|
|
|
71
|
+
| `SendSingleMessage` | Send email via Graph API |
|
|
72
|
+
| `GetMessages` | Retrieve messages with filtering and header extraction |
|
|
73
|
+
| `GetSingleMessage` | Retrieve a single message by ID |
|
|
74
|
+
| `ForwardMessage` | Forward email to new recipients |
|
|
75
|
+
| `ReplyToMessage` | Reply to an existing email thread |
|
|
76
|
+
| `CreateDraft` | Create a draft message in the mailbox |
|
|
77
|
+
| `DeleteMessage` | Move to Deleted Items or permanently delete |
|
|
78
|
+
| `MoveMessage` | Move message to a different mail folder |
|
|
79
|
+
| `ListFolders` | List mail folders with optional message counts |
|
|
80
|
+
| `MarkAsRead` | Mark messages as read or unread (batch) |
|
|
81
|
+
| `ArchiveMessage` | Move message to Archive folder |
|
|
82
|
+
| `SearchMessages` | Full-text search with KQL syntax and date filtering |
|
|
83
|
+
| `ListAttachments` | List attachments on a message |
|
|
84
|
+
| `DownloadAttachment` | Download attachment content as base64/Buffer |
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
### Sending Email
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
92
|
+
import { Message } from '@memberjunction/communication-types';
|
|
93
|
+
|
|
94
|
+
const engine = CommunicationEngine.Instance;
|
|
95
|
+
await engine.Config(false, contextUser);
|
|
96
|
+
|
|
97
|
+
const message = new Message();
|
|
98
|
+
message.From = 'user@yourdomain.com';
|
|
99
|
+
message.To = 'recipient@example.com';
|
|
100
|
+
message.Subject = 'Hello from MS Graph';
|
|
101
|
+
message.HTMLBody = '<h1>Hello</h1><p>Sent via Microsoft Graph.</p>';
|
|
102
|
+
message.ContextData = { saveToSentItems: true };
|
|
103
|
+
|
|
104
|
+
const result = await engine.SendSingleMessage(
|
|
105
|
+
'Microsoft Graph',
|
|
106
|
+
'Standard Email',
|
|
107
|
+
message
|
|
108
|
+
);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Per-Request Credentials
|
|
112
|
+
|
|
113
|
+
Override credentials on a per-request basis for multi-tenant scenarios:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { MSGraphCredentials } from '@memberjunction/communication-ms-graph';
|
|
117
|
+
|
|
118
|
+
const result = await engine.SendSingleMessage(
|
|
119
|
+
'Microsoft Graph',
|
|
120
|
+
'Standard Email',
|
|
121
|
+
message,
|
|
122
|
+
undefined,
|
|
123
|
+
false,
|
|
124
|
+
{
|
|
125
|
+
tenantId: 'customer-tenant-id',
|
|
126
|
+
clientId: 'customer-app-id',
|
|
127
|
+
clientSecret: 'customer-secret',
|
|
128
|
+
accountEmail: 'user@customer.com'
|
|
129
|
+
} as MSGraphCredentials
|
|
130
|
+
);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Reading Messages
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const provider = engine.GetProvider('Microsoft Graph');
|
|
137
|
+
|
|
138
|
+
const result = await provider.GetMessages({
|
|
139
|
+
NumMessages: 10,
|
|
140
|
+
UnreadOnly: true,
|
|
141
|
+
IncludeHeaders: true,
|
|
142
|
+
ContextData: {
|
|
143
|
+
ReturnAsPlainText: true,
|
|
144
|
+
MarkAsRead: true
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
result.Messages.forEach(msg => {
|
|
149
|
+
console.log(`${msg.From}: ${msg.Subject}`);
|
|
150
|
+
console.log(`Thread: ${msg.ThreadID}`);
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Searching Messages
|
|
155
|
+
|
|
156
|
+
MS Graph supports KQL (Keyword Query Language) for search:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const result = await provider.SearchMessages({
|
|
160
|
+
Query: 'invoice',
|
|
161
|
+
FromDate: new Date('2025-01-01'),
|
|
162
|
+
MaxResults: 25,
|
|
163
|
+
FolderID: 'inbox-folder-id'
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Creating Drafts
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const result = await engine.CreateDraft(message, 'Microsoft Graph', contextUser);
|
|
171
|
+
if (result.Success) {
|
|
172
|
+
console.log(`Draft ID: ${result.DraftID}`);
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Managing Folders
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// List top-level folders
|
|
180
|
+
const folders = await provider.ListFolders({ IncludeCounts: true });
|
|
181
|
+
folders.Folders.forEach(f => {
|
|
182
|
+
console.log(`${f.Name}: ${f.MessageCount} total, ${f.UnreadCount} unread`);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// List subfolders
|
|
186
|
+
const subfolders = await provider.ListFolders({
|
|
187
|
+
ParentFolderID: 'parent-folder-id',
|
|
188
|
+
IncludeCounts: true
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Move a message
|
|
192
|
+
await provider.MoveMessage({
|
|
193
|
+
MessageID: 'msg-id',
|
|
194
|
+
DestinationFolderID: 'folder-id'
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Archive a message
|
|
198
|
+
await provider.ArchiveMessage({ MessageID: 'msg-id' });
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Downloading Attachments
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
const attachments = await provider.ListAttachments({ MessageID: 'msg-id' });
|
|
205
|
+
for (const att of attachments.Attachments) {
|
|
206
|
+
const download = await provider.DownloadAttachment({
|
|
207
|
+
MessageID: 'msg-id',
|
|
208
|
+
AttachmentID: att.ID
|
|
209
|
+
});
|
|
210
|
+
// download.Content is a Buffer
|
|
211
|
+
// download.ContentBase64 is the raw base64 string
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Client Caching
|
|
216
|
+
|
|
217
|
+
The provider caches Microsoft Graph `Client` instances per credential set for performance. Environment credential clients are shared across all calls; per-request credential clients are cached by `tenantId:clientId`.
|
|
218
|
+
|
|
219
|
+
## System Folder Mapping
|
|
220
|
+
|
|
221
|
+
| Exchange Display Name | SystemFolderType |
|
|
222
|
+
|----------------------|-----------------|
|
|
223
|
+
| Inbox | `inbox` |
|
|
224
|
+
| Sent Items | `sent` |
|
|
225
|
+
| Drafts | `drafts` |
|
|
226
|
+
| Deleted Items | `trash` |
|
|
227
|
+
| Junk Email | `spam` |
|
|
228
|
+
| Archive | `archive` |
|
|
229
|
+
| Other folders | `other` |
|
|
230
|
+
|
|
231
|
+
## HTML to Text Conversion
|
|
232
|
+
|
|
233
|
+
When `ReturnAsPlainText` is set in `ContextData`, the provider uses the `html-to-text` library to convert HTML email bodies to plain text with 130-character word wrap.
|
|
234
|
+
|
|
235
|
+
## Dependencies
|
|
236
|
+
|
|
237
|
+
| Package | Purpose |
|
|
238
|
+
|---------|---------|
|
|
239
|
+
| `@memberjunction/communication-types` | Base provider class and type definitions |
|
|
240
|
+
| `@memberjunction/core` | Logging utilities |
|
|
241
|
+
| `@memberjunction/global` | RegisterClass decorator |
|
|
242
|
+
| `@microsoft/microsoft-graph-client` | Microsoft Graph SDK |
|
|
243
|
+
| `@azure/identity` | Azure AD ClientSecretCredential |
|
|
244
|
+
| `html-to-text` | HTML to plain text conversion |
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npm run build # Compile TypeScript
|
|
250
|
+
npm run clean # Remove dist directory
|
|
251
|
+
```
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/communication-ms-graph",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.2.0",
|
|
5
5
|
"description": "MemberJunction: Microsoft Graph Provider for the MJ Communication Framework",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@azure/identity": "^4.13.0",
|
|
25
25
|
"@azure/msal-node": "^5.0.3",
|
|
26
|
-
"@memberjunction/ai": "5.
|
|
27
|
-
"@memberjunction/ai-provider-bundle": "5.
|
|
28
|
-
"@memberjunction/aiengine": "5.
|
|
29
|
-
"@memberjunction/communication-types": "5.
|
|
30
|
-
"@memberjunction/core": "5.
|
|
31
|
-
"@memberjunction/core-entities": "5.
|
|
32
|
-
"@memberjunction/global": "5.
|
|
33
|
-
"@memberjunction/sqlserver-dataprovider": "5.
|
|
26
|
+
"@memberjunction/ai": "5.2.0",
|
|
27
|
+
"@memberjunction/ai-provider-bundle": "5.2.0",
|
|
28
|
+
"@memberjunction/aiengine": "5.2.0",
|
|
29
|
+
"@memberjunction/communication-types": "5.2.0",
|
|
30
|
+
"@memberjunction/core": "5.2.0",
|
|
31
|
+
"@memberjunction/core-entities": "5.2.0",
|
|
32
|
+
"@memberjunction/global": "5.2.0",
|
|
33
|
+
"@memberjunction/sqlserver-dataprovider": "5.2.0",
|
|
34
34
|
"@microsoft/microsoft-graph-client": "^3.0.7",
|
|
35
35
|
"@microsoft/microsoft-graph-types": "^2.43.1",
|
|
36
36
|
"@types/html-to-text": "^9.0.4",
|