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.
@@ -4009,15 +4009,37 @@ var emailRouter$1 = ({ strapi: strapi2 }) => ({
4009
4009
  if (!templateData && data) {
4010
4010
  templateData = data;
4011
4011
  }
4012
- if (to && typeof to === "string") {
4013
- to = to.trim().toLowerCase();
4014
- }
4015
- if (from && typeof from === "string") {
4016
- from = from.trim();
4017
- }
4018
- if (replyTo && typeof replyTo === "string") {
4019
- replyTo = replyTo.trim();
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
- if (!emailRegex.test(to)) {
5086
- throw new Error(`Invalid recipient email format: ${to}`);
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.5";
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
- return crypto.createHash("sha256").update(`${emailId}-${recipient}-${process.env.APP_KEYS || "secret"}`).digest("hex").substring(0, 16);
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: data.to,
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({});
@@ -3999,15 +3999,37 @@ var emailRouter$1 = ({ strapi: strapi2 }) => ({
3999
3999
  if (!templateData && data) {
4000
4000
  templateData = data;
4001
4001
  }
4002
- if (to && typeof to === "string") {
4003
- to = to.trim().toLowerCase();
4004
- }
4005
- if (from && typeof from === "string") {
4006
- from = from.trim();
4007
- }
4008
- if (replyTo && typeof replyTo === "string") {
4009
- replyTo = replyTo.trim();
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
- if (!emailRegex.test(to)) {
5076
- throw new Error(`Invalid recipient email format: ${to}`);
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.5";
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
- return crypto.createHash("sha256").update(`${emailId}-${recipient}-${process.env.APP_KEYS || "secret"}`).digest("hex").substring(0, 16);
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: data.to,
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
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.6.6",
2
+ "version": "2.6.7",
3
3
  "keywords": [
4
4
  "strapi",
5
5
  "strapi-plugin",