strapi-plugin-magic-mail 2.3.10 → 2.4.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/dist/_chunks/{App-BMaJu77a.js → App-58t1-H0G.js} +895 -534
- package/dist/_chunks/{App-DxiMl-Zd.mjs → App-ClJVoU2s.mjs} +896 -535
- package/dist/_chunks/PluginSettings-D2BUUHY1.js +376 -0
- package/dist/_chunks/PluginSettings-ywPWZVt0.mjs +374 -0
- package/dist/_chunks/{Settings-BSFLpt0H.js → Settings-CPPrGxLm.js} +38 -82
- package/dist/_chunks/{Settings-Ca5UE3c1.mjs → Settings-Cc-hhoLA.mjs} +39 -83
- package/dist/_chunks/StyledButtons-M7vUd2N4.js +435 -0
- package/dist/_chunks/StyledButtons-nt2C730e.mjs +434 -0
- package/dist/_chunks/{de-YhjDItIL.js → de-CF2ItE3Z.js} +1 -1
- package/dist/_chunks/{de-CpIQf94q.mjs → de-CwbYw2jT.mjs} +1 -1
- package/dist/_chunks/{en-BcdTnA2-.js → en-CK6UpShS.js} +1 -1
- package/dist/_chunks/{en-BHmOVzsP.mjs → en-ZRmfU4qX.mjs} +1 -1
- package/dist/admin/index.js +16 -7
- package/dist/admin/index.mjs +16 -7
- package/dist/server/index.js +298 -54
- package/dist/server/index.mjs +298 -54
- package/package.json +8 -8
package/dist/server/index.mjs
CHANGED
|
@@ -240,13 +240,27 @@ function requireConfig() {
|
|
|
240
240
|
};
|
|
241
241
|
return config;
|
|
242
242
|
}
|
|
243
|
+
const kind$7 = "collectionType";
|
|
244
|
+
const collectionName$7 = "magic_mail_accounts";
|
|
245
|
+
const info$7 = { "singularName": "email-account", "pluralName": "email-accounts", "displayName": "Email Account", "description": "Email provider accounts for multi-account email sending" };
|
|
246
|
+
const options$7 = { "draftAndPublish": false };
|
|
247
|
+
const pluginOptions$7 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
248
|
+
const attributes$7 = { "name": { "type": "string", "required": true, "unique": true }, "description": { "type": "text" }, "provider": { "type": "enumeration", "enum": ["smtp", "gmail-oauth", "microsoft-oauth", "yahoo-oauth", "sendgrid", "mailgun", "ses", "nodemailer"], "required": true, "default": "smtp" }, "config": { "type": "json", "required": true }, "oauth": { "type": "json" }, "fromEmail": { "type": "email", "required": true }, "fromName": { "type": "string" }, "replyTo": { "type": "email" }, "isActive": { "type": "boolean", "default": true, "required": true }, "isPrimary": { "type": "boolean", "default": false }, "priority": { "type": "integer", "default": 1, "min": 1, "max": 10 }, "dailyLimit": { "type": "integer", "default": 0 }, "hourlyLimit": { "type": "integer", "default": 0 }, "emailsSentToday": { "type": "integer", "default": 0 }, "emailsSentThisHour": { "type": "integer", "default": 0 }, "totalEmailsSent": { "type": "integer", "default": 0 }, "lastUsed": { "type": "datetime" } };
|
|
249
|
+
const require$$0 = {
|
|
250
|
+
kind: kind$7,
|
|
251
|
+
collectionName: collectionName$7,
|
|
252
|
+
info: info$7,
|
|
253
|
+
options: options$7,
|
|
254
|
+
pluginOptions: pluginOptions$7,
|
|
255
|
+
attributes: attributes$7
|
|
256
|
+
};
|
|
243
257
|
const kind$6 = "collectionType";
|
|
244
|
-
const collectionName$6 = "
|
|
245
|
-
const info$6 = { "singularName": "
|
|
258
|
+
const collectionName$6 = "magic_mail_routing_rules";
|
|
259
|
+
const info$6 = { "singularName": "routing-rule", "pluralName": "routing-rules", "displayName": "Email Routing Rule", "description": "Rules for routing emails to specific accounts" };
|
|
246
260
|
const options$6 = { "draftAndPublish": false };
|
|
247
261
|
const pluginOptions$6 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
248
|
-
const attributes$6 = { "name": { "type": "string", "required": true, "unique": true }, "description": { "type": "text" }, "
|
|
249
|
-
const require$$
|
|
262
|
+
const attributes$6 = { "name": { "type": "string", "required": true, "unique": true }, "description": { "type": "text" }, "isActive": { "type": "boolean", "default": true, "required": true }, "priority": { "type": "integer", "default": 1, "min": 1 }, "matchType": { "type": "enumeration", "enum": ["emailType", "subject", "recipient", "template", "custom"], "required": true, "default": "emailType" }, "matchValue": { "type": "text", "required": true }, "accountName": { "type": "string", "required": true }, "fallbackAccountName": { "type": "string" }, "whatsappFallback": { "type": "boolean", "default": false }, "whatsappPhoneField": { "type": "string" } };
|
|
263
|
+
const require$$1 = {
|
|
250
264
|
kind: kind$6,
|
|
251
265
|
collectionName: collectionName$6,
|
|
252
266
|
info: info$6,
|
|
@@ -255,12 +269,12 @@ const require$$0 = {
|
|
|
255
269
|
attributes: attributes$6
|
|
256
270
|
};
|
|
257
271
|
const kind$5 = "collectionType";
|
|
258
|
-
const collectionName$5 = "
|
|
259
|
-
const info$5 = { "singularName": "
|
|
272
|
+
const collectionName$5 = "magic_mail_email_logs";
|
|
273
|
+
const info$5 = { "singularName": "email-log", "pluralName": "email-logs", "displayName": "Email Log", "description": "Tracks all sent emails with user association" };
|
|
260
274
|
const options$5 = { "draftAndPublish": false };
|
|
261
275
|
const pluginOptions$5 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
262
|
-
const attributes$5 = { "
|
|
263
|
-
const require$$1 = {
|
|
276
|
+
const attributes$5 = { "emailId": { "type": "string", "required": true, "unique": true }, "user": { "type": "relation", "relation": "manyToOne", "target": "plugin::users-permissions.user" }, "recipient": { "type": "email", "required": true }, "recipientName": { "type": "string" }, "subject": { "type": "string", "required": true }, "templateId": { "type": "integer" }, "templateName": { "type": "string" }, "accountId": { "type": "integer" }, "accountName": { "type": "string" }, "sentAt": { "type": "datetime", "required": true }, "deliveredAt": { "type": "datetime" }, "firstOpenedAt": { "type": "datetime" }, "lastOpenedAt": { "type": "datetime" }, "openCount": { "type": "integer", "default": 0 }, "clickCount": { "type": "integer", "default": 0 }, "bounced": { "type": "boolean", "default": false }, "bounceReason": { "type": "text" }, "unsubscribed": { "type": "boolean", "default": false }, "unsubscribedAt": { "type": "datetime" }, "metadata": { "type": "json" }, "events": { "type": "relation", "relation": "oneToMany", "target": "plugin::magic-mail.email-event", "mappedBy": "emailLog" }, "links": { "type": "relation", "relation": "oneToMany", "target": "plugin::magic-mail.email-link", "mappedBy": "emailLog" } };
|
|
277
|
+
const require$$2$1 = {
|
|
264
278
|
kind: kind$5,
|
|
265
279
|
collectionName: collectionName$5,
|
|
266
280
|
info: info$5,
|
|
@@ -269,12 +283,12 @@ const require$$1 = {
|
|
|
269
283
|
attributes: attributes$5
|
|
270
284
|
};
|
|
271
285
|
const kind$4 = "collectionType";
|
|
272
|
-
const collectionName$4 = "
|
|
273
|
-
const info$4 = { "singularName": "email-
|
|
286
|
+
const collectionName$4 = "magic_mail_email_events";
|
|
287
|
+
const info$4 = { "singularName": "email-event", "pluralName": "email-events", "displayName": "Email Event", "description": "Individual email tracking events (opens, clicks, bounces)" };
|
|
274
288
|
const options$4 = { "draftAndPublish": false };
|
|
275
289
|
const pluginOptions$4 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
276
|
-
const attributes$4 = { "
|
|
277
|
-
const require$$
|
|
290
|
+
const attributes$4 = { "emailLog": { "type": "relation", "relation": "manyToOne", "target": "plugin::magic-mail.email-log", "inversedBy": "events" }, "type": { "type": "enumeration", "enum": ["open", "click", "bounce", "complaint", "unsubscribe"], "required": true }, "timestamp": { "type": "datetime", "required": true }, "ipAddress": { "type": "string" }, "userAgent": { "type": "text" }, "location": { "type": "json" }, "linkUrl": { "type": "text" }, "linkText": { "type": "string" }, "metadata": { "type": "json" } };
|
|
291
|
+
const require$$3 = {
|
|
278
292
|
kind: kind$4,
|
|
279
293
|
collectionName: collectionName$4,
|
|
280
294
|
info: info$4,
|
|
@@ -283,12 +297,12 @@ const require$$2$1 = {
|
|
|
283
297
|
attributes: attributes$4
|
|
284
298
|
};
|
|
285
299
|
const kind$3 = "collectionType";
|
|
286
|
-
const collectionName$3 = "
|
|
287
|
-
const info$3 = { "singularName": "email-
|
|
300
|
+
const collectionName$3 = "magic_mail_email_links";
|
|
301
|
+
const info$3 = { "singularName": "email-link", "pluralName": "email-links", "displayName": "Email Link", "description": "Stores click tracking links for emails" };
|
|
288
302
|
const options$3 = { "draftAndPublish": false };
|
|
289
303
|
const pluginOptions$3 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
290
|
-
const attributes$3 = { "emailLog": { "type": "relation", "relation": "manyToOne", "target": "plugin::magic-mail.email-log", "inversedBy": "
|
|
291
|
-
const require$$
|
|
304
|
+
const attributes$3 = { "emailLog": { "type": "relation", "relation": "manyToOne", "target": "plugin::magic-mail.email-log", "inversedBy": "links" }, "linkHash": { "type": "string", "required": true, "unique": false }, "originalUrl": { "type": "text", "required": true }, "clickCount": { "type": "integer", "default": 0 }, "firstClickedAt": { "type": "datetime" }, "lastClickedAt": { "type": "datetime" } };
|
|
305
|
+
const require$$4 = {
|
|
292
306
|
kind: kind$3,
|
|
293
307
|
collectionName: collectionName$3,
|
|
294
308
|
info: info$3,
|
|
@@ -297,12 +311,12 @@ const require$$3 = {
|
|
|
297
311
|
attributes: attributes$3
|
|
298
312
|
};
|
|
299
313
|
const kind$2 = "collectionType";
|
|
300
|
-
const collectionName$2 = "
|
|
301
|
-
const info$2 = { "singularName": "email-
|
|
302
|
-
const options$2 = { "draftAndPublish": false };
|
|
314
|
+
const collectionName$2 = "magic_mail_email_templates";
|
|
315
|
+
const info$2 = { "singularName": "email-template", "pluralName": "email-templates", "displayName": "Email Template", "description": "Email templates created with the visual designer" };
|
|
316
|
+
const options$2 = { "draftAndPublish": false, "timestamps": true };
|
|
303
317
|
const pluginOptions$2 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
304
|
-
const attributes$2 = { "
|
|
305
|
-
const require$$
|
|
318
|
+
const attributes$2 = { "templateReferenceId": { "type": "integer", "required": true, "unique": true, "configurable": false }, "name": { "type": "string", "required": true, "configurable": false }, "subject": { "type": "string", "required": true, "configurable": false }, "design": { "type": "json", "configurable": false }, "bodyHtml": { "type": "text", "configurable": false }, "bodyText": { "type": "text", "configurable": false }, "category": { "type": "enumeration", "enum": ["transactional", "marketing", "notification", "custom"], "default": "custom", "configurable": false }, "isActive": { "type": "boolean", "default": true, "configurable": false }, "tags": { "type": "json", "configurable": false }, "versions": { "type": "relation", "relation": "oneToMany", "target": "plugin::magic-mail.email-template-version", "mappedBy": "template" } };
|
|
319
|
+
const require$$5 = {
|
|
306
320
|
kind: kind$2,
|
|
307
321
|
collectionName: collectionName$2,
|
|
308
322
|
info: info$2,
|
|
@@ -311,12 +325,12 @@ const require$$4 = {
|
|
|
311
325
|
attributes: attributes$2
|
|
312
326
|
};
|
|
313
327
|
const kind$1 = "collectionType";
|
|
314
|
-
const collectionName$1 = "
|
|
315
|
-
const info$1 = { "singularName": "email-template", "pluralName": "email-
|
|
328
|
+
const collectionName$1 = "magic_mail_email_template_versions";
|
|
329
|
+
const info$1 = { "singularName": "email-template-version", "pluralName": "email-template-versions", "displayName": "Email Template Version", "description": "Version history for email templates" };
|
|
316
330
|
const options$1 = { "draftAndPublish": false, "timestamps": true };
|
|
317
331
|
const pluginOptions$1 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
318
|
-
const attributes$1 = { "
|
|
319
|
-
const require$$
|
|
332
|
+
const attributes$1 = { "template": { "type": "relation", "relation": "manyToOne", "target": "plugin::magic-mail.email-template", "inversedBy": "versions" }, "versionNumber": { "type": "integer", "required": true, "configurable": false }, "name": { "type": "string", "configurable": false }, "subject": { "type": "string", "configurable": false }, "design": { "type": "json", "configurable": false }, "bodyHtml": { "type": "text", "configurable": false }, "bodyText": { "type": "text", "configurable": false }, "tags": { "type": "json", "configurable": false } };
|
|
333
|
+
const require$$6 = {
|
|
320
334
|
kind: kind$1,
|
|
321
335
|
collectionName: collectionName$1,
|
|
322
336
|
info: info$1,
|
|
@@ -324,13 +338,13 @@ const require$$5 = {
|
|
|
324
338
|
pluginOptions: pluginOptions$1,
|
|
325
339
|
attributes: attributes$1
|
|
326
340
|
};
|
|
327
|
-
const kind = "
|
|
328
|
-
const collectionName = "
|
|
329
|
-
const info = { "singularName": "
|
|
330
|
-
const options = { "draftAndPublish": false, "
|
|
341
|
+
const kind = "singleType";
|
|
342
|
+
const collectionName = "magic_mail_settings";
|
|
343
|
+
const info = { "singularName": "plugin-settings", "pluralName": "plugin-settings", "displayName": "MagicMail Settings" };
|
|
344
|
+
const options = { "draftAndPublish": false, "comment": "Global settings for MagicMail plugin" };
|
|
331
345
|
const pluginOptions = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
332
|
-
const attributes = { "
|
|
333
|
-
const require$$
|
|
346
|
+
const attributes = { "enableLinkTracking": { "type": "boolean", "default": true, "configurable": false }, "enableOpenTracking": { "type": "boolean", "default": true, "configurable": false }, "trackingBaseUrl": { "type": "string", "configurable": false }, "defaultFromName": { "type": "string", "configurable": false }, "defaultFromEmail": { "type": "string", "configurable": false }, "unsubscribeUrl": { "type": "string", "configurable": false }, "enableUnsubscribeHeader": { "type": "boolean", "default": true, "configurable": false } };
|
|
347
|
+
const require$$7 = {
|
|
334
348
|
kind,
|
|
335
349
|
collectionName,
|
|
336
350
|
info,
|
|
@@ -350,6 +364,7 @@ function requireContentTypes() {
|
|
|
350
364
|
const emailLink = require$$4;
|
|
351
365
|
const emailTemplate = require$$5;
|
|
352
366
|
const emailTemplateVersion = require$$6;
|
|
367
|
+
const pluginSettings2 = require$$7;
|
|
353
368
|
contentTypes = {
|
|
354
369
|
"email-account": {
|
|
355
370
|
schema: emailAccount
|
|
@@ -371,6 +386,9 @@ function requireContentTypes() {
|
|
|
371
386
|
},
|
|
372
387
|
"email-template-version": {
|
|
373
388
|
schema: emailTemplateVersion
|
|
389
|
+
},
|
|
390
|
+
"plugin-settings": {
|
|
391
|
+
schema: pluginSettings2
|
|
374
392
|
}
|
|
375
393
|
};
|
|
376
394
|
return contentTypes;
|
|
@@ -2545,7 +2563,7 @@ function requireWhatsapp$1() {
|
|
|
2545
2563
|
success: true,
|
|
2546
2564
|
data: {
|
|
2547
2565
|
available,
|
|
2548
|
-
message: available ? "WhatsApp integration is available" : "Baileys not installed. Run: npm install
|
|
2566
|
+
message: available ? "WhatsApp integration is available" : "Baileys not installed. Run: npm install baileys pino qrcode"
|
|
2549
2567
|
}
|
|
2550
2568
|
};
|
|
2551
2569
|
} catch (error) {
|
|
@@ -2740,6 +2758,62 @@ function requireWhatsapp$1() {
|
|
|
2740
2758
|
};
|
|
2741
2759
|
return whatsapp$1;
|
|
2742
2760
|
}
|
|
2761
|
+
var pluginSettings$1;
|
|
2762
|
+
var hasRequiredPluginSettings$1;
|
|
2763
|
+
function requirePluginSettings$1() {
|
|
2764
|
+
if (hasRequiredPluginSettings$1) return pluginSettings$1;
|
|
2765
|
+
hasRequiredPluginSettings$1 = 1;
|
|
2766
|
+
pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
2767
|
+
/**
|
|
2768
|
+
* GET /magic-mail/settings
|
|
2769
|
+
* Get current plugin settings
|
|
2770
|
+
*/
|
|
2771
|
+
async getSettings(ctx) {
|
|
2772
|
+
try {
|
|
2773
|
+
const settings = await strapi2.plugin("magic-mail").service("plugin-settings").getSettings();
|
|
2774
|
+
ctx.body = {
|
|
2775
|
+
data: settings
|
|
2776
|
+
};
|
|
2777
|
+
} catch (error) {
|
|
2778
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error getting settings:", error);
|
|
2779
|
+
ctx.throw(500, "Failed to get settings");
|
|
2780
|
+
}
|
|
2781
|
+
},
|
|
2782
|
+
/**
|
|
2783
|
+
* PUT /magic-mail/settings
|
|
2784
|
+
* Update plugin settings
|
|
2785
|
+
*/
|
|
2786
|
+
async updateSettings(ctx) {
|
|
2787
|
+
try {
|
|
2788
|
+
const { body } = ctx.request;
|
|
2789
|
+
const allowedFields = [
|
|
2790
|
+
"enableLinkTracking",
|
|
2791
|
+
"enableOpenTracking",
|
|
2792
|
+
"trackingBaseUrl",
|
|
2793
|
+
"defaultFromName",
|
|
2794
|
+
"defaultFromEmail",
|
|
2795
|
+
"unsubscribeUrl",
|
|
2796
|
+
"enableUnsubscribeHeader"
|
|
2797
|
+
];
|
|
2798
|
+
const data = {};
|
|
2799
|
+
for (const field of allowedFields) {
|
|
2800
|
+
if (body[field] !== void 0) {
|
|
2801
|
+
data[field] = body[field];
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
const settings = await strapi2.plugin("magic-mail").service("plugin-settings").updateSettings(data);
|
|
2805
|
+
ctx.body = {
|
|
2806
|
+
data: settings,
|
|
2807
|
+
message: "Settings updated successfully"
|
|
2808
|
+
};
|
|
2809
|
+
} catch (error) {
|
|
2810
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error updating settings:", error);
|
|
2811
|
+
ctx.throw(500, "Failed to update settings");
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
});
|
|
2815
|
+
return pluginSettings$1;
|
|
2816
|
+
}
|
|
2743
2817
|
var controllers;
|
|
2744
2818
|
var hasRequiredControllers;
|
|
2745
2819
|
function requireControllers() {
|
|
@@ -2754,6 +2828,7 @@ function requireControllers() {
|
|
|
2754
2828
|
const analytics2 = requireAnalytics$1();
|
|
2755
2829
|
const test2 = requireTest();
|
|
2756
2830
|
const whatsapp2 = requireWhatsapp$1();
|
|
2831
|
+
const pluginSettings2 = requirePluginSettings$1();
|
|
2757
2832
|
controllers = {
|
|
2758
2833
|
controller: controller2,
|
|
2759
2834
|
accounts: accounts2,
|
|
@@ -2763,7 +2838,8 @@ function requireControllers() {
|
|
|
2763
2838
|
emailDesigner: emailDesigner2,
|
|
2764
2839
|
analytics: analytics2,
|
|
2765
2840
|
test: test2,
|
|
2766
|
-
whatsapp: whatsapp2
|
|
2841
|
+
whatsapp: whatsapp2,
|
|
2842
|
+
pluginSettings: pluginSettings2
|
|
2767
2843
|
};
|
|
2768
2844
|
return controllers;
|
|
2769
2845
|
}
|
|
@@ -3338,6 +3414,25 @@ function requireAdmin() {
|
|
|
3338
3414
|
policies: ["admin::isAuthenticatedAdmin"],
|
|
3339
3415
|
description: "Get WhatsApp session info"
|
|
3340
3416
|
}
|
|
3417
|
+
},
|
|
3418
|
+
// Plugin Settings Routes
|
|
3419
|
+
{
|
|
3420
|
+
method: "GET",
|
|
3421
|
+
path: "/settings",
|
|
3422
|
+
handler: "pluginSettings.getSettings",
|
|
3423
|
+
config: {
|
|
3424
|
+
policies: ["admin::isAuthenticatedAdmin"],
|
|
3425
|
+
description: "Get plugin settings"
|
|
3426
|
+
}
|
|
3427
|
+
},
|
|
3428
|
+
{
|
|
3429
|
+
method: "PUT",
|
|
3430
|
+
path: "/settings",
|
|
3431
|
+
handler: "pluginSettings.updateSettings",
|
|
3432
|
+
config: {
|
|
3433
|
+
policies: ["admin::isAuthenticatedAdmin"],
|
|
3434
|
+
description: "Update plugin settings"
|
|
3435
|
+
}
|
|
3341
3436
|
}
|
|
3342
3437
|
]
|
|
3343
3438
|
};
|
|
@@ -3614,6 +3709,10 @@ function requireEmailRouter() {
|
|
|
3614
3709
|
if (enableTracking && html) {
|
|
3615
3710
|
try {
|
|
3616
3711
|
const analyticsService = strapi2.plugin("magic-mail").service("analytics");
|
|
3712
|
+
const settingsService = strapi2.plugin("magic-mail").service("plugin-settings");
|
|
3713
|
+
const pluginSettings2 = await settingsService.getSettings();
|
|
3714
|
+
const globalLinkTrackingEnabled = pluginSettings2.enableLinkTracking !== false;
|
|
3715
|
+
const globalOpenTrackingEnabled = pluginSettings2.enableOpenTracking !== false;
|
|
3617
3716
|
emailLog = await analyticsService.createEmailLog({
|
|
3618
3717
|
to,
|
|
3619
3718
|
userId: emailData.userId || null,
|
|
@@ -3632,12 +3731,19 @@ function requireEmailRouter() {
|
|
|
3632
3731
|
}
|
|
3633
3732
|
});
|
|
3634
3733
|
recipientHash = analyticsService.generateRecipientHash(emailLog.emailId, to);
|
|
3635
|
-
|
|
3636
|
-
|
|
3734
|
+
if (globalOpenTrackingEnabled) {
|
|
3735
|
+
html = analyticsService.injectTrackingPixel(html, emailLog.emailId, recipientHash);
|
|
3736
|
+
} else {
|
|
3737
|
+
strapi2.log.info(`[magic-mail] [STATS] Open tracking DISABLED globally`);
|
|
3738
|
+
}
|
|
3739
|
+
const shouldTrackLinks = globalLinkTrackingEnabled && !skipLinkTracking;
|
|
3740
|
+
if (shouldTrackLinks) {
|
|
3637
3741
|
html = await analyticsService.rewriteLinksForTracking(html, emailLog.emailId, recipientHash);
|
|
3638
|
-
strapi2.log.info(`[magic-mail] [STATS]
|
|
3742
|
+
strapi2.log.info(`[magic-mail] [STATS] Link tracking enabled for email: ${emailLog.emailId}`);
|
|
3743
|
+
} else if (!globalLinkTrackingEnabled) {
|
|
3744
|
+
strapi2.log.info(`[magic-mail] [STATS] Link tracking DISABLED globally for email: ${emailLog.emailId}`);
|
|
3639
3745
|
} else {
|
|
3640
|
-
strapi2.log.info(`[magic-mail] [STATS]
|
|
3746
|
+
strapi2.log.info(`[magic-mail] [STATS] Link tracking DISABLED per-email (skipLinkTracking=true) for email: ${emailLog.emailId}`);
|
|
3641
3747
|
}
|
|
3642
3748
|
} catch (error) {
|
|
3643
3749
|
strapi2.log.error(`[magic-mail] [WARNING] Tracking setup failed (continuing without tracking):`, error.message);
|
|
@@ -3711,7 +3817,7 @@ function requireEmailRouter() {
|
|
|
3711
3817
|
await strapi2.documents("plugin::magic-mail.email-log").update({
|
|
3712
3818
|
documentId: emailLog.documentId,
|
|
3713
3819
|
data: {
|
|
3714
|
-
accountId: account.
|
|
3820
|
+
accountId: account.documentId,
|
|
3715
3821
|
accountName: account.name,
|
|
3716
3822
|
deliveredAt: /* @__PURE__ */ new Date()
|
|
3717
3823
|
}
|
|
@@ -5533,7 +5639,7 @@ function requireOauth() {
|
|
|
5533
5639
|
});
|
|
5534
5640
|
return oauth;
|
|
5535
5641
|
}
|
|
5536
|
-
const version = "2.
|
|
5642
|
+
const version = "2.4.0";
|
|
5537
5643
|
const require$$2 = {
|
|
5538
5644
|
version
|
|
5539
5645
|
};
|
|
@@ -6817,7 +6923,10 @@ function requireAnalytics() {
|
|
|
6817
6923
|
* Rewrite links for click tracking
|
|
6818
6924
|
*/
|
|
6819
6925
|
async rewriteLinksForTracking(html, emailId, recipientHash) {
|
|
6820
|
-
const
|
|
6926
|
+
const settingsService = strapi2.plugin("magic-mail").service("plugin-settings");
|
|
6927
|
+
const pluginSettings2 = await settingsService.getSettings();
|
|
6928
|
+
const baseUrl = pluginSettings2.trackingBaseUrl || strapi2.config.get("server.url") || "http://localhost:1337";
|
|
6929
|
+
strapi2.log.debug(`[magic-mail] [LINK-TRACK] Using base URL: ${baseUrl}`);
|
|
6821
6930
|
const emailLog = await strapi2.documents(EMAIL_LOG_UID).findFirst({
|
|
6822
6931
|
filters: { emailId }
|
|
6823
6932
|
});
|
|
@@ -6825,23 +6934,27 @@ function requireAnalytics() {
|
|
|
6825
6934
|
strapi2.log.error(`[magic-mail] Cannot rewrite links: Email log not found for ${emailId}`);
|
|
6826
6935
|
return html;
|
|
6827
6936
|
}
|
|
6828
|
-
|
|
6937
|
+
let processedHtml = html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"');
|
|
6938
|
+
const linkRegex = /<a\s+(?:[^>]*?\s+)?href\s*=\s*["']([^"']+)["'][^>]*>/gis;
|
|
6939
|
+
const simpleLinkRegex = /href\s*=\s*["'](https?:\/\/[^"']+)["']/gi;
|
|
6829
6940
|
const linkMappings = [];
|
|
6830
6941
|
const replacements = [];
|
|
6942
|
+
const processedUrls = /* @__PURE__ */ new Set();
|
|
6831
6943
|
let linkCount = 0;
|
|
6832
6944
|
let match;
|
|
6833
|
-
while ((match = linkRegex.exec(
|
|
6834
|
-
match[
|
|
6835
|
-
|
|
6945
|
+
while ((match = linkRegex.exec(processedHtml)) !== null) {
|
|
6946
|
+
const originalUrl = match[1].trim();
|
|
6947
|
+
if (processedUrls.has(originalUrl)) continue;
|
|
6836
6948
|
strapi2.log.debug(`[magic-mail] [CHECK] Found link: ${originalUrl.substring(0, 100)}${originalUrl.length > 100 ? "..." : ""}`);
|
|
6837
|
-
if (originalUrl.startsWith("#") || originalUrl.includes("/track/click/")) {
|
|
6838
|
-
strapi2.log.debug(`[magic-mail] [SKIP] Skipping
|
|
6949
|
+
if (originalUrl.startsWith("#") || originalUrl.includes("/track/click/") || originalUrl.startsWith("mailto:") || originalUrl.startsWith("tel:") || originalUrl.startsWith("javascript:")) {
|
|
6950
|
+
strapi2.log.debug(`[magic-mail] [SKIP] Skipping special URL: ${originalUrl.substring(0, 50)}`);
|
|
6839
6951
|
continue;
|
|
6840
6952
|
}
|
|
6841
|
-
if (!originalUrl.match(/^https?:\/\//i)
|
|
6842
|
-
strapi2.log.debug(`[magic-mail] [SKIP] Skipping
|
|
6953
|
+
if (!originalUrl.match(/^https?:\/\//i)) {
|
|
6954
|
+
strapi2.log.debug(`[magic-mail] [SKIP] Skipping non-http URL: ${originalUrl.substring(0, 50)}`);
|
|
6843
6955
|
continue;
|
|
6844
6956
|
}
|
|
6957
|
+
processedUrls.add(originalUrl);
|
|
6845
6958
|
const linkHash = crypto.createHash("md5").update(originalUrl).digest("hex").substring(0, 8);
|
|
6846
6959
|
linkMappings.push({
|
|
6847
6960
|
linkHash,
|
|
@@ -6849,12 +6962,27 @@ function requireAnalytics() {
|
|
|
6849
6962
|
});
|
|
6850
6963
|
const trackingUrl = `${baseUrl}/api/magic-mail/track/click/${emailId}/${linkHash}/${recipientHash}`;
|
|
6851
6964
|
linkCount++;
|
|
6852
|
-
strapi2.log.info(`[magic-mail] [LINK] Link ${linkCount}: ${originalUrl}
|
|
6965
|
+
strapi2.log.info(`[magic-mail] [LINK] Link ${linkCount}: ${originalUrl.substring(0, 80)}${originalUrl.length > 80 ? "..." : ""}`);
|
|
6853
6966
|
replacements.push({
|
|
6854
6967
|
from: originalUrl,
|
|
6855
6968
|
to: trackingUrl
|
|
6856
6969
|
});
|
|
6857
6970
|
}
|
|
6971
|
+
if (linkCount === 0) {
|
|
6972
|
+
strapi2.log.debug(`[magic-mail] [LINK-TRACK] Primary regex found no links, trying simple pattern...`);
|
|
6973
|
+
while ((match = simpleLinkRegex.exec(processedHtml)) !== null) {
|
|
6974
|
+
const originalUrl = match[1].trim();
|
|
6975
|
+
if (processedUrls.has(originalUrl)) continue;
|
|
6976
|
+
if (originalUrl.includes("/track/click/")) continue;
|
|
6977
|
+
processedUrls.add(originalUrl);
|
|
6978
|
+
const linkHash = crypto.createHash("md5").update(originalUrl).digest("hex").substring(0, 8);
|
|
6979
|
+
linkMappings.push({ linkHash, originalUrl });
|
|
6980
|
+
const trackingUrl = `${baseUrl}/api/magic-mail/track/click/${emailId}/${linkHash}/${recipientHash}`;
|
|
6981
|
+
linkCount++;
|
|
6982
|
+
strapi2.log.info(`[magic-mail] [LINK] Link ${linkCount} (simple): ${originalUrl.substring(0, 80)}`);
|
|
6983
|
+
replacements.push({ from: originalUrl, to: trackingUrl });
|
|
6984
|
+
}
|
|
6985
|
+
}
|
|
6858
6986
|
for (const mapping of linkMappings) {
|
|
6859
6987
|
try {
|
|
6860
6988
|
await this.storeLinkMapping(emailLog.documentId, mapping.linkHash, mapping.originalUrl);
|
|
@@ -6865,13 +6993,17 @@ function requireAnalytics() {
|
|
|
6865
6993
|
let result = html;
|
|
6866
6994
|
for (const replacement of replacements) {
|
|
6867
6995
|
const escapedFrom = replacement.from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6996
|
+
const escapedFromEncoded = replacement.from.replace(/&/g, "&").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6868
6997
|
const hrefRegex = new RegExp(`(href\\s*=\\s*["'])${escapedFrom}(["'])`, "gi");
|
|
6998
|
+
const hrefRegexEncoded = new RegExp(`(href\\s*=\\s*["'])${escapedFromEncoded}(["'])`, "gi");
|
|
6869
6999
|
result = result.replace(hrefRegex, `$1${replacement.to}$2`);
|
|
7000
|
+
result = result.replace(hrefRegexEncoded, `$1${replacement.to}$2`);
|
|
6870
7001
|
}
|
|
6871
7002
|
if (linkCount > 0) {
|
|
6872
7003
|
strapi2.log.info(`[magic-mail] [SUCCESS] Rewrote ${linkCount} links for click tracking`);
|
|
6873
7004
|
} else {
|
|
6874
|
-
strapi2.log.warn(`[magic-mail] [WARNING]
|
|
7005
|
+
strapi2.log.warn(`[magic-mail] [WARNING] No links found in email HTML for tracking!`);
|
|
7006
|
+
strapi2.log.debug(`[magic-mail] [DEBUG] HTML preview: ${html.substring(0, 500)}...`);
|
|
6875
7007
|
}
|
|
6876
7008
|
return result;
|
|
6877
7009
|
},
|
|
@@ -6956,14 +7088,14 @@ function requireWhatsapp() {
|
|
|
6956
7088
|
const loadBaileys = async () => {
|
|
6957
7089
|
if (!baileys) {
|
|
6958
7090
|
try {
|
|
6959
|
-
baileys = require("
|
|
7091
|
+
baileys = require("baileys");
|
|
6960
7092
|
if (process.env.DEBUG) {
|
|
6961
7093
|
console.log("[MagicMail WhatsApp] Baileys loaded successfully");
|
|
6962
7094
|
}
|
|
6963
7095
|
return true;
|
|
6964
7096
|
} catch (error) {
|
|
6965
7097
|
console.warn("[MagicMail WhatsApp] Baileys not installed. WhatsApp features disabled.");
|
|
6966
|
-
console.warn("[MagicMail WhatsApp] Install with: npm install
|
|
7098
|
+
console.warn("[MagicMail WhatsApp] Install with: npm install baileys pino qrcode");
|
|
6967
7099
|
return false;
|
|
6968
7100
|
}
|
|
6969
7101
|
}
|
|
@@ -7043,7 +7175,7 @@ function requireWhatsapp() {
|
|
|
7043
7175
|
async connect() {
|
|
7044
7176
|
const available = await loadBaileys();
|
|
7045
7177
|
if (!available) {
|
|
7046
|
-
lastError = "Baileys not installed. Run: npm install
|
|
7178
|
+
lastError = "Baileys not installed. Run: npm install baileys pino qrcode";
|
|
7047
7179
|
strapi2.log.error("[MagicMail WhatsApp] [ERROR] Baileys library not available");
|
|
7048
7180
|
return { success: false, error: lastError };
|
|
7049
7181
|
}
|
|
@@ -7373,6 +7505,116 @@ function requireWhatsapp() {
|
|
|
7373
7505
|
};
|
|
7374
7506
|
return whatsapp;
|
|
7375
7507
|
}
|
|
7508
|
+
var pluginSettings;
|
|
7509
|
+
var hasRequiredPluginSettings;
|
|
7510
|
+
function requirePluginSettings() {
|
|
7511
|
+
if (hasRequiredPluginSettings) return pluginSettings;
|
|
7512
|
+
hasRequiredPluginSettings = 1;
|
|
7513
|
+
const SETTINGS_UID = "plugin::magic-mail.plugin-settings";
|
|
7514
|
+
pluginSettings = ({ strapi: strapi2 }) => ({
|
|
7515
|
+
/**
|
|
7516
|
+
* Get plugin settings (creates default if not exists)
|
|
7517
|
+
* @returns {Promise<Object>} Plugin settings
|
|
7518
|
+
*/
|
|
7519
|
+
async getSettings() {
|
|
7520
|
+
try {
|
|
7521
|
+
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
|
7522
|
+
if (!settings) {
|
|
7523
|
+
settings = await strapi2.documents(SETTINGS_UID).create({
|
|
7524
|
+
data: {
|
|
7525
|
+
enableLinkTracking: true,
|
|
7526
|
+
enableOpenTracking: true,
|
|
7527
|
+
trackingBaseUrl: null,
|
|
7528
|
+
defaultFromName: null,
|
|
7529
|
+
defaultFromEmail: null,
|
|
7530
|
+
unsubscribeUrl: null,
|
|
7531
|
+
enableUnsubscribeHeader: true
|
|
7532
|
+
}
|
|
7533
|
+
});
|
|
7534
|
+
strapi2.log.info("[magic-mail] [SETTINGS] Created default plugin settings");
|
|
7535
|
+
}
|
|
7536
|
+
return settings;
|
|
7537
|
+
} catch (error) {
|
|
7538
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error getting settings:", error);
|
|
7539
|
+
return {
|
|
7540
|
+
enableLinkTracking: true,
|
|
7541
|
+
enableOpenTracking: true,
|
|
7542
|
+
trackingBaseUrl: null,
|
|
7543
|
+
defaultFromName: null,
|
|
7544
|
+
defaultFromEmail: null,
|
|
7545
|
+
unsubscribeUrl: null,
|
|
7546
|
+
enableUnsubscribeHeader: true
|
|
7547
|
+
};
|
|
7548
|
+
}
|
|
7549
|
+
},
|
|
7550
|
+
/**
|
|
7551
|
+
* Update plugin settings
|
|
7552
|
+
* @param {Object} data - Settings to update
|
|
7553
|
+
* @returns {Promise<Object>} Updated settings
|
|
7554
|
+
*/
|
|
7555
|
+
async updateSettings(data) {
|
|
7556
|
+
try {
|
|
7557
|
+
const sanitizedData = {
|
|
7558
|
+
...data,
|
|
7559
|
+
trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
|
|
7560
|
+
defaultFromName: data.defaultFromName?.trim() || null,
|
|
7561
|
+
defaultFromEmail: data.defaultFromEmail?.trim() || null,
|
|
7562
|
+
unsubscribeUrl: data.unsubscribeUrl?.trim() || null
|
|
7563
|
+
};
|
|
7564
|
+
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
|
7565
|
+
if (settings) {
|
|
7566
|
+
settings = await strapi2.documents(SETTINGS_UID).update({
|
|
7567
|
+
documentId: settings.documentId,
|
|
7568
|
+
data: sanitizedData
|
|
7569
|
+
});
|
|
7570
|
+
strapi2.log.info("[magic-mail] [SETTINGS] Updated plugin settings");
|
|
7571
|
+
} else {
|
|
7572
|
+
settings = await strapi2.documents(SETTINGS_UID).create({
|
|
7573
|
+
data: {
|
|
7574
|
+
enableLinkTracking: sanitizedData.enableLinkTracking ?? true,
|
|
7575
|
+
enableOpenTracking: sanitizedData.enableOpenTracking ?? true,
|
|
7576
|
+
trackingBaseUrl: sanitizedData.trackingBaseUrl,
|
|
7577
|
+
defaultFromName: sanitizedData.defaultFromName,
|
|
7578
|
+
defaultFromEmail: sanitizedData.defaultFromEmail,
|
|
7579
|
+
unsubscribeUrl: sanitizedData.unsubscribeUrl,
|
|
7580
|
+
enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true
|
|
7581
|
+
}
|
|
7582
|
+
});
|
|
7583
|
+
strapi2.log.info("[magic-mail] [SETTINGS] Created plugin settings");
|
|
7584
|
+
}
|
|
7585
|
+
return settings;
|
|
7586
|
+
} catch (error) {
|
|
7587
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error updating settings:", error);
|
|
7588
|
+
throw error;
|
|
7589
|
+
}
|
|
7590
|
+
},
|
|
7591
|
+
/**
|
|
7592
|
+
* Check if link tracking is enabled
|
|
7593
|
+
* @returns {Promise<boolean>}
|
|
7594
|
+
*/
|
|
7595
|
+
async isLinkTrackingEnabled() {
|
|
7596
|
+
const settings = await this.getSettings();
|
|
7597
|
+
return settings.enableLinkTracking !== false;
|
|
7598
|
+
},
|
|
7599
|
+
/**
|
|
7600
|
+
* Check if open tracking is enabled
|
|
7601
|
+
* @returns {Promise<boolean>}
|
|
7602
|
+
*/
|
|
7603
|
+
async isOpenTrackingEnabled() {
|
|
7604
|
+
const settings = await this.getSettings();
|
|
7605
|
+
return settings.enableOpenTracking !== false;
|
|
7606
|
+
},
|
|
7607
|
+
/**
|
|
7608
|
+
* Get tracking base URL
|
|
7609
|
+
* @returns {Promise<string|null>}
|
|
7610
|
+
*/
|
|
7611
|
+
async getTrackingBaseUrl() {
|
|
7612
|
+
const settings = await this.getSettings();
|
|
7613
|
+
return settings.trackingBaseUrl || null;
|
|
7614
|
+
}
|
|
7615
|
+
});
|
|
7616
|
+
return pluginSettings;
|
|
7617
|
+
}
|
|
7376
7618
|
var services;
|
|
7377
7619
|
var hasRequiredServices;
|
|
7378
7620
|
function requireServices() {
|
|
@@ -7385,6 +7627,7 @@ function requireServices() {
|
|
|
7385
7627
|
const emailDesigner2 = requireEmailDesigner();
|
|
7386
7628
|
const analytics2 = requireAnalytics();
|
|
7387
7629
|
const whatsapp2 = requireWhatsapp();
|
|
7630
|
+
const pluginSettings2 = requirePluginSettings();
|
|
7388
7631
|
services = {
|
|
7389
7632
|
"email-router": emailRouter2,
|
|
7390
7633
|
"account-manager": accountManager2,
|
|
@@ -7392,7 +7635,8 @@ function requireServices() {
|
|
|
7392
7635
|
"license-guard": licenseGuard2,
|
|
7393
7636
|
"email-designer": emailDesigner2,
|
|
7394
7637
|
analytics: analytics2,
|
|
7395
|
-
whatsapp: whatsapp2
|
|
7638
|
+
whatsapp: whatsapp2,
|
|
7639
|
+
"plugin-settings": pluginSettings2
|
|
7396
7640
|
};
|
|
7397
7641
|
return services;
|
|
7398
7642
|
}
|