strapi-plugin-magic-mail 2.6.5 → 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,6 +4009,37 @@ var emailRouter$1 = ({ strapi: strapi2 }) => ({
4009
4009
  if (!templateData && data) {
4010
4010
  templateData = data;
4011
4011
  }
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);
4012
4043
  if (skipLinkTracking) {
4013
4044
  strapi2.log.info(`[magic-mail] [SKIP-TRACK] skipLinkTracking=true received for email to: ${to}`);
4014
4045
  }
@@ -4275,7 +4306,7 @@ ${text || "Email delivery failed. Please check your email settings."}`;
4275
4306
  break;
4276
4307
  }
4277
4308
  if (matches) {
4278
- const account = accounts2.find((a) => a.name === rule.accountName);
4309
+ const account = accounts2.find((a) => a.name.toLowerCase() === rule.accountName.toLowerCase());
4279
4310
  if (account) {
4280
4311
  strapi2.log.info(`[magic-mail] [ROUTE] Routing rule matched: ${rule.name} -> ${account.name}`);
4281
4312
  return account;
@@ -5073,8 +5104,28 @@ ${text || "Email delivery failed. Please check your email settings."}`;
5073
5104
  validateEmailSecurity(emailData) {
5074
5105
  const { to, subject, html, text } = emailData;
5075
5106
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
5076
- if (!emailRegex.test(to)) {
5077
- 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
+ }
5078
5129
  }
5079
5130
  if (!subject || subject.trim().length === 0) {
5080
5131
  throw new Error("Email subject is required for security and deliverability");
@@ -5964,10 +6015,9 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
5964
6015
  // OAuth app credentials
5965
6016
  oauth: encryptedOAuth,
5966
6017
  // OAuth tokens
5967
- fromEmail: tokenData.email,
5968
- // [SUCCESS] Use email from Google, not from accountDetails
6018
+ fromEmail: tokenData.email ? tokenData.email.trim().toLowerCase() : tokenData.email,
5969
6019
  fromName: accountDetails.fromName || tokenData.email.split("@")[0],
5970
- replyTo: accountDetails.replyTo || tokenData.email,
6020
+ replyTo: (accountDetails.replyTo || tokenData.email || "").trim().toLowerCase(),
5971
6021
  isActive: true,
5972
6022
  isPrimary: accountDetails.isPrimary || false,
5973
6023
  priority: accountDetails.priority || 1,
@@ -5982,7 +6032,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
5982
6032
  return account;
5983
6033
  }
5984
6034
  });
5985
- const version = "2.6.4";
6035
+ const version = "2.6.6";
5986
6036
  const require$$2 = {
5987
6037
  version
5988
6038
  };
@@ -6992,18 +7042,20 @@ var analytics$1 = ({ strapi: strapi2 }) => ({
6992
7042
  * Generate secure hash for recipient (for tracking URLs)
6993
7043
  */
6994
7044
  generateRecipientHash(emailId, recipient) {
6995
- 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);
6996
7047
  },
6997
7048
  /**
6998
7049
  * Create email log entry
6999
7050
  */
7000
7051
  async createEmailLog(data) {
7001
7052
  const emailId = this.generateEmailId();
7053
+ const normalizedRecipient = data.to ? String(data.to).trim().toLowerCase() : data.to;
7002
7054
  const logEntry = await strapi2.documents(EMAIL_LOG_UID).create({
7003
7055
  data: {
7004
7056
  emailId,
7005
7057
  user: data.userId || null,
7006
- recipient: data.to,
7058
+ recipient: normalizedRecipient,
7007
7059
  recipientName: data.recipientName || null,
7008
7060
  subject: data.subject,
7009
7061
  templateId: data.templateId || null,
@@ -7868,7 +7920,7 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
7868
7920
  ...data,
7869
7921
  trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
7870
7922
  defaultFromName: data.defaultFromName?.trim() || null,
7871
- defaultFromEmail: data.defaultFromEmail?.trim() || null,
7923
+ defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
7872
7924
  unsubscribeUrl: data.unsubscribeUrl?.trim() || null
7873
7925
  };
7874
7926
  let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
@@ -3999,6 +3999,37 @@ var emailRouter$1 = ({ strapi: strapi2 }) => ({
3999
3999
  if (!templateData && data) {
4000
4000
  templateData = data;
4001
4001
  }
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);
4002
4033
  if (skipLinkTracking) {
4003
4034
  strapi2.log.info(`[magic-mail] [SKIP-TRACK] skipLinkTracking=true received for email to: ${to}`);
4004
4035
  }
@@ -4265,7 +4296,7 @@ ${text || "Email delivery failed. Please check your email settings."}`;
4265
4296
  break;
4266
4297
  }
4267
4298
  if (matches) {
4268
- const account = accounts2.find((a) => a.name === rule.accountName);
4299
+ const account = accounts2.find((a) => a.name.toLowerCase() === rule.accountName.toLowerCase());
4269
4300
  if (account) {
4270
4301
  strapi2.log.info(`[magic-mail] [ROUTE] Routing rule matched: ${rule.name} -> ${account.name}`);
4271
4302
  return account;
@@ -5063,8 +5094,28 @@ ${text || "Email delivery failed. Please check your email settings."}`;
5063
5094
  validateEmailSecurity(emailData) {
5064
5095
  const { to, subject, html, text } = emailData;
5065
5096
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
5066
- if (!emailRegex.test(to)) {
5067
- 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
+ }
5068
5119
  }
5069
5120
  if (!subject || subject.trim().length === 0) {
5070
5121
  throw new Error("Email subject is required for security and deliverability");
@@ -5954,10 +6005,9 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
5954
6005
  // OAuth app credentials
5955
6006
  oauth: encryptedOAuth,
5956
6007
  // OAuth tokens
5957
- fromEmail: tokenData.email,
5958
- // [SUCCESS] Use email from Google, not from accountDetails
6008
+ fromEmail: tokenData.email ? tokenData.email.trim().toLowerCase() : tokenData.email,
5959
6009
  fromName: accountDetails.fromName || tokenData.email.split("@")[0],
5960
- replyTo: accountDetails.replyTo || tokenData.email,
6010
+ replyTo: (accountDetails.replyTo || tokenData.email || "").trim().toLowerCase(),
5961
6011
  isActive: true,
5962
6012
  isPrimary: accountDetails.isPrimary || false,
5963
6013
  priority: accountDetails.priority || 1,
@@ -5972,7 +6022,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
5972
6022
  return account;
5973
6023
  }
5974
6024
  });
5975
- const version = "2.6.4";
6025
+ const version = "2.6.6";
5976
6026
  const require$$2 = {
5977
6027
  version
5978
6028
  };
@@ -6982,18 +7032,20 @@ var analytics$1 = ({ strapi: strapi2 }) => ({
6982
7032
  * Generate secure hash for recipient (for tracking URLs)
6983
7033
  */
6984
7034
  generateRecipientHash(emailId, recipient) {
6985
- 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);
6986
7037
  },
6987
7038
  /**
6988
7039
  * Create email log entry
6989
7040
  */
6990
7041
  async createEmailLog(data) {
6991
7042
  const emailId = this.generateEmailId();
7043
+ const normalizedRecipient = data.to ? String(data.to).trim().toLowerCase() : data.to;
6992
7044
  const logEntry = await strapi2.documents(EMAIL_LOG_UID).create({
6993
7045
  data: {
6994
7046
  emailId,
6995
7047
  user: data.userId || null,
6996
- recipient: data.to,
7048
+ recipient: normalizedRecipient,
6997
7049
  recipientName: data.recipientName || null,
6998
7050
  subject: data.subject,
6999
7051
  templateId: data.templateId || null,
@@ -7858,7 +7910,7 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
7858
7910
  ...data,
7859
7911
  trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
7860
7912
  defaultFromName: data.defaultFromName?.trim() || null,
7861
- defaultFromEmail: data.defaultFromEmail?.trim() || null,
7913
+ defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
7862
7914
  unsubscribeUrl: data.unsubscribeUrl?.trim() || null
7863
7915
  };
7864
7916
  let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.6.5",
2
+ "version": "2.6.7",
3
3
  "keywords": [
4
4
  "strapi",
5
5
  "strapi-plugin",