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.js
CHANGED
|
@@ -250,13 +250,27 @@ function requireConfig() {
|
|
|
250
250
|
};
|
|
251
251
|
return config;
|
|
252
252
|
}
|
|
253
|
+
const kind$7 = "collectionType";
|
|
254
|
+
const collectionName$7 = "magic_mail_accounts";
|
|
255
|
+
const info$7 = { "singularName": "email-account", "pluralName": "email-accounts", "displayName": "Email Account", "description": "Email provider accounts for multi-account email sending" };
|
|
256
|
+
const options$7 = { "draftAndPublish": false };
|
|
257
|
+
const pluginOptions$7 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
258
|
+
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" } };
|
|
259
|
+
const require$$0 = {
|
|
260
|
+
kind: kind$7,
|
|
261
|
+
collectionName: collectionName$7,
|
|
262
|
+
info: info$7,
|
|
263
|
+
options: options$7,
|
|
264
|
+
pluginOptions: pluginOptions$7,
|
|
265
|
+
attributes: attributes$7
|
|
266
|
+
};
|
|
253
267
|
const kind$6 = "collectionType";
|
|
254
|
-
const collectionName$6 = "
|
|
255
|
-
const info$6 = { "singularName": "
|
|
268
|
+
const collectionName$6 = "magic_mail_routing_rules";
|
|
269
|
+
const info$6 = { "singularName": "routing-rule", "pluralName": "routing-rules", "displayName": "Email Routing Rule", "description": "Rules for routing emails to specific accounts" };
|
|
256
270
|
const options$6 = { "draftAndPublish": false };
|
|
257
271
|
const pluginOptions$6 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
258
|
-
const attributes$6 = { "name": { "type": "string", "required": true, "unique": true }, "description": { "type": "text" }, "
|
|
259
|
-
const require$$
|
|
272
|
+
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" } };
|
|
273
|
+
const require$$1 = {
|
|
260
274
|
kind: kind$6,
|
|
261
275
|
collectionName: collectionName$6,
|
|
262
276
|
info: info$6,
|
|
@@ -265,12 +279,12 @@ const require$$0 = {
|
|
|
265
279
|
attributes: attributes$6
|
|
266
280
|
};
|
|
267
281
|
const kind$5 = "collectionType";
|
|
268
|
-
const collectionName$5 = "
|
|
269
|
-
const info$5 = { "singularName": "
|
|
282
|
+
const collectionName$5 = "magic_mail_email_logs";
|
|
283
|
+
const info$5 = { "singularName": "email-log", "pluralName": "email-logs", "displayName": "Email Log", "description": "Tracks all sent emails with user association" };
|
|
270
284
|
const options$5 = { "draftAndPublish": false };
|
|
271
285
|
const pluginOptions$5 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
272
|
-
const attributes$5 = { "
|
|
273
|
-
const require$$1 = {
|
|
286
|
+
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" } };
|
|
287
|
+
const require$$2$1 = {
|
|
274
288
|
kind: kind$5,
|
|
275
289
|
collectionName: collectionName$5,
|
|
276
290
|
info: info$5,
|
|
@@ -279,12 +293,12 @@ const require$$1 = {
|
|
|
279
293
|
attributes: attributes$5
|
|
280
294
|
};
|
|
281
295
|
const kind$4 = "collectionType";
|
|
282
|
-
const collectionName$4 = "
|
|
283
|
-
const info$4 = { "singularName": "email-
|
|
296
|
+
const collectionName$4 = "magic_mail_email_events";
|
|
297
|
+
const info$4 = { "singularName": "email-event", "pluralName": "email-events", "displayName": "Email Event", "description": "Individual email tracking events (opens, clicks, bounces)" };
|
|
284
298
|
const options$4 = { "draftAndPublish": false };
|
|
285
299
|
const pluginOptions$4 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
286
|
-
const attributes$4 = { "
|
|
287
|
-
const require$$
|
|
300
|
+
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" } };
|
|
301
|
+
const require$$3 = {
|
|
288
302
|
kind: kind$4,
|
|
289
303
|
collectionName: collectionName$4,
|
|
290
304
|
info: info$4,
|
|
@@ -293,12 +307,12 @@ const require$$2$1 = {
|
|
|
293
307
|
attributes: attributes$4
|
|
294
308
|
};
|
|
295
309
|
const kind$3 = "collectionType";
|
|
296
|
-
const collectionName$3 = "
|
|
297
|
-
const info$3 = { "singularName": "email-
|
|
310
|
+
const collectionName$3 = "magic_mail_email_links";
|
|
311
|
+
const info$3 = { "singularName": "email-link", "pluralName": "email-links", "displayName": "Email Link", "description": "Stores click tracking links for emails" };
|
|
298
312
|
const options$3 = { "draftAndPublish": false };
|
|
299
313
|
const pluginOptions$3 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
300
|
-
const attributes$3 = { "emailLog": { "type": "relation", "relation": "manyToOne", "target": "plugin::magic-mail.email-log", "inversedBy": "
|
|
301
|
-
const require$$
|
|
314
|
+
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" } };
|
|
315
|
+
const require$$4 = {
|
|
302
316
|
kind: kind$3,
|
|
303
317
|
collectionName: collectionName$3,
|
|
304
318
|
info: info$3,
|
|
@@ -307,12 +321,12 @@ const require$$3 = {
|
|
|
307
321
|
attributes: attributes$3
|
|
308
322
|
};
|
|
309
323
|
const kind$2 = "collectionType";
|
|
310
|
-
const collectionName$2 = "
|
|
311
|
-
const info$2 = { "singularName": "email-
|
|
312
|
-
const options$2 = { "draftAndPublish": false };
|
|
324
|
+
const collectionName$2 = "magic_mail_email_templates";
|
|
325
|
+
const info$2 = { "singularName": "email-template", "pluralName": "email-templates", "displayName": "Email Template", "description": "Email templates created with the visual designer" };
|
|
326
|
+
const options$2 = { "draftAndPublish": false, "timestamps": true };
|
|
313
327
|
const pluginOptions$2 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
314
|
-
const attributes$2 = { "
|
|
315
|
-
const require$$
|
|
328
|
+
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" } };
|
|
329
|
+
const require$$5 = {
|
|
316
330
|
kind: kind$2,
|
|
317
331
|
collectionName: collectionName$2,
|
|
318
332
|
info: info$2,
|
|
@@ -321,12 +335,12 @@ const require$$4 = {
|
|
|
321
335
|
attributes: attributes$2
|
|
322
336
|
};
|
|
323
337
|
const kind$1 = "collectionType";
|
|
324
|
-
const collectionName$1 = "
|
|
325
|
-
const info$1 = { "singularName": "email-template", "pluralName": "email-
|
|
338
|
+
const collectionName$1 = "magic_mail_email_template_versions";
|
|
339
|
+
const info$1 = { "singularName": "email-template-version", "pluralName": "email-template-versions", "displayName": "Email Template Version", "description": "Version history for email templates" };
|
|
326
340
|
const options$1 = { "draftAndPublish": false, "timestamps": true };
|
|
327
341
|
const pluginOptions$1 = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
328
|
-
const attributes$1 = { "
|
|
329
|
-
const require$$
|
|
342
|
+
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 } };
|
|
343
|
+
const require$$6 = {
|
|
330
344
|
kind: kind$1,
|
|
331
345
|
collectionName: collectionName$1,
|
|
332
346
|
info: info$1,
|
|
@@ -334,13 +348,13 @@ const require$$5 = {
|
|
|
334
348
|
pluginOptions: pluginOptions$1,
|
|
335
349
|
attributes: attributes$1
|
|
336
350
|
};
|
|
337
|
-
const kind = "
|
|
338
|
-
const collectionName = "
|
|
339
|
-
const info = { "singularName": "
|
|
340
|
-
const options = { "draftAndPublish": false, "
|
|
351
|
+
const kind = "singleType";
|
|
352
|
+
const collectionName = "magic_mail_settings";
|
|
353
|
+
const info = { "singularName": "plugin-settings", "pluralName": "plugin-settings", "displayName": "MagicMail Settings" };
|
|
354
|
+
const options = { "draftAndPublish": false, "comment": "Global settings for MagicMail plugin" };
|
|
341
355
|
const pluginOptions = { "content-manager": { "visible": false }, "content-type-builder": { "visible": false } };
|
|
342
|
-
const attributes = { "
|
|
343
|
-
const require$$
|
|
356
|
+
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 } };
|
|
357
|
+
const require$$7 = {
|
|
344
358
|
kind,
|
|
345
359
|
collectionName,
|
|
346
360
|
info,
|
|
@@ -360,6 +374,7 @@ function requireContentTypes() {
|
|
|
360
374
|
const emailLink = require$$4;
|
|
361
375
|
const emailTemplate = require$$5;
|
|
362
376
|
const emailTemplateVersion = require$$6;
|
|
377
|
+
const pluginSettings2 = require$$7;
|
|
363
378
|
contentTypes = {
|
|
364
379
|
"email-account": {
|
|
365
380
|
schema: emailAccount
|
|
@@ -381,6 +396,9 @@ function requireContentTypes() {
|
|
|
381
396
|
},
|
|
382
397
|
"email-template-version": {
|
|
383
398
|
schema: emailTemplateVersion
|
|
399
|
+
},
|
|
400
|
+
"plugin-settings": {
|
|
401
|
+
schema: pluginSettings2
|
|
384
402
|
}
|
|
385
403
|
};
|
|
386
404
|
return contentTypes;
|
|
@@ -2555,7 +2573,7 @@ function requireWhatsapp$1() {
|
|
|
2555
2573
|
success: true,
|
|
2556
2574
|
data: {
|
|
2557
2575
|
available,
|
|
2558
|
-
message: available ? "WhatsApp integration is available" : "Baileys not installed. Run: npm install
|
|
2576
|
+
message: available ? "WhatsApp integration is available" : "Baileys not installed. Run: npm install baileys pino qrcode"
|
|
2559
2577
|
}
|
|
2560
2578
|
};
|
|
2561
2579
|
} catch (error) {
|
|
@@ -2750,6 +2768,62 @@ function requireWhatsapp$1() {
|
|
|
2750
2768
|
};
|
|
2751
2769
|
return whatsapp$1;
|
|
2752
2770
|
}
|
|
2771
|
+
var pluginSettings$1;
|
|
2772
|
+
var hasRequiredPluginSettings$1;
|
|
2773
|
+
function requirePluginSettings$1() {
|
|
2774
|
+
if (hasRequiredPluginSettings$1) return pluginSettings$1;
|
|
2775
|
+
hasRequiredPluginSettings$1 = 1;
|
|
2776
|
+
pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
2777
|
+
/**
|
|
2778
|
+
* GET /magic-mail/settings
|
|
2779
|
+
* Get current plugin settings
|
|
2780
|
+
*/
|
|
2781
|
+
async getSettings(ctx) {
|
|
2782
|
+
try {
|
|
2783
|
+
const settings = await strapi2.plugin("magic-mail").service("plugin-settings").getSettings();
|
|
2784
|
+
ctx.body = {
|
|
2785
|
+
data: settings
|
|
2786
|
+
};
|
|
2787
|
+
} catch (error) {
|
|
2788
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error getting settings:", error);
|
|
2789
|
+
ctx.throw(500, "Failed to get settings");
|
|
2790
|
+
}
|
|
2791
|
+
},
|
|
2792
|
+
/**
|
|
2793
|
+
* PUT /magic-mail/settings
|
|
2794
|
+
* Update plugin settings
|
|
2795
|
+
*/
|
|
2796
|
+
async updateSettings(ctx) {
|
|
2797
|
+
try {
|
|
2798
|
+
const { body } = ctx.request;
|
|
2799
|
+
const allowedFields = [
|
|
2800
|
+
"enableLinkTracking",
|
|
2801
|
+
"enableOpenTracking",
|
|
2802
|
+
"trackingBaseUrl",
|
|
2803
|
+
"defaultFromName",
|
|
2804
|
+
"defaultFromEmail",
|
|
2805
|
+
"unsubscribeUrl",
|
|
2806
|
+
"enableUnsubscribeHeader"
|
|
2807
|
+
];
|
|
2808
|
+
const data = {};
|
|
2809
|
+
for (const field of allowedFields) {
|
|
2810
|
+
if (body[field] !== void 0) {
|
|
2811
|
+
data[field] = body[field];
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
const settings = await strapi2.plugin("magic-mail").service("plugin-settings").updateSettings(data);
|
|
2815
|
+
ctx.body = {
|
|
2816
|
+
data: settings,
|
|
2817
|
+
message: "Settings updated successfully"
|
|
2818
|
+
};
|
|
2819
|
+
} catch (error) {
|
|
2820
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error updating settings:", error);
|
|
2821
|
+
ctx.throw(500, "Failed to update settings");
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
});
|
|
2825
|
+
return pluginSettings$1;
|
|
2826
|
+
}
|
|
2753
2827
|
var controllers;
|
|
2754
2828
|
var hasRequiredControllers;
|
|
2755
2829
|
function requireControllers() {
|
|
@@ -2764,6 +2838,7 @@ function requireControllers() {
|
|
|
2764
2838
|
const analytics2 = requireAnalytics$1();
|
|
2765
2839
|
const test2 = requireTest();
|
|
2766
2840
|
const whatsapp2 = requireWhatsapp$1();
|
|
2841
|
+
const pluginSettings2 = requirePluginSettings$1();
|
|
2767
2842
|
controllers = {
|
|
2768
2843
|
controller: controller2,
|
|
2769
2844
|
accounts: accounts2,
|
|
@@ -2773,7 +2848,8 @@ function requireControllers() {
|
|
|
2773
2848
|
emailDesigner: emailDesigner2,
|
|
2774
2849
|
analytics: analytics2,
|
|
2775
2850
|
test: test2,
|
|
2776
|
-
whatsapp: whatsapp2
|
|
2851
|
+
whatsapp: whatsapp2,
|
|
2852
|
+
pluginSettings: pluginSettings2
|
|
2777
2853
|
};
|
|
2778
2854
|
return controllers;
|
|
2779
2855
|
}
|
|
@@ -3348,6 +3424,25 @@ function requireAdmin() {
|
|
|
3348
3424
|
policies: ["admin::isAuthenticatedAdmin"],
|
|
3349
3425
|
description: "Get WhatsApp session info"
|
|
3350
3426
|
}
|
|
3427
|
+
},
|
|
3428
|
+
// Plugin Settings Routes
|
|
3429
|
+
{
|
|
3430
|
+
method: "GET",
|
|
3431
|
+
path: "/settings",
|
|
3432
|
+
handler: "pluginSettings.getSettings",
|
|
3433
|
+
config: {
|
|
3434
|
+
policies: ["admin::isAuthenticatedAdmin"],
|
|
3435
|
+
description: "Get plugin settings"
|
|
3436
|
+
}
|
|
3437
|
+
},
|
|
3438
|
+
{
|
|
3439
|
+
method: "PUT",
|
|
3440
|
+
path: "/settings",
|
|
3441
|
+
handler: "pluginSettings.updateSettings",
|
|
3442
|
+
config: {
|
|
3443
|
+
policies: ["admin::isAuthenticatedAdmin"],
|
|
3444
|
+
description: "Update plugin settings"
|
|
3445
|
+
}
|
|
3351
3446
|
}
|
|
3352
3447
|
]
|
|
3353
3448
|
};
|
|
@@ -3624,6 +3719,10 @@ function requireEmailRouter() {
|
|
|
3624
3719
|
if (enableTracking && html) {
|
|
3625
3720
|
try {
|
|
3626
3721
|
const analyticsService = strapi2.plugin("magic-mail").service("analytics");
|
|
3722
|
+
const settingsService = strapi2.plugin("magic-mail").service("plugin-settings");
|
|
3723
|
+
const pluginSettings2 = await settingsService.getSettings();
|
|
3724
|
+
const globalLinkTrackingEnabled = pluginSettings2.enableLinkTracking !== false;
|
|
3725
|
+
const globalOpenTrackingEnabled = pluginSettings2.enableOpenTracking !== false;
|
|
3627
3726
|
emailLog = await analyticsService.createEmailLog({
|
|
3628
3727
|
to,
|
|
3629
3728
|
userId: emailData.userId || null,
|
|
@@ -3642,12 +3741,19 @@ function requireEmailRouter() {
|
|
|
3642
3741
|
}
|
|
3643
3742
|
});
|
|
3644
3743
|
recipientHash = analyticsService.generateRecipientHash(emailLog.emailId, to);
|
|
3645
|
-
|
|
3646
|
-
|
|
3744
|
+
if (globalOpenTrackingEnabled) {
|
|
3745
|
+
html = analyticsService.injectTrackingPixel(html, emailLog.emailId, recipientHash);
|
|
3746
|
+
} else {
|
|
3747
|
+
strapi2.log.info(`[magic-mail] [STATS] Open tracking DISABLED globally`);
|
|
3748
|
+
}
|
|
3749
|
+
const shouldTrackLinks = globalLinkTrackingEnabled && !skipLinkTracking;
|
|
3750
|
+
if (shouldTrackLinks) {
|
|
3647
3751
|
html = await analyticsService.rewriteLinksForTracking(html, emailLog.emailId, recipientHash);
|
|
3648
|
-
strapi2.log.info(`[magic-mail] [STATS]
|
|
3752
|
+
strapi2.log.info(`[magic-mail] [STATS] Link tracking enabled for email: ${emailLog.emailId}`);
|
|
3753
|
+
} else if (!globalLinkTrackingEnabled) {
|
|
3754
|
+
strapi2.log.info(`[magic-mail] [STATS] Link tracking DISABLED globally for email: ${emailLog.emailId}`);
|
|
3649
3755
|
} else {
|
|
3650
|
-
strapi2.log.info(`[magic-mail] [STATS]
|
|
3756
|
+
strapi2.log.info(`[magic-mail] [STATS] Link tracking DISABLED per-email (skipLinkTracking=true) for email: ${emailLog.emailId}`);
|
|
3651
3757
|
}
|
|
3652
3758
|
} catch (error) {
|
|
3653
3759
|
strapi2.log.error(`[magic-mail] [WARNING] Tracking setup failed (continuing without tracking):`, error.message);
|
|
@@ -3721,7 +3827,7 @@ function requireEmailRouter() {
|
|
|
3721
3827
|
await strapi2.documents("plugin::magic-mail.email-log").update({
|
|
3722
3828
|
documentId: emailLog.documentId,
|
|
3723
3829
|
data: {
|
|
3724
|
-
accountId: account.
|
|
3830
|
+
accountId: account.documentId,
|
|
3725
3831
|
accountName: account.name,
|
|
3726
3832
|
deliveredAt: /* @__PURE__ */ new Date()
|
|
3727
3833
|
}
|
|
@@ -5543,7 +5649,7 @@ function requireOauth() {
|
|
|
5543
5649
|
});
|
|
5544
5650
|
return oauth;
|
|
5545
5651
|
}
|
|
5546
|
-
const version = "2.
|
|
5652
|
+
const version = "2.4.0";
|
|
5547
5653
|
const require$$2 = {
|
|
5548
5654
|
version
|
|
5549
5655
|
};
|
|
@@ -6827,7 +6933,10 @@ function requireAnalytics() {
|
|
|
6827
6933
|
* Rewrite links for click tracking
|
|
6828
6934
|
*/
|
|
6829
6935
|
async rewriteLinksForTracking(html, emailId, recipientHash) {
|
|
6830
|
-
const
|
|
6936
|
+
const settingsService = strapi2.plugin("magic-mail").service("plugin-settings");
|
|
6937
|
+
const pluginSettings2 = await settingsService.getSettings();
|
|
6938
|
+
const baseUrl = pluginSettings2.trackingBaseUrl || strapi2.config.get("server.url") || "http://localhost:1337";
|
|
6939
|
+
strapi2.log.debug(`[magic-mail] [LINK-TRACK] Using base URL: ${baseUrl}`);
|
|
6831
6940
|
const emailLog = await strapi2.documents(EMAIL_LOG_UID).findFirst({
|
|
6832
6941
|
filters: { emailId }
|
|
6833
6942
|
});
|
|
@@ -6835,23 +6944,27 @@ function requireAnalytics() {
|
|
|
6835
6944
|
strapi2.log.error(`[magic-mail] Cannot rewrite links: Email log not found for ${emailId}`);
|
|
6836
6945
|
return html;
|
|
6837
6946
|
}
|
|
6838
|
-
|
|
6947
|
+
let processedHtml = html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"');
|
|
6948
|
+
const linkRegex = /<a\s+(?:[^>]*?\s+)?href\s*=\s*["']([^"']+)["'][^>]*>/gis;
|
|
6949
|
+
const simpleLinkRegex = /href\s*=\s*["'](https?:\/\/[^"']+)["']/gi;
|
|
6839
6950
|
const linkMappings = [];
|
|
6840
6951
|
const replacements = [];
|
|
6952
|
+
const processedUrls = /* @__PURE__ */ new Set();
|
|
6841
6953
|
let linkCount = 0;
|
|
6842
6954
|
let match;
|
|
6843
|
-
while ((match = linkRegex.exec(
|
|
6844
|
-
match[
|
|
6845
|
-
|
|
6955
|
+
while ((match = linkRegex.exec(processedHtml)) !== null) {
|
|
6956
|
+
const originalUrl = match[1].trim();
|
|
6957
|
+
if (processedUrls.has(originalUrl)) continue;
|
|
6846
6958
|
strapi2.log.debug(`[magic-mail] [CHECK] Found link: ${originalUrl.substring(0, 100)}${originalUrl.length > 100 ? "..." : ""}`);
|
|
6847
|
-
if (originalUrl.startsWith("#") || originalUrl.includes("/track/click/")) {
|
|
6848
|
-
strapi2.log.debug(`[magic-mail] [SKIP] Skipping
|
|
6959
|
+
if (originalUrl.startsWith("#") || originalUrl.includes("/track/click/") || originalUrl.startsWith("mailto:") || originalUrl.startsWith("tel:") || originalUrl.startsWith("javascript:")) {
|
|
6960
|
+
strapi2.log.debug(`[magic-mail] [SKIP] Skipping special URL: ${originalUrl.substring(0, 50)}`);
|
|
6849
6961
|
continue;
|
|
6850
6962
|
}
|
|
6851
|
-
if (!originalUrl.match(/^https?:\/\//i)
|
|
6852
|
-
strapi2.log.debug(`[magic-mail] [SKIP] Skipping
|
|
6963
|
+
if (!originalUrl.match(/^https?:\/\//i)) {
|
|
6964
|
+
strapi2.log.debug(`[magic-mail] [SKIP] Skipping non-http URL: ${originalUrl.substring(0, 50)}`);
|
|
6853
6965
|
continue;
|
|
6854
6966
|
}
|
|
6967
|
+
processedUrls.add(originalUrl);
|
|
6855
6968
|
const linkHash = crypto.createHash("md5").update(originalUrl).digest("hex").substring(0, 8);
|
|
6856
6969
|
linkMappings.push({
|
|
6857
6970
|
linkHash,
|
|
@@ -6859,12 +6972,27 @@ function requireAnalytics() {
|
|
|
6859
6972
|
});
|
|
6860
6973
|
const trackingUrl = `${baseUrl}/api/magic-mail/track/click/${emailId}/${linkHash}/${recipientHash}`;
|
|
6861
6974
|
linkCount++;
|
|
6862
|
-
strapi2.log.info(`[magic-mail] [LINK] Link ${linkCount}: ${originalUrl}
|
|
6975
|
+
strapi2.log.info(`[magic-mail] [LINK] Link ${linkCount}: ${originalUrl.substring(0, 80)}${originalUrl.length > 80 ? "..." : ""}`);
|
|
6863
6976
|
replacements.push({
|
|
6864
6977
|
from: originalUrl,
|
|
6865
6978
|
to: trackingUrl
|
|
6866
6979
|
});
|
|
6867
6980
|
}
|
|
6981
|
+
if (linkCount === 0) {
|
|
6982
|
+
strapi2.log.debug(`[magic-mail] [LINK-TRACK] Primary regex found no links, trying simple pattern...`);
|
|
6983
|
+
while ((match = simpleLinkRegex.exec(processedHtml)) !== null) {
|
|
6984
|
+
const originalUrl = match[1].trim();
|
|
6985
|
+
if (processedUrls.has(originalUrl)) continue;
|
|
6986
|
+
if (originalUrl.includes("/track/click/")) continue;
|
|
6987
|
+
processedUrls.add(originalUrl);
|
|
6988
|
+
const linkHash = crypto.createHash("md5").update(originalUrl).digest("hex").substring(0, 8);
|
|
6989
|
+
linkMappings.push({ linkHash, originalUrl });
|
|
6990
|
+
const trackingUrl = `${baseUrl}/api/magic-mail/track/click/${emailId}/${linkHash}/${recipientHash}`;
|
|
6991
|
+
linkCount++;
|
|
6992
|
+
strapi2.log.info(`[magic-mail] [LINK] Link ${linkCount} (simple): ${originalUrl.substring(0, 80)}`);
|
|
6993
|
+
replacements.push({ from: originalUrl, to: trackingUrl });
|
|
6994
|
+
}
|
|
6995
|
+
}
|
|
6868
6996
|
for (const mapping of linkMappings) {
|
|
6869
6997
|
try {
|
|
6870
6998
|
await this.storeLinkMapping(emailLog.documentId, mapping.linkHash, mapping.originalUrl);
|
|
@@ -6875,13 +7003,17 @@ function requireAnalytics() {
|
|
|
6875
7003
|
let result = html;
|
|
6876
7004
|
for (const replacement of replacements) {
|
|
6877
7005
|
const escapedFrom = replacement.from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7006
|
+
const escapedFromEncoded = replacement.from.replace(/&/g, "&").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6878
7007
|
const hrefRegex = new RegExp(`(href\\s*=\\s*["'])${escapedFrom}(["'])`, "gi");
|
|
7008
|
+
const hrefRegexEncoded = new RegExp(`(href\\s*=\\s*["'])${escapedFromEncoded}(["'])`, "gi");
|
|
6879
7009
|
result = result.replace(hrefRegex, `$1${replacement.to}$2`);
|
|
7010
|
+
result = result.replace(hrefRegexEncoded, `$1${replacement.to}$2`);
|
|
6880
7011
|
}
|
|
6881
7012
|
if (linkCount > 0) {
|
|
6882
7013
|
strapi2.log.info(`[magic-mail] [SUCCESS] Rewrote ${linkCount} links for click tracking`);
|
|
6883
7014
|
} else {
|
|
6884
|
-
strapi2.log.warn(`[magic-mail] [WARNING]
|
|
7015
|
+
strapi2.log.warn(`[magic-mail] [WARNING] No links found in email HTML for tracking!`);
|
|
7016
|
+
strapi2.log.debug(`[magic-mail] [DEBUG] HTML preview: ${html.substring(0, 500)}...`);
|
|
6885
7017
|
}
|
|
6886
7018
|
return result;
|
|
6887
7019
|
},
|
|
@@ -6966,14 +7098,14 @@ function requireWhatsapp() {
|
|
|
6966
7098
|
const loadBaileys = async () => {
|
|
6967
7099
|
if (!baileys) {
|
|
6968
7100
|
try {
|
|
6969
|
-
baileys = require("
|
|
7101
|
+
baileys = require("baileys");
|
|
6970
7102
|
if (process.env.DEBUG) {
|
|
6971
7103
|
console.log("[MagicMail WhatsApp] Baileys loaded successfully");
|
|
6972
7104
|
}
|
|
6973
7105
|
return true;
|
|
6974
7106
|
} catch (error) {
|
|
6975
7107
|
console.warn("[MagicMail WhatsApp] Baileys not installed. WhatsApp features disabled.");
|
|
6976
|
-
console.warn("[MagicMail WhatsApp] Install with: npm install
|
|
7108
|
+
console.warn("[MagicMail WhatsApp] Install with: npm install baileys pino qrcode");
|
|
6977
7109
|
return false;
|
|
6978
7110
|
}
|
|
6979
7111
|
}
|
|
@@ -7053,7 +7185,7 @@ function requireWhatsapp() {
|
|
|
7053
7185
|
async connect() {
|
|
7054
7186
|
const available = await loadBaileys();
|
|
7055
7187
|
if (!available) {
|
|
7056
|
-
lastError = "Baileys not installed. Run: npm install
|
|
7188
|
+
lastError = "Baileys not installed. Run: npm install baileys pino qrcode";
|
|
7057
7189
|
strapi2.log.error("[MagicMail WhatsApp] [ERROR] Baileys library not available");
|
|
7058
7190
|
return { success: false, error: lastError };
|
|
7059
7191
|
}
|
|
@@ -7383,6 +7515,116 @@ function requireWhatsapp() {
|
|
|
7383
7515
|
};
|
|
7384
7516
|
return whatsapp;
|
|
7385
7517
|
}
|
|
7518
|
+
var pluginSettings;
|
|
7519
|
+
var hasRequiredPluginSettings;
|
|
7520
|
+
function requirePluginSettings() {
|
|
7521
|
+
if (hasRequiredPluginSettings) return pluginSettings;
|
|
7522
|
+
hasRequiredPluginSettings = 1;
|
|
7523
|
+
const SETTINGS_UID = "plugin::magic-mail.plugin-settings";
|
|
7524
|
+
pluginSettings = ({ strapi: strapi2 }) => ({
|
|
7525
|
+
/**
|
|
7526
|
+
* Get plugin settings (creates default if not exists)
|
|
7527
|
+
* @returns {Promise<Object>} Plugin settings
|
|
7528
|
+
*/
|
|
7529
|
+
async getSettings() {
|
|
7530
|
+
try {
|
|
7531
|
+
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
|
7532
|
+
if (!settings) {
|
|
7533
|
+
settings = await strapi2.documents(SETTINGS_UID).create({
|
|
7534
|
+
data: {
|
|
7535
|
+
enableLinkTracking: true,
|
|
7536
|
+
enableOpenTracking: true,
|
|
7537
|
+
trackingBaseUrl: null,
|
|
7538
|
+
defaultFromName: null,
|
|
7539
|
+
defaultFromEmail: null,
|
|
7540
|
+
unsubscribeUrl: null,
|
|
7541
|
+
enableUnsubscribeHeader: true
|
|
7542
|
+
}
|
|
7543
|
+
});
|
|
7544
|
+
strapi2.log.info("[magic-mail] [SETTINGS] Created default plugin settings");
|
|
7545
|
+
}
|
|
7546
|
+
return settings;
|
|
7547
|
+
} catch (error) {
|
|
7548
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error getting settings:", error);
|
|
7549
|
+
return {
|
|
7550
|
+
enableLinkTracking: true,
|
|
7551
|
+
enableOpenTracking: true,
|
|
7552
|
+
trackingBaseUrl: null,
|
|
7553
|
+
defaultFromName: null,
|
|
7554
|
+
defaultFromEmail: null,
|
|
7555
|
+
unsubscribeUrl: null,
|
|
7556
|
+
enableUnsubscribeHeader: true
|
|
7557
|
+
};
|
|
7558
|
+
}
|
|
7559
|
+
},
|
|
7560
|
+
/**
|
|
7561
|
+
* Update plugin settings
|
|
7562
|
+
* @param {Object} data - Settings to update
|
|
7563
|
+
* @returns {Promise<Object>} Updated settings
|
|
7564
|
+
*/
|
|
7565
|
+
async updateSettings(data) {
|
|
7566
|
+
try {
|
|
7567
|
+
const sanitizedData = {
|
|
7568
|
+
...data,
|
|
7569
|
+
trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
|
|
7570
|
+
defaultFromName: data.defaultFromName?.trim() || null,
|
|
7571
|
+
defaultFromEmail: data.defaultFromEmail?.trim() || null,
|
|
7572
|
+
unsubscribeUrl: data.unsubscribeUrl?.trim() || null
|
|
7573
|
+
};
|
|
7574
|
+
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
|
7575
|
+
if (settings) {
|
|
7576
|
+
settings = await strapi2.documents(SETTINGS_UID).update({
|
|
7577
|
+
documentId: settings.documentId,
|
|
7578
|
+
data: sanitizedData
|
|
7579
|
+
});
|
|
7580
|
+
strapi2.log.info("[magic-mail] [SETTINGS] Updated plugin settings");
|
|
7581
|
+
} else {
|
|
7582
|
+
settings = await strapi2.documents(SETTINGS_UID).create({
|
|
7583
|
+
data: {
|
|
7584
|
+
enableLinkTracking: sanitizedData.enableLinkTracking ?? true,
|
|
7585
|
+
enableOpenTracking: sanitizedData.enableOpenTracking ?? true,
|
|
7586
|
+
trackingBaseUrl: sanitizedData.trackingBaseUrl,
|
|
7587
|
+
defaultFromName: sanitizedData.defaultFromName,
|
|
7588
|
+
defaultFromEmail: sanitizedData.defaultFromEmail,
|
|
7589
|
+
unsubscribeUrl: sanitizedData.unsubscribeUrl,
|
|
7590
|
+
enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true
|
|
7591
|
+
}
|
|
7592
|
+
});
|
|
7593
|
+
strapi2.log.info("[magic-mail] [SETTINGS] Created plugin settings");
|
|
7594
|
+
}
|
|
7595
|
+
return settings;
|
|
7596
|
+
} catch (error) {
|
|
7597
|
+
strapi2.log.error("[magic-mail] [SETTINGS] Error updating settings:", error);
|
|
7598
|
+
throw error;
|
|
7599
|
+
}
|
|
7600
|
+
},
|
|
7601
|
+
/**
|
|
7602
|
+
* Check if link tracking is enabled
|
|
7603
|
+
* @returns {Promise<boolean>}
|
|
7604
|
+
*/
|
|
7605
|
+
async isLinkTrackingEnabled() {
|
|
7606
|
+
const settings = await this.getSettings();
|
|
7607
|
+
return settings.enableLinkTracking !== false;
|
|
7608
|
+
},
|
|
7609
|
+
/**
|
|
7610
|
+
* Check if open tracking is enabled
|
|
7611
|
+
* @returns {Promise<boolean>}
|
|
7612
|
+
*/
|
|
7613
|
+
async isOpenTrackingEnabled() {
|
|
7614
|
+
const settings = await this.getSettings();
|
|
7615
|
+
return settings.enableOpenTracking !== false;
|
|
7616
|
+
},
|
|
7617
|
+
/**
|
|
7618
|
+
* Get tracking base URL
|
|
7619
|
+
* @returns {Promise<string|null>}
|
|
7620
|
+
*/
|
|
7621
|
+
async getTrackingBaseUrl() {
|
|
7622
|
+
const settings = await this.getSettings();
|
|
7623
|
+
return settings.trackingBaseUrl || null;
|
|
7624
|
+
}
|
|
7625
|
+
});
|
|
7626
|
+
return pluginSettings;
|
|
7627
|
+
}
|
|
7386
7628
|
var services;
|
|
7387
7629
|
var hasRequiredServices;
|
|
7388
7630
|
function requireServices() {
|
|
@@ -7395,6 +7637,7 @@ function requireServices() {
|
|
|
7395
7637
|
const emailDesigner2 = requireEmailDesigner();
|
|
7396
7638
|
const analytics2 = requireAnalytics();
|
|
7397
7639
|
const whatsapp2 = requireWhatsapp();
|
|
7640
|
+
const pluginSettings2 = requirePluginSettings();
|
|
7398
7641
|
services = {
|
|
7399
7642
|
"email-router": emailRouter2,
|
|
7400
7643
|
"account-manager": accountManager2,
|
|
@@ -7402,7 +7645,8 @@ function requireServices() {
|
|
|
7402
7645
|
"license-guard": licenseGuard2,
|
|
7403
7646
|
"email-designer": emailDesigner2,
|
|
7404
7647
|
analytics: analytics2,
|
|
7405
|
-
whatsapp: whatsapp2
|
|
7648
|
+
whatsapp: whatsapp2,
|
|
7649
|
+
"plugin-settings": pluginSettings2
|
|
7406
7650
|
};
|
|
7407
7651
|
return services;
|
|
7408
7652
|
}
|