strapi-plugin-magic-mail 2.6.6 → 2.6.7
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 +62 -19
- package/dist/server/index.mjs +62 -19
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -4009,15 +4009,37 @@ var emailRouter$1 = ({ strapi: strapi2 }) => ({
|
|
|
4009
4009
|
if (!templateData && data) {
|
|
4010
4010
|
templateData = data;
|
|
4011
4011
|
}
|
|
4012
|
-
if (to
|
|
4013
|
-
|
|
4014
|
-
}
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4012
|
+
if (!to || typeof to === "string" && to.trim().length === 0) {
|
|
4013
|
+
throw new Error("Recipient email address (to) is required");
|
|
4014
|
+
}
|
|
4015
|
+
const normalizeAddr = (addr) => {
|
|
4016
|
+
if (!addr) return addr;
|
|
4017
|
+
if (typeof addr === "string") {
|
|
4018
|
+
if (addr.includes("<") && addr.includes(">")) {
|
|
4019
|
+
return addr.replace(/<([^>]+)>/, (_, email) => `<${email.trim().toLowerCase()}>`);
|
|
4020
|
+
}
|
|
4021
|
+
return addr.trim().toLowerCase();
|
|
4022
|
+
}
|
|
4023
|
+
return addr;
|
|
4024
|
+
};
|
|
4025
|
+
const normalizeAddrs = (val) => {
|
|
4026
|
+
if (!val) return val;
|
|
4027
|
+
if (Array.isArray(val)) {
|
|
4028
|
+
return val.map((a) => normalizeAddr(a));
|
|
4029
|
+
}
|
|
4030
|
+
if (typeof val === "string" && val.includes(",")) {
|
|
4031
|
+
return val.split(",").map((a) => normalizeAddr(a)).join(", ");
|
|
4032
|
+
}
|
|
4033
|
+
return normalizeAddr(val);
|
|
4034
|
+
};
|
|
4035
|
+
to = normalizeAddrs(to);
|
|
4036
|
+
from = normalizeAddr(from);
|
|
4037
|
+
replyTo = normalizeAddr(replyTo);
|
|
4038
|
+
emailData.to = to;
|
|
4039
|
+
emailData.from = from;
|
|
4040
|
+
emailData.replyTo = replyTo;
|
|
4041
|
+
if (emailData.cc) emailData.cc = normalizeAddrs(emailData.cc);
|
|
4042
|
+
if (emailData.bcc) emailData.bcc = normalizeAddrs(emailData.bcc);
|
|
4021
4043
|
if (skipLinkTracking) {
|
|
4022
4044
|
strapi2.log.info(`[magic-mail] [SKIP-TRACK] skipLinkTracking=true received for email to: ${to}`);
|
|
4023
4045
|
}
|
|
@@ -4284,7 +4306,7 @@ ${text || "Email delivery failed. Please check your email settings."}`;
|
|
|
4284
4306
|
break;
|
|
4285
4307
|
}
|
|
4286
4308
|
if (matches) {
|
|
4287
|
-
const account = accounts2.find((a) => a.name === rule.accountName);
|
|
4309
|
+
const account = accounts2.find((a) => a.name.toLowerCase() === rule.accountName.toLowerCase());
|
|
4288
4310
|
if (account) {
|
|
4289
4311
|
strapi2.log.info(`[magic-mail] [ROUTE] Routing rule matched: ${rule.name} -> ${account.name}`);
|
|
4290
4312
|
return account;
|
|
@@ -5082,8 +5104,28 @@ ${text || "Email delivery failed. Please check your email settings."}`;
|
|
|
5082
5104
|
validateEmailSecurity(emailData) {
|
|
5083
5105
|
const { to, subject, html, text } = emailData;
|
|
5084
5106
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
5085
|
-
|
|
5086
|
-
|
|
5107
|
+
const extractEmail = (addr) => {
|
|
5108
|
+
if (!addr || typeof addr !== "string") return "";
|
|
5109
|
+
if (addr.includes("<")) {
|
|
5110
|
+
const match = addr.match(/<([^>]+)>/);
|
|
5111
|
+
return match ? match[1].trim() : addr.trim();
|
|
5112
|
+
}
|
|
5113
|
+
return addr.trim();
|
|
5114
|
+
};
|
|
5115
|
+
const validateAddr = (addr) => emailRegex.test(extractEmail(addr));
|
|
5116
|
+
if (Array.isArray(to)) {
|
|
5117
|
+
for (const addr of to) {
|
|
5118
|
+
if (!validateAddr(addr)) {
|
|
5119
|
+
throw new Error(`Invalid recipient email format: ${addr}`);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
} else if (typeof to === "string") {
|
|
5123
|
+
const addresses = to.includes(",") ? to.split(",") : [to];
|
|
5124
|
+
for (const addr of addresses) {
|
|
5125
|
+
if (!validateAddr(addr.trim())) {
|
|
5126
|
+
throw new Error(`Invalid recipient email format: ${addr.trim()}`);
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5087
5129
|
}
|
|
5088
5130
|
if (!subject || subject.trim().length === 0) {
|
|
5089
5131
|
throw new Error("Email subject is required for security and deliverability");
|
|
@@ -5973,10 +6015,9 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
|
|
|
5973
6015
|
// OAuth app credentials
|
|
5974
6016
|
oauth: encryptedOAuth,
|
|
5975
6017
|
// OAuth tokens
|
|
5976
|
-
fromEmail: tokenData.email,
|
|
5977
|
-
// [SUCCESS] Use email from Google, not from accountDetails
|
|
6018
|
+
fromEmail: tokenData.email ? tokenData.email.trim().toLowerCase() : tokenData.email,
|
|
5978
6019
|
fromName: accountDetails.fromName || tokenData.email.split("@")[0],
|
|
5979
|
-
replyTo: accountDetails.replyTo || tokenData.email,
|
|
6020
|
+
replyTo: (accountDetails.replyTo || tokenData.email || "").trim().toLowerCase(),
|
|
5980
6021
|
isActive: true,
|
|
5981
6022
|
isPrimary: accountDetails.isPrimary || false,
|
|
5982
6023
|
priority: accountDetails.priority || 1,
|
|
@@ -5991,7 +6032,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
|
|
|
5991
6032
|
return account;
|
|
5992
6033
|
}
|
|
5993
6034
|
});
|
|
5994
|
-
const version = "2.6.
|
|
6035
|
+
const version = "2.6.6";
|
|
5995
6036
|
const require$$2 = {
|
|
5996
6037
|
version
|
|
5997
6038
|
};
|
|
@@ -7001,18 +7042,20 @@ var analytics$1 = ({ strapi: strapi2 }) => ({
|
|
|
7001
7042
|
* Generate secure hash for recipient (for tracking URLs)
|
|
7002
7043
|
*/
|
|
7003
7044
|
generateRecipientHash(emailId, recipient) {
|
|
7004
|
-
|
|
7045
|
+
const normalized = (recipient || "").trim().toLowerCase();
|
|
7046
|
+
return crypto.createHash("sha256").update(`${emailId}-${normalized}-${process.env.APP_KEYS || "secret"}`).digest("hex").substring(0, 16);
|
|
7005
7047
|
},
|
|
7006
7048
|
/**
|
|
7007
7049
|
* Create email log entry
|
|
7008
7050
|
*/
|
|
7009
7051
|
async createEmailLog(data) {
|
|
7010
7052
|
const emailId = this.generateEmailId();
|
|
7053
|
+
const normalizedRecipient = data.to ? String(data.to).trim().toLowerCase() : data.to;
|
|
7011
7054
|
const logEntry = await strapi2.documents(EMAIL_LOG_UID).create({
|
|
7012
7055
|
data: {
|
|
7013
7056
|
emailId,
|
|
7014
7057
|
user: data.userId || null,
|
|
7015
|
-
recipient:
|
|
7058
|
+
recipient: normalizedRecipient,
|
|
7016
7059
|
recipientName: data.recipientName || null,
|
|
7017
7060
|
subject: data.subject,
|
|
7018
7061
|
templateId: data.templateId || null,
|
|
@@ -7877,7 +7920,7 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
7877
7920
|
...data,
|
|
7878
7921
|
trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
|
|
7879
7922
|
defaultFromName: data.defaultFromName?.trim() || null,
|
|
7880
|
-
defaultFromEmail: data.defaultFromEmail?.trim() || null,
|
|
7923
|
+
defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
|
|
7881
7924
|
unsubscribeUrl: data.unsubscribeUrl?.trim() || null
|
|
7882
7925
|
};
|
|
7883
7926
|
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
package/dist/server/index.mjs
CHANGED
|
@@ -3999,15 +3999,37 @@ var emailRouter$1 = ({ strapi: strapi2 }) => ({
|
|
|
3999
3999
|
if (!templateData && data) {
|
|
4000
4000
|
templateData = data;
|
|
4001
4001
|
}
|
|
4002
|
-
if (to
|
|
4003
|
-
|
|
4004
|
-
}
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4002
|
+
if (!to || typeof to === "string" && to.trim().length === 0) {
|
|
4003
|
+
throw new Error("Recipient email address (to) is required");
|
|
4004
|
+
}
|
|
4005
|
+
const normalizeAddr = (addr) => {
|
|
4006
|
+
if (!addr) return addr;
|
|
4007
|
+
if (typeof addr === "string") {
|
|
4008
|
+
if (addr.includes("<") && addr.includes(">")) {
|
|
4009
|
+
return addr.replace(/<([^>]+)>/, (_, email) => `<${email.trim().toLowerCase()}>`);
|
|
4010
|
+
}
|
|
4011
|
+
return addr.trim().toLowerCase();
|
|
4012
|
+
}
|
|
4013
|
+
return addr;
|
|
4014
|
+
};
|
|
4015
|
+
const normalizeAddrs = (val) => {
|
|
4016
|
+
if (!val) return val;
|
|
4017
|
+
if (Array.isArray(val)) {
|
|
4018
|
+
return val.map((a) => normalizeAddr(a));
|
|
4019
|
+
}
|
|
4020
|
+
if (typeof val === "string" && val.includes(",")) {
|
|
4021
|
+
return val.split(",").map((a) => normalizeAddr(a)).join(", ");
|
|
4022
|
+
}
|
|
4023
|
+
return normalizeAddr(val);
|
|
4024
|
+
};
|
|
4025
|
+
to = normalizeAddrs(to);
|
|
4026
|
+
from = normalizeAddr(from);
|
|
4027
|
+
replyTo = normalizeAddr(replyTo);
|
|
4028
|
+
emailData.to = to;
|
|
4029
|
+
emailData.from = from;
|
|
4030
|
+
emailData.replyTo = replyTo;
|
|
4031
|
+
if (emailData.cc) emailData.cc = normalizeAddrs(emailData.cc);
|
|
4032
|
+
if (emailData.bcc) emailData.bcc = normalizeAddrs(emailData.bcc);
|
|
4011
4033
|
if (skipLinkTracking) {
|
|
4012
4034
|
strapi2.log.info(`[magic-mail] [SKIP-TRACK] skipLinkTracking=true received for email to: ${to}`);
|
|
4013
4035
|
}
|
|
@@ -4274,7 +4296,7 @@ ${text || "Email delivery failed. Please check your email settings."}`;
|
|
|
4274
4296
|
break;
|
|
4275
4297
|
}
|
|
4276
4298
|
if (matches) {
|
|
4277
|
-
const account = accounts2.find((a) => a.name === rule.accountName);
|
|
4299
|
+
const account = accounts2.find((a) => a.name.toLowerCase() === rule.accountName.toLowerCase());
|
|
4278
4300
|
if (account) {
|
|
4279
4301
|
strapi2.log.info(`[magic-mail] [ROUTE] Routing rule matched: ${rule.name} -> ${account.name}`);
|
|
4280
4302
|
return account;
|
|
@@ -5072,8 +5094,28 @@ ${text || "Email delivery failed. Please check your email settings."}`;
|
|
|
5072
5094
|
validateEmailSecurity(emailData) {
|
|
5073
5095
|
const { to, subject, html, text } = emailData;
|
|
5074
5096
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
5075
|
-
|
|
5076
|
-
|
|
5097
|
+
const extractEmail = (addr) => {
|
|
5098
|
+
if (!addr || typeof addr !== "string") return "";
|
|
5099
|
+
if (addr.includes("<")) {
|
|
5100
|
+
const match = addr.match(/<([^>]+)>/);
|
|
5101
|
+
return match ? match[1].trim() : addr.trim();
|
|
5102
|
+
}
|
|
5103
|
+
return addr.trim();
|
|
5104
|
+
};
|
|
5105
|
+
const validateAddr = (addr) => emailRegex.test(extractEmail(addr));
|
|
5106
|
+
if (Array.isArray(to)) {
|
|
5107
|
+
for (const addr of to) {
|
|
5108
|
+
if (!validateAddr(addr)) {
|
|
5109
|
+
throw new Error(`Invalid recipient email format: ${addr}`);
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
} else if (typeof to === "string") {
|
|
5113
|
+
const addresses = to.includes(",") ? to.split(",") : [to];
|
|
5114
|
+
for (const addr of addresses) {
|
|
5115
|
+
if (!validateAddr(addr.trim())) {
|
|
5116
|
+
throw new Error(`Invalid recipient email format: ${addr.trim()}`);
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5077
5119
|
}
|
|
5078
5120
|
if (!subject || subject.trim().length === 0) {
|
|
5079
5121
|
throw new Error("Email subject is required for security and deliverability");
|
|
@@ -5963,10 +6005,9 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
|
|
|
5963
6005
|
// OAuth app credentials
|
|
5964
6006
|
oauth: encryptedOAuth,
|
|
5965
6007
|
// OAuth tokens
|
|
5966
|
-
fromEmail: tokenData.email,
|
|
5967
|
-
// [SUCCESS] Use email from Google, not from accountDetails
|
|
6008
|
+
fromEmail: tokenData.email ? tokenData.email.trim().toLowerCase() : tokenData.email,
|
|
5968
6009
|
fromName: accountDetails.fromName || tokenData.email.split("@")[0],
|
|
5969
|
-
replyTo: accountDetails.replyTo || tokenData.email,
|
|
6010
|
+
replyTo: (accountDetails.replyTo || tokenData.email || "").trim().toLowerCase(),
|
|
5970
6011
|
isActive: true,
|
|
5971
6012
|
isPrimary: accountDetails.isPrimary || false,
|
|
5972
6013
|
priority: accountDetails.priority || 1,
|
|
@@ -5981,7 +6022,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
|
|
|
5981
6022
|
return account;
|
|
5982
6023
|
}
|
|
5983
6024
|
});
|
|
5984
|
-
const version = "2.6.
|
|
6025
|
+
const version = "2.6.6";
|
|
5985
6026
|
const require$$2 = {
|
|
5986
6027
|
version
|
|
5987
6028
|
};
|
|
@@ -6991,18 +7032,20 @@ var analytics$1 = ({ strapi: strapi2 }) => ({
|
|
|
6991
7032
|
* Generate secure hash for recipient (for tracking URLs)
|
|
6992
7033
|
*/
|
|
6993
7034
|
generateRecipientHash(emailId, recipient) {
|
|
6994
|
-
|
|
7035
|
+
const normalized = (recipient || "").trim().toLowerCase();
|
|
7036
|
+
return crypto.createHash("sha256").update(`${emailId}-${normalized}-${process.env.APP_KEYS || "secret"}`).digest("hex").substring(0, 16);
|
|
6995
7037
|
},
|
|
6996
7038
|
/**
|
|
6997
7039
|
* Create email log entry
|
|
6998
7040
|
*/
|
|
6999
7041
|
async createEmailLog(data) {
|
|
7000
7042
|
const emailId = this.generateEmailId();
|
|
7043
|
+
const normalizedRecipient = data.to ? String(data.to).trim().toLowerCase() : data.to;
|
|
7001
7044
|
const logEntry = await strapi2.documents(EMAIL_LOG_UID).create({
|
|
7002
7045
|
data: {
|
|
7003
7046
|
emailId,
|
|
7004
7047
|
user: data.userId || null,
|
|
7005
|
-
recipient:
|
|
7048
|
+
recipient: normalizedRecipient,
|
|
7006
7049
|
recipientName: data.recipientName || null,
|
|
7007
7050
|
subject: data.subject,
|
|
7008
7051
|
templateId: data.templateId || null,
|
|
@@ -7867,7 +7910,7 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
|
|
|
7867
7910
|
...data,
|
|
7868
7911
|
trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
|
|
7869
7912
|
defaultFromName: data.defaultFromName?.trim() || null,
|
|
7870
|
-
defaultFromEmail: data.defaultFromEmail?.trim() || null,
|
|
7913
|
+
defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
|
|
7871
7914
|
unsubscribeUrl: data.unsubscribeUrl?.trim() || null
|
|
7872
7915
|
};
|
|
7873
7916
|
let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
|
package/package.json
CHANGED