strapi-plugin-magic-mail 2.9.1 → 2.9.2
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/server/index.js +93 -14
- package/dist/server/index.mjs +93 -14
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -1007,6 +1007,10 @@ const attributes = {
|
|
|
1007
1007
|
type: "boolean",
|
|
1008
1008
|
"default": true,
|
|
1009
1009
|
configurable: false
|
|
1010
|
+
},
|
|
1011
|
+
trackingFallbackUrl: {
|
|
1012
|
+
type: "string",
|
|
1013
|
+
configurable: false
|
|
1010
1014
|
}
|
|
1011
1015
|
};
|
|
1012
1016
|
const require$$7 = {
|
|
@@ -48884,7 +48888,11 @@ const schemas = {
|
|
|
48884
48888
|
defaultFromName: headerSafe.optional(),
|
|
48885
48889
|
defaultFromEmail: emailString.optional().or(z2.literal("")),
|
|
48886
48890
|
unsubscribeUrl: z2.string().url().optional().or(z2.literal("")),
|
|
48887
|
-
enableUnsubscribeHeader: z2.boolean().optional()
|
|
48891
|
+
enableUnsubscribeHeader: z2.boolean().optional(),
|
|
48892
|
+
// Where to redirect the recipient when a tracking link is no longer
|
|
48893
|
+
// resolvable (e.g. retention cleanup removed the row). If empty the
|
|
48894
|
+
// tracker renders a static HTML fallback page instead.
|
|
48895
|
+
trackingFallbackUrl: z2.string().url().optional().or(z2.literal(""))
|
|
48888
48896
|
}),
|
|
48889
48897
|
// ── Content-API send payloads ───────────────────────────────────────────
|
|
48890
48898
|
// Bounded attachments to prevent OOM from huge base64 payloads.
|
|
@@ -49344,7 +49352,7 @@ var oauthState = {
|
|
|
49344
49352
|
verifyAndConsumeState: verifyAndConsumeState$1
|
|
49345
49353
|
};
|
|
49346
49354
|
const { createState, verifyAndConsumeState } = oauthState;
|
|
49347
|
-
function escapeHtml(str2) {
|
|
49355
|
+
function escapeHtml$1(str2) {
|
|
49348
49356
|
return String(str2 || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
49349
49357
|
}
|
|
49350
49358
|
function escapeJs(str2) {
|
|
@@ -49409,7 +49417,7 @@ var oauth$3 = {
|
|
|
49409
49417
|
</head>
|
|
49410
49418
|
<body>
|
|
49411
49419
|
<div class="error">[ERROR] OAuth Authorization Failed</div>
|
|
49412
|
-
<p>Error: ${escapeHtml(error2)}</p>
|
|
49420
|
+
<p>Error: ${escapeHtml$1(error2)}</p>
|
|
49413
49421
|
<p>You can close this window and try again.</p>
|
|
49414
49422
|
<script>
|
|
49415
49423
|
setTimeout(() => window.close(), 3000);
|
|
@@ -49520,7 +49528,7 @@ var oauth$3 = {
|
|
|
49520
49528
|
</head>
|
|
49521
49529
|
<body>
|
|
49522
49530
|
<div class="error">[ERROR] OAuth Authorization Failed</div>
|
|
49523
|
-
<p>Error: ${escapeHtml(error2)}</p>
|
|
49531
|
+
<p>Error: ${escapeHtml$1(error2)}</p>
|
|
49524
49532
|
<p>You can close this window and try again.</p>
|
|
49525
49533
|
<script>
|
|
49526
49534
|
setTimeout(() => window.close(), 3000);
|
|
@@ -49628,7 +49636,7 @@ var oauth$3 = {
|
|
|
49628
49636
|
</head>
|
|
49629
49637
|
<body>
|
|
49630
49638
|
<div class="error">[ERROR] OAuth Authorization Failed</div>
|
|
49631
|
-
<p>Error: ${escapeHtml(error2)}</p>
|
|
49639
|
+
<p>Error: ${escapeHtml$1(error2)}</p>
|
|
49632
49640
|
<p>You can close this window and try again.</p>
|
|
49633
49641
|
<script>
|
|
49634
49642
|
setTimeout(() => window.close(), 3000);
|
|
@@ -50711,6 +50719,52 @@ var emailDesigner$3 = ({ strapi: strapi2 }) => ({
|
|
|
50711
50719
|
const EMAIL_LOG_UID$1 = "plugin::magic-mail.email-log";
|
|
50712
50720
|
const EMAIL_EVENT_UID$1 = "plugin::magic-mail.email-event";
|
|
50713
50721
|
const EMAIL_ACCOUNT_UID$1 = "plugin::magic-mail.email-account";
|
|
50722
|
+
const escapeHtml = (value) => String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
50723
|
+
const renderTrackingFallbackHtml = (reason, fallbackUrl) => {
|
|
50724
|
+
const safeReason = escapeHtml(reason);
|
|
50725
|
+
const safeUrl = fallbackUrl ? escapeHtml(fallbackUrl) : "";
|
|
50726
|
+
const refreshMeta = fallbackUrl ? `<meta http-equiv="refresh" content="3;url=${safeUrl}">` : "";
|
|
50727
|
+
const manualLink = fallbackUrl ? `<p style="margin-top:24px;font-size:14px;color:#6b7280;">
|
|
50728
|
+
You will be redirected in a few seconds. If nothing happens,
|
|
50729
|
+
<a href="${safeUrl}" style="color:#4f46e5;">click here</a>.
|
|
50730
|
+
</p>` : `<p style="margin-top:24px;font-size:14px;color:#6b7280;">
|
|
50731
|
+
You can safely close this tab.
|
|
50732
|
+
</p>`;
|
|
50733
|
+
return `<!doctype html>
|
|
50734
|
+
<html lang="en">
|
|
50735
|
+
<head>
|
|
50736
|
+
<meta charset="utf-8">
|
|
50737
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
50738
|
+
${refreshMeta}
|
|
50739
|
+
<title>Link unavailable</title>
|
|
50740
|
+
<style>
|
|
50741
|
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background:#f9fafb; margin:0; padding:40px 20px; color:#111827; }
|
|
50742
|
+
.card { max-width: 480px; margin: 60px auto; background:#fff; border-radius: 12px; padding: 32px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); text-align:center; }
|
|
50743
|
+
h1 { font-size: 22px; margin: 0 0 12px; }
|
|
50744
|
+
p { font-size: 15px; line-height: 1.5; color:#374151; }
|
|
50745
|
+
</style>
|
|
50746
|
+
</head>
|
|
50747
|
+
<body>
|
|
50748
|
+
<main class="card">
|
|
50749
|
+
<h1>This link is no longer available</h1>
|
|
50750
|
+
<p>${safeReason}</p>
|
|
50751
|
+
${manualLink}
|
|
50752
|
+
</main>
|
|
50753
|
+
</body>
|
|
50754
|
+
</html>`;
|
|
50755
|
+
};
|
|
50756
|
+
const respondWithTrackingFallback = async (ctx, reason) => {
|
|
50757
|
+
let fallbackUrl = null;
|
|
50758
|
+
try {
|
|
50759
|
+
const settings = await strapi.plugin("magic-mail").service("plugin-settings").getSettings();
|
|
50760
|
+
fallbackUrl = settings?.trackingFallbackUrl || null;
|
|
50761
|
+
} catch (err) {
|
|
50762
|
+
strapi.log.debug(`[magic-mail] Could not load tracking fallback setting: ${err.message}`);
|
|
50763
|
+
}
|
|
50764
|
+
ctx.status = 410;
|
|
50765
|
+
ctx.type = "text/html; charset=utf-8";
|
|
50766
|
+
ctx.body = renderTrackingFallbackHtml(reason, fallbackUrl);
|
|
50767
|
+
};
|
|
50714
50768
|
var analytics$3 = ({ strapi: strapi2 }) => ({
|
|
50715
50769
|
/**
|
|
50716
50770
|
* Tracking pixel endpoint
|
|
@@ -50731,7 +50785,18 @@ var analytics$3 = ({ strapi: strapi2 }) => ({
|
|
|
50731
50785
|
ctx.body = pixel;
|
|
50732
50786
|
},
|
|
50733
50787
|
/**
|
|
50734
|
-
* Click tracking endpoint with open-redirect protection
|
|
50788
|
+
* Click tracking endpoint with open-redirect protection.
|
|
50789
|
+
*
|
|
50790
|
+
* Resolves the destination URL exclusively from the database — never
|
|
50791
|
+
* from query parameters — so the endpoint cannot be used as an open
|
|
50792
|
+
* redirect. When the URL is no longer resolvable (retention cleanup
|
|
50793
|
+
* deleted the row, the hash is wrong, the stored URL is malformed),
|
|
50794
|
+
* the end-user used to receive a Strapi JSON error envelope, which is
|
|
50795
|
+
* the single biggest UX regression in any tracking setup. Now the
|
|
50796
|
+
* user sees a branded HTML fallback page that either redirects to the
|
|
50797
|
+
* admin-configured `trackingFallbackUrl` or apologises and invites
|
|
50798
|
+
* them to close the tab.
|
|
50799
|
+
*
|
|
50735
50800
|
* GET /magic-mail/track/click/:emailId/:linkHash/:recipientHash
|
|
50736
50801
|
*/
|
|
50737
50802
|
async trackClick(ctx) {
|
|
@@ -50744,15 +50809,25 @@ var analytics$3 = ({ strapi: strapi2 }) => ({
|
|
|
50744
50809
|
strapi2.log.error("[magic-mail] Error getting original URL:", err.message);
|
|
50745
50810
|
}
|
|
50746
50811
|
if (!url) {
|
|
50747
|
-
return
|
|
50812
|
+
return respondWithTrackingFallback(
|
|
50813
|
+
ctx,
|
|
50814
|
+
"The page behind this link is no longer tracked. It may have been removed by our retention policy."
|
|
50815
|
+
);
|
|
50748
50816
|
}
|
|
50749
50817
|
try {
|
|
50750
50818
|
const parsed = new URL(url);
|
|
50751
50819
|
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
50752
|
-
|
|
50820
|
+
strapi2.log.warn(`[magic-mail] Blocked non-http(s) tracking URL for email ${emailId}`);
|
|
50821
|
+
return respondWithTrackingFallback(
|
|
50822
|
+
ctx,
|
|
50823
|
+
"This link points to an unsupported destination and cannot be opened for your safety."
|
|
50824
|
+
);
|
|
50753
50825
|
}
|
|
50754
50826
|
} catch {
|
|
50755
|
-
return
|
|
50827
|
+
return respondWithTrackingFallback(
|
|
50828
|
+
ctx,
|
|
50829
|
+
"This link is no longer valid."
|
|
50830
|
+
);
|
|
50756
50831
|
}
|
|
50757
50832
|
try {
|
|
50758
50833
|
await strapi2.plugin("magic-mail").service("analytics").recordClick(emailId, linkHash, recipientHash, url, ctx.request);
|
|
@@ -63354,7 +63429,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
|
|
|
63354
63429
|
return account;
|
|
63355
63430
|
}
|
|
63356
63431
|
});
|
|
63357
|
-
const version = "2.9.
|
|
63432
|
+
const version = "2.9.1";
|
|
63358
63433
|
const require$$2 = {
|
|
63359
63434
|
version
|
|
63360
63435
|
};
|
|
@@ -65238,7 +65313,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65238
65313
|
defaultFromName: null,
|
|
65239
65314
|
defaultFromEmail: null,
|
|
65240
65315
|
unsubscribeUrl: null,
|
|
65241
|
-
enableUnsubscribeHeader: true
|
|
65316
|
+
enableUnsubscribeHeader: true,
|
|
65317
|
+
trackingFallbackUrl: null
|
|
65242
65318
|
}
|
|
65243
65319
|
});
|
|
65244
65320
|
strapi2.log.info("[magic-mail] [SETTINGS] Created default plugin settings");
|
|
@@ -65253,7 +65329,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65253
65329
|
defaultFromName: null,
|
|
65254
65330
|
defaultFromEmail: null,
|
|
65255
65331
|
unsubscribeUrl: null,
|
|
65256
|
-
enableUnsubscribeHeader: true
|
|
65332
|
+
enableUnsubscribeHeader: true,
|
|
65333
|
+
trackingFallbackUrl: null
|
|
65257
65334
|
};
|
|
65258
65335
|
}
|
|
65259
65336
|
},
|
|
@@ -65269,7 +65346,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65269
65346
|
trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
|
|
65270
65347
|
defaultFromName: data.defaultFromName?.trim() || null,
|
|
65271
65348
|
defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
|
|
65272
|
-
unsubscribeUrl: data.unsubscribeUrl?.trim() || null
|
|
65349
|
+
unsubscribeUrl: data.unsubscribeUrl?.trim() || null,
|
|
65350
|
+
trackingFallbackUrl: data.trackingFallbackUrl?.trim() || null
|
|
65273
65351
|
};
|
|
65274
65352
|
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
|
65275
65353
|
if (settings) {
|
|
@@ -65287,7 +65365,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65287
65365
|
defaultFromName: sanitizedData.defaultFromName,
|
|
65288
65366
|
defaultFromEmail: sanitizedData.defaultFromEmail,
|
|
65289
65367
|
unsubscribeUrl: sanitizedData.unsubscribeUrl,
|
|
65290
|
-
enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true
|
|
65368
|
+
enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true,
|
|
65369
|
+
trackingFallbackUrl: sanitizedData.trackingFallbackUrl
|
|
65291
65370
|
}
|
|
65292
65371
|
});
|
|
65293
65372
|
strapi2.log.info("[magic-mail] [SETTINGS] Created plugin settings");
|
package/dist/server/index.mjs
CHANGED
|
@@ -971,6 +971,10 @@ const attributes = {
|
|
|
971
971
|
type: "boolean",
|
|
972
972
|
"default": true,
|
|
973
973
|
configurable: false
|
|
974
|
+
},
|
|
975
|
+
trackingFallbackUrl: {
|
|
976
|
+
type: "string",
|
|
977
|
+
configurable: false
|
|
974
978
|
}
|
|
975
979
|
};
|
|
976
980
|
const require$$7 = {
|
|
@@ -48848,7 +48852,11 @@ const schemas = {
|
|
|
48848
48852
|
defaultFromName: headerSafe.optional(),
|
|
48849
48853
|
defaultFromEmail: emailString.optional().or(z2.literal("")),
|
|
48850
48854
|
unsubscribeUrl: z2.string().url().optional().or(z2.literal("")),
|
|
48851
|
-
enableUnsubscribeHeader: z2.boolean().optional()
|
|
48855
|
+
enableUnsubscribeHeader: z2.boolean().optional(),
|
|
48856
|
+
// Where to redirect the recipient when a tracking link is no longer
|
|
48857
|
+
// resolvable (e.g. retention cleanup removed the row). If empty the
|
|
48858
|
+
// tracker renders a static HTML fallback page instead.
|
|
48859
|
+
trackingFallbackUrl: z2.string().url().optional().or(z2.literal(""))
|
|
48852
48860
|
}),
|
|
48853
48861
|
// ── Content-API send payloads ───────────────────────────────────────────
|
|
48854
48862
|
// Bounded attachments to prevent OOM from huge base64 payloads.
|
|
@@ -49308,7 +49316,7 @@ var oauthState = {
|
|
|
49308
49316
|
verifyAndConsumeState: verifyAndConsumeState$1
|
|
49309
49317
|
};
|
|
49310
49318
|
const { createState, verifyAndConsumeState } = oauthState;
|
|
49311
|
-
function escapeHtml(str2) {
|
|
49319
|
+
function escapeHtml$1(str2) {
|
|
49312
49320
|
return String(str2 || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
49313
49321
|
}
|
|
49314
49322
|
function escapeJs(str2) {
|
|
@@ -49373,7 +49381,7 @@ var oauth$3 = {
|
|
|
49373
49381
|
</head>
|
|
49374
49382
|
<body>
|
|
49375
49383
|
<div class="error">[ERROR] OAuth Authorization Failed</div>
|
|
49376
|
-
<p>Error: ${escapeHtml(error2)}</p>
|
|
49384
|
+
<p>Error: ${escapeHtml$1(error2)}</p>
|
|
49377
49385
|
<p>You can close this window and try again.</p>
|
|
49378
49386
|
<script>
|
|
49379
49387
|
setTimeout(() => window.close(), 3000);
|
|
@@ -49484,7 +49492,7 @@ var oauth$3 = {
|
|
|
49484
49492
|
</head>
|
|
49485
49493
|
<body>
|
|
49486
49494
|
<div class="error">[ERROR] OAuth Authorization Failed</div>
|
|
49487
|
-
<p>Error: ${escapeHtml(error2)}</p>
|
|
49495
|
+
<p>Error: ${escapeHtml$1(error2)}</p>
|
|
49488
49496
|
<p>You can close this window and try again.</p>
|
|
49489
49497
|
<script>
|
|
49490
49498
|
setTimeout(() => window.close(), 3000);
|
|
@@ -49592,7 +49600,7 @@ var oauth$3 = {
|
|
|
49592
49600
|
</head>
|
|
49593
49601
|
<body>
|
|
49594
49602
|
<div class="error">[ERROR] OAuth Authorization Failed</div>
|
|
49595
|
-
<p>Error: ${escapeHtml(error2)}</p>
|
|
49603
|
+
<p>Error: ${escapeHtml$1(error2)}</p>
|
|
49596
49604
|
<p>You can close this window and try again.</p>
|
|
49597
49605
|
<script>
|
|
49598
49606
|
setTimeout(() => window.close(), 3000);
|
|
@@ -50675,6 +50683,52 @@ var emailDesigner$3 = ({ strapi: strapi2 }) => ({
|
|
|
50675
50683
|
const EMAIL_LOG_UID$1 = "plugin::magic-mail.email-log";
|
|
50676
50684
|
const EMAIL_EVENT_UID$1 = "plugin::magic-mail.email-event";
|
|
50677
50685
|
const EMAIL_ACCOUNT_UID$1 = "plugin::magic-mail.email-account";
|
|
50686
|
+
const escapeHtml = (value) => String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
50687
|
+
const renderTrackingFallbackHtml = (reason, fallbackUrl) => {
|
|
50688
|
+
const safeReason = escapeHtml(reason);
|
|
50689
|
+
const safeUrl = fallbackUrl ? escapeHtml(fallbackUrl) : "";
|
|
50690
|
+
const refreshMeta = fallbackUrl ? `<meta http-equiv="refresh" content="3;url=${safeUrl}">` : "";
|
|
50691
|
+
const manualLink = fallbackUrl ? `<p style="margin-top:24px;font-size:14px;color:#6b7280;">
|
|
50692
|
+
You will be redirected in a few seconds. If nothing happens,
|
|
50693
|
+
<a href="${safeUrl}" style="color:#4f46e5;">click here</a>.
|
|
50694
|
+
</p>` : `<p style="margin-top:24px;font-size:14px;color:#6b7280;">
|
|
50695
|
+
You can safely close this tab.
|
|
50696
|
+
</p>`;
|
|
50697
|
+
return `<!doctype html>
|
|
50698
|
+
<html lang="en">
|
|
50699
|
+
<head>
|
|
50700
|
+
<meta charset="utf-8">
|
|
50701
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
50702
|
+
${refreshMeta}
|
|
50703
|
+
<title>Link unavailable</title>
|
|
50704
|
+
<style>
|
|
50705
|
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background:#f9fafb; margin:0; padding:40px 20px; color:#111827; }
|
|
50706
|
+
.card { max-width: 480px; margin: 60px auto; background:#fff; border-radius: 12px; padding: 32px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); text-align:center; }
|
|
50707
|
+
h1 { font-size: 22px; margin: 0 0 12px; }
|
|
50708
|
+
p { font-size: 15px; line-height: 1.5; color:#374151; }
|
|
50709
|
+
</style>
|
|
50710
|
+
</head>
|
|
50711
|
+
<body>
|
|
50712
|
+
<main class="card">
|
|
50713
|
+
<h1>This link is no longer available</h1>
|
|
50714
|
+
<p>${safeReason}</p>
|
|
50715
|
+
${manualLink}
|
|
50716
|
+
</main>
|
|
50717
|
+
</body>
|
|
50718
|
+
</html>`;
|
|
50719
|
+
};
|
|
50720
|
+
const respondWithTrackingFallback = async (ctx, reason) => {
|
|
50721
|
+
let fallbackUrl = null;
|
|
50722
|
+
try {
|
|
50723
|
+
const settings = await strapi.plugin("magic-mail").service("plugin-settings").getSettings();
|
|
50724
|
+
fallbackUrl = settings?.trackingFallbackUrl || null;
|
|
50725
|
+
} catch (err) {
|
|
50726
|
+
strapi.log.debug(`[magic-mail] Could not load tracking fallback setting: ${err.message}`);
|
|
50727
|
+
}
|
|
50728
|
+
ctx.status = 410;
|
|
50729
|
+
ctx.type = "text/html; charset=utf-8";
|
|
50730
|
+
ctx.body = renderTrackingFallbackHtml(reason, fallbackUrl);
|
|
50731
|
+
};
|
|
50678
50732
|
var analytics$3 = ({ strapi: strapi2 }) => ({
|
|
50679
50733
|
/**
|
|
50680
50734
|
* Tracking pixel endpoint
|
|
@@ -50695,7 +50749,18 @@ var analytics$3 = ({ strapi: strapi2 }) => ({
|
|
|
50695
50749
|
ctx.body = pixel;
|
|
50696
50750
|
},
|
|
50697
50751
|
/**
|
|
50698
|
-
* Click tracking endpoint with open-redirect protection
|
|
50752
|
+
* Click tracking endpoint with open-redirect protection.
|
|
50753
|
+
*
|
|
50754
|
+
* Resolves the destination URL exclusively from the database — never
|
|
50755
|
+
* from query parameters — so the endpoint cannot be used as an open
|
|
50756
|
+
* redirect. When the URL is no longer resolvable (retention cleanup
|
|
50757
|
+
* deleted the row, the hash is wrong, the stored URL is malformed),
|
|
50758
|
+
* the end-user used to receive a Strapi JSON error envelope, which is
|
|
50759
|
+
* the single biggest UX regression in any tracking setup. Now the
|
|
50760
|
+
* user sees a branded HTML fallback page that either redirects to the
|
|
50761
|
+
* admin-configured `trackingFallbackUrl` or apologises and invites
|
|
50762
|
+
* them to close the tab.
|
|
50763
|
+
*
|
|
50699
50764
|
* GET /magic-mail/track/click/:emailId/:linkHash/:recipientHash
|
|
50700
50765
|
*/
|
|
50701
50766
|
async trackClick(ctx) {
|
|
@@ -50708,15 +50773,25 @@ var analytics$3 = ({ strapi: strapi2 }) => ({
|
|
|
50708
50773
|
strapi2.log.error("[magic-mail] Error getting original URL:", err.message);
|
|
50709
50774
|
}
|
|
50710
50775
|
if (!url) {
|
|
50711
|
-
return
|
|
50776
|
+
return respondWithTrackingFallback(
|
|
50777
|
+
ctx,
|
|
50778
|
+
"The page behind this link is no longer tracked. It may have been removed by our retention policy."
|
|
50779
|
+
);
|
|
50712
50780
|
}
|
|
50713
50781
|
try {
|
|
50714
50782
|
const parsed = new URL(url);
|
|
50715
50783
|
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
50716
|
-
|
|
50784
|
+
strapi2.log.warn(`[magic-mail] Blocked non-http(s) tracking URL for email ${emailId}`);
|
|
50785
|
+
return respondWithTrackingFallback(
|
|
50786
|
+
ctx,
|
|
50787
|
+
"This link points to an unsupported destination and cannot be opened for your safety."
|
|
50788
|
+
);
|
|
50717
50789
|
}
|
|
50718
50790
|
} catch {
|
|
50719
|
-
return
|
|
50791
|
+
return respondWithTrackingFallback(
|
|
50792
|
+
ctx,
|
|
50793
|
+
"This link is no longer valid."
|
|
50794
|
+
);
|
|
50720
50795
|
}
|
|
50721
50796
|
try {
|
|
50722
50797
|
await strapi2.plugin("magic-mail").service("analytics").recordClick(emailId, linkHash, recipientHash, url, ctx.request);
|
|
@@ -63318,7 +63393,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
|
|
|
63318
63393
|
return account;
|
|
63319
63394
|
}
|
|
63320
63395
|
});
|
|
63321
|
-
const version = "2.9.
|
|
63396
|
+
const version = "2.9.1";
|
|
63322
63397
|
const require$$2 = {
|
|
63323
63398
|
version
|
|
63324
63399
|
};
|
|
@@ -65202,7 +65277,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65202
65277
|
defaultFromName: null,
|
|
65203
65278
|
defaultFromEmail: null,
|
|
65204
65279
|
unsubscribeUrl: null,
|
|
65205
|
-
enableUnsubscribeHeader: true
|
|
65280
|
+
enableUnsubscribeHeader: true,
|
|
65281
|
+
trackingFallbackUrl: null
|
|
65206
65282
|
}
|
|
65207
65283
|
});
|
|
65208
65284
|
strapi2.log.info("[magic-mail] [SETTINGS] Created default plugin settings");
|
|
@@ -65217,7 +65293,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65217
65293
|
defaultFromName: null,
|
|
65218
65294
|
defaultFromEmail: null,
|
|
65219
65295
|
unsubscribeUrl: null,
|
|
65220
|
-
enableUnsubscribeHeader: true
|
|
65296
|
+
enableUnsubscribeHeader: true,
|
|
65297
|
+
trackingFallbackUrl: null
|
|
65221
65298
|
};
|
|
65222
65299
|
}
|
|
65223
65300
|
},
|
|
@@ -65233,7 +65310,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65233
65310
|
trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
|
|
65234
65311
|
defaultFromName: data.defaultFromName?.trim() || null,
|
|
65235
65312
|
defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
|
|
65236
|
-
unsubscribeUrl: data.unsubscribeUrl?.trim() || null
|
|
65313
|
+
unsubscribeUrl: data.unsubscribeUrl?.trim() || null,
|
|
65314
|
+
trackingFallbackUrl: data.trackingFallbackUrl?.trim() || null
|
|
65237
65315
|
};
|
|
65238
65316
|
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
|
65239
65317
|
if (settings) {
|
|
@@ -65251,7 +65329,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
65251
65329
|
defaultFromName: sanitizedData.defaultFromName,
|
|
65252
65330
|
defaultFromEmail: sanitizedData.defaultFromEmail,
|
|
65253
65331
|
unsubscribeUrl: sanitizedData.unsubscribeUrl,
|
|
65254
|
-
enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true
|
|
65332
|
+
enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true,
|
|
65333
|
+
trackingFallbackUrl: sanitizedData.trackingFallbackUrl
|
|
65255
65334
|
}
|
|
65256
65335
|
});
|
|
65257
65336
|
strapi2.log.info("[magic-mail] [SETTINGS] Created plugin settings");
|
package/package.json
CHANGED