@lowdefy/connection-sendgrid 0.0.0-experimental-20260720072521 → 0.0.0-experimental-20260720135014
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/dist/connections/SendGridMail/SendGridMail.js +2 -2
- package/dist/connections/SendGridMail/SendGridMailSend/SendGridMailSend.js +22 -12
- package/dist/connections/SendGridMail/schema.js +0 -53
- package/package.json +5 -5
- package/dist/connections/SendGridMail/applyMailFilter.js +0 -81
- package/dist/connections/SendGridMail/send.js +0 -59
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/ import
|
|
16
|
-
import
|
|
15
|
+
*/ import SendGridMailSend from './SendGridMailSend/SendGridMailSend.js';
|
|
16
|
+
import schema from './schema.js';
|
|
17
17
|
export default {
|
|
18
18
|
schema,
|
|
19
19
|
requests: {
|
|
@@ -12,24 +12,34 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/ import
|
|
16
|
-
import
|
|
15
|
+
*/ import sendgrid from '@sendgrid/mail';
|
|
16
|
+
import { type } from '@lowdefy/helpers';
|
|
17
17
|
import schema from './schema.js';
|
|
18
|
+
// https://sendgrid.api-docs.io/v3.0/how-to-use-the-sendgrid-v3-api/api-authentication
|
|
19
|
+
// https://github.com/sendgrid/sendgrid-nodejs/blob/master/docs/use-cases/README.md#email-use-cases
|
|
18
20
|
async function SendGridMailSend({ request, connection }) {
|
|
19
|
-
const
|
|
21
|
+
const { apiKey, from, templateId, mailSettings } = connection;
|
|
22
|
+
sendgrid.setApiKey(apiKey);
|
|
23
|
+
const messages = (type.isArray(request) ? request : [
|
|
20
24
|
request
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
connection,
|
|
27
|
-
mail
|
|
25
|
+
]).map((msg)=>({
|
|
26
|
+
...msg,
|
|
27
|
+
from,
|
|
28
|
+
templateId,
|
|
29
|
+
mailSettings
|
|
28
30
|
}));
|
|
31
|
+
try {
|
|
32
|
+
await sendgrid.send(messages);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (error.response) {
|
|
35
|
+
throw new Error('SendGrid request failed.', {
|
|
36
|
+
cause: error
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
throw error;
|
|
29
40
|
}
|
|
30
41
|
return {
|
|
31
|
-
response: 'Mail sent successfully'
|
|
32
|
-
results
|
|
42
|
+
response: 'Mail sent successfully'
|
|
33
43
|
};
|
|
34
44
|
}
|
|
35
45
|
SendGridMailSend.schema = schema;
|
|
@@ -100,10 +100,6 @@
|
|
|
100
100
|
type: 'SendGridMail connection property "apiKey" should be a string.'
|
|
101
101
|
}
|
|
102
102
|
},
|
|
103
|
-
replyTo: {
|
|
104
|
-
$ref: '#/definitions/emails',
|
|
105
|
-
description: 'Default email address to reply to.'
|
|
106
|
-
},
|
|
107
103
|
templateId: {
|
|
108
104
|
type: 'string',
|
|
109
105
|
description: 'SendGrid email template ID to render email when sending.',
|
|
@@ -111,55 +107,6 @@
|
|
|
111
107
|
type: 'SendGridMail connection property "templateId" should be a string.'
|
|
112
108
|
}
|
|
113
109
|
},
|
|
114
|
-
filter: {
|
|
115
|
-
type: [
|
|
116
|
-
'object',
|
|
117
|
-
'null'
|
|
118
|
-
],
|
|
119
|
-
description: 'Filter to restrict or redirect the recipients of outgoing mail.',
|
|
120
|
-
additionalProperties: false,
|
|
121
|
-
properties: {
|
|
122
|
-
replaceAddress: {
|
|
123
|
-
type: [
|
|
124
|
-
'string',
|
|
125
|
-
'null'
|
|
126
|
-
],
|
|
127
|
-
description: 'Replace all "to" recipients with this address and drop cc and bcc.',
|
|
128
|
-
errorMessage: {
|
|
129
|
-
type: 'SendGridMail connection property "filter.replaceAddress" should be a string.'
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
allowlist: {
|
|
133
|
-
type: [
|
|
134
|
-
'array',
|
|
135
|
-
'null'
|
|
136
|
-
],
|
|
137
|
-
description: 'List of domains allowed to receive mail.',
|
|
138
|
-
items: {
|
|
139
|
-
type: 'string',
|
|
140
|
-
errorMessage: {
|
|
141
|
-
type: 'SendGridMail connection property "filter.allowlist" should be a list of domain strings.'
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
errorMessage: {
|
|
145
|
-
type: 'SendGridMail connection property "filter.allowlist" should be an array.'
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
regex: {
|
|
149
|
-
type: [
|
|
150
|
-
'string',
|
|
151
|
-
'null'
|
|
152
|
-
],
|
|
153
|
-
description: 'Regular expression an email address must match to receive mail.',
|
|
154
|
-
errorMessage: {
|
|
155
|
-
type: 'SendGridMail connection property "filter.regex" should be a string.'
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
errorMessage: {
|
|
160
|
-
type: 'SendGridMail connection property "filter" should be an object.'
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
110
|
mailSettings: {
|
|
164
111
|
type: 'object',
|
|
165
112
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/connection-sendgrid",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-20260720135014",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"dist/*"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@lowdefy/helpers": "0.0.0-experimental-
|
|
38
|
+
"@lowdefy/helpers": "0.0.0-experimental-20260720135014",
|
|
39
39
|
"@sendgrid/mail": "7.7.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@jest/globals": "28.1.3",
|
|
43
|
-
"@lowdefy/ajv": "0.0.0-experimental-
|
|
44
|
-
"@swc/cli": "0.8.
|
|
45
|
-
"@swc/core": "1.15.
|
|
43
|
+
"@lowdefy/ajv": "0.0.0-experimental-20260720135014",
|
|
44
|
+
"@swc/cli": "0.8.0",
|
|
45
|
+
"@swc/core": "1.15.18",
|
|
46
46
|
"@swc/jest": "0.2.39",
|
|
47
47
|
"jest": "28.1.3"
|
|
48
48
|
},
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { type } from '@lowdefy/helpers';
|
|
16
|
-
function applyMailFilter({ filter, mail }) {
|
|
17
|
-
if (type.isNone(filter)) {
|
|
18
|
-
return mail;
|
|
19
|
-
}
|
|
20
|
-
const { replaceAddress, allowlist, regex } = filter;
|
|
21
|
-
if (type.isNone(replaceAddress) && type.isNone(allowlist) && type.isNone(regex)) {
|
|
22
|
-
return mail;
|
|
23
|
-
}
|
|
24
|
-
if (!type.isNone(replaceAddress)) {
|
|
25
|
-
return {
|
|
26
|
-
...mail,
|
|
27
|
-
to: replaceAddress,
|
|
28
|
-
cc: undefined,
|
|
29
|
-
bcc: undefined
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const allowedDomains = type.isNone(allowlist) ? null : allowlist.map((domain)=>domain.toLowerCase());
|
|
33
|
-
const addressRegex = type.isNone(regex) ? null : new RegExp(regex);
|
|
34
|
-
function getBareAddress(recipient) {
|
|
35
|
-
if (type.isObject(recipient)) {
|
|
36
|
-
return recipient.email.toLowerCase();
|
|
37
|
-
}
|
|
38
|
-
const match = recipient.match(/<([^>]+)>/);
|
|
39
|
-
if (match) {
|
|
40
|
-
return match[1].toLowerCase();
|
|
41
|
-
}
|
|
42
|
-
return recipient.toLowerCase();
|
|
43
|
-
}
|
|
44
|
-
function isAllowed(recipient) {
|
|
45
|
-
const address = getBareAddress(recipient);
|
|
46
|
-
if (allowedDomains !== null) {
|
|
47
|
-
const domain = address.slice(address.lastIndexOf('@') + 1);
|
|
48
|
-
if (!allowedDomains.includes(domain)) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (addressRegex !== null && !addressRegex.test(address)) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
function filterRecipients(recipients) {
|
|
58
|
-
if (type.isNone(recipients)) {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
|
-
if (!type.isArray(recipients)) {
|
|
62
|
-
return isAllowed(recipients) ? recipients : undefined;
|
|
63
|
-
}
|
|
64
|
-
const allowed = recipients.filter(isAllowed);
|
|
65
|
-
if (allowed.length === 0) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
return allowed;
|
|
69
|
-
}
|
|
70
|
-
const to = filterRecipients(mail.to);
|
|
71
|
-
if (type.isUndefined(to)) {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
return {
|
|
75
|
-
...mail,
|
|
76
|
-
to,
|
|
77
|
-
cc: filterRecipients(mail.cc),
|
|
78
|
-
bcc: filterRecipients(mail.bcc)
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
export default applyMailFilter;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import sendgrid from '@sendgrid/mail';
|
|
16
|
-
import applyMailFilter from './applyMailFilter.js';
|
|
17
|
-
// https://sendgrid.api-docs.io/v3.0/how-to-use-the-sendgrid-v3-api/api-authentication
|
|
18
|
-
// https://github.com/sendgrid/sendgrid-nodejs/blob/master/docs/use-cases/README.md#email-use-cases
|
|
19
|
-
async function send({ connection, mail }) {
|
|
20
|
-
const { apiKey, from, replyTo, templateId, mailSettings, filter } = connection;
|
|
21
|
-
sendgrid.setApiKey(apiKey);
|
|
22
|
-
const filtered = applyMailFilter({
|
|
23
|
-
filter,
|
|
24
|
-
mail
|
|
25
|
-
});
|
|
26
|
-
if (filtered === null) {
|
|
27
|
-
return {
|
|
28
|
-
messageId: null,
|
|
29
|
-
to: null,
|
|
30
|
-
filtered: true
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
const message = {
|
|
34
|
-
...filtered,
|
|
35
|
-
from,
|
|
36
|
-
replyTo: filtered.replyTo ?? replyTo,
|
|
37
|
-
// Fall back to the mail templateId so an undefined connection templateId
|
|
38
|
-
// does not clobber a template set on the mail itself.
|
|
39
|
-
templateId: templateId ?? filtered.templateId,
|
|
40
|
-
mailSettings
|
|
41
|
-
};
|
|
42
|
-
try {
|
|
43
|
-
const [response] = await sendgrid.send(message);
|
|
44
|
-
// Return the post-filter to so callers can record where mail actually went
|
|
45
|
-
// when a connection filter (replaceAddress/allowlist/regex) rewrites it.
|
|
46
|
-
return {
|
|
47
|
-
messageId: response?.headers?.['x-message-id'] ?? null,
|
|
48
|
-
to: filtered.to
|
|
49
|
-
};
|
|
50
|
-
} catch (error) {
|
|
51
|
-
if (error.response) {
|
|
52
|
-
throw new Error('SendGrid request failed.', {
|
|
53
|
-
cause: error
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
export default send;
|