strapi-plugin-magic-mail 2.2.4 → 2.2.6

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.
Files changed (71) hide show
  1. package/README.md +0 -2
  2. package/dist/server/index.js +1 -1
  3. package/dist/server/index.mjs +1 -1
  4. package/package.json +1 -3
  5. package/admin/jsconfig.json +0 -10
  6. package/admin/src/components/AddAccountModal.jsx +0 -1943
  7. package/admin/src/components/Initializer.jsx +0 -14
  8. package/admin/src/components/LicenseGuard.jsx +0 -475
  9. package/admin/src/components/PluginIcon.jsx +0 -5
  10. package/admin/src/hooks/useAuthRefresh.js +0 -44
  11. package/admin/src/hooks/useLicense.js +0 -158
  12. package/admin/src/index.js +0 -87
  13. package/admin/src/pages/Analytics.jsx +0 -762
  14. package/admin/src/pages/App.jsx +0 -111
  15. package/admin/src/pages/EmailDesigner/EditorPage.jsx +0 -1424
  16. package/admin/src/pages/EmailDesigner/TemplateList.jsx +0 -1807
  17. package/admin/src/pages/HomePage.jsx +0 -1170
  18. package/admin/src/pages/LicensePage.jsx +0 -430
  19. package/admin/src/pages/RoutingRules.jsx +0 -1141
  20. package/admin/src/pages/Settings.jsx +0 -603
  21. package/admin/src/pluginId.js +0 -3
  22. package/admin/src/translations/de.json +0 -71
  23. package/admin/src/translations/en.json +0 -70
  24. package/admin/src/translations/es.json +0 -71
  25. package/admin/src/translations/fr.json +0 -71
  26. package/admin/src/translations/pt.json +0 -71
  27. package/admin/src/utils/fetchWithRetry.js +0 -123
  28. package/admin/src/utils/getTranslation.js +0 -5
  29. package/admin/src/utils/theme.js +0 -85
  30. package/server/jsconfig.json +0 -10
  31. package/server/src/bootstrap.js +0 -157
  32. package/server/src/config/features.js +0 -260
  33. package/server/src/config/index.js +0 -9
  34. package/server/src/content-types/email-account/schema.json +0 -93
  35. package/server/src/content-types/email-event/index.js +0 -8
  36. package/server/src/content-types/email-event/schema.json +0 -57
  37. package/server/src/content-types/email-link/index.js +0 -8
  38. package/server/src/content-types/email-link/schema.json +0 -49
  39. package/server/src/content-types/email-log/index.js +0 -8
  40. package/server/src/content-types/email-log/schema.json +0 -106
  41. package/server/src/content-types/email-template/schema.json +0 -74
  42. package/server/src/content-types/email-template-version/schema.json +0 -60
  43. package/server/src/content-types/index.js +0 -33
  44. package/server/src/content-types/routing-rule/schema.json +0 -59
  45. package/server/src/controllers/accounts.js +0 -229
  46. package/server/src/controllers/analytics.js +0 -361
  47. package/server/src/controllers/controller.js +0 -26
  48. package/server/src/controllers/email-designer.js +0 -474
  49. package/server/src/controllers/index.js +0 -21
  50. package/server/src/controllers/license.js +0 -269
  51. package/server/src/controllers/oauth.js +0 -474
  52. package/server/src/controllers/routing-rules.js +0 -129
  53. package/server/src/controllers/test.js +0 -301
  54. package/server/src/destroy.js +0 -27
  55. package/server/src/index.js +0 -25
  56. package/server/src/middlewares/index.js +0 -3
  57. package/server/src/policies/index.js +0 -3
  58. package/server/src/register.js +0 -5
  59. package/server/src/routes/admin.js +0 -469
  60. package/server/src/routes/content-api.js +0 -37
  61. package/server/src/routes/index.js +0 -9
  62. package/server/src/services/account-manager.js +0 -329
  63. package/server/src/services/analytics.js +0 -512
  64. package/server/src/services/email-designer.js +0 -717
  65. package/server/src/services/email-router.js +0 -1446
  66. package/server/src/services/index.js +0 -17
  67. package/server/src/services/license-guard.js +0 -423
  68. package/server/src/services/oauth.js +0 -515
  69. package/server/src/services/service.js +0 -7
  70. package/server/src/utils/encryption.js +0 -81
  71. package/server/src/utils/logger.js +0 -84
@@ -1,329 +0,0 @@
1
- 'use strict';
2
-
3
- const { encryptCredentials, decryptCredentials } = require('../utils/encryption');
4
-
5
- /**
6
- * Account Manager Service
7
- * Manages email accounts (create, update, test, delete)
8
- * [SUCCESS] Migrated to strapi.documents() API (Strapi v5 Best Practice)
9
- */
10
-
11
- const EMAIL_ACCOUNT_UID = 'plugin::magic-mail.email-account';
12
-
13
- module.exports = ({ strapi }) => ({
14
- /**
15
- * Resolves account ID to documentId (handles both numeric id and documentId)
16
- * @param {string|number} idOrDocumentId - Either numeric id or documentId
17
- * @returns {Promise<string|null>} The documentId or null if not found
18
- */
19
- async resolveDocumentId(idOrDocumentId) {
20
- // If it looks like a documentId (not purely numeric), use directly
21
- if (idOrDocumentId && !/^\d+$/.test(String(idOrDocumentId))) {
22
- return String(idOrDocumentId);
23
- }
24
-
25
- // Otherwise, find by numeric id
26
- const accounts = await strapi.documents(EMAIL_ACCOUNT_UID).findMany({
27
- filters: { id: Number(idOrDocumentId) },
28
- fields: ['documentId'],
29
- limit: 1,
30
- });
31
-
32
- return accounts.length > 0 ? accounts[0].documentId : null;
33
- },
34
-
35
- /**
36
- * Create new email account
37
- */
38
- async createAccount(accountData) {
39
- const {
40
- name,
41
- provider,
42
- config,
43
- fromEmail,
44
- fromName,
45
- replyTo,
46
- isPrimary = false,
47
- priority = 1,
48
- dailyLimit = 0,
49
- hourlyLimit = 0,
50
- } = accountData;
51
-
52
- console.log('create account', accountData);
53
-
54
- // Encrypt sensitive config data
55
- const encryptedConfig = encryptCredentials(config);
56
-
57
- // If this is primary, unset other primaries
58
- if (isPrimary) {
59
- await this.unsetAllPrimary();
60
- }
61
-
62
- const account = await strapi.documents(EMAIL_ACCOUNT_UID).create({
63
- data: {
64
- name,
65
- provider,
66
- config: encryptedConfig,
67
- fromEmail,
68
- fromName,
69
- replyTo,
70
- isPrimary,
71
- priority,
72
- dailyLimit,
73
- hourlyLimit,
74
- isActive: true,
75
- emailsSentToday: 0,
76
- emailsSentThisHour: 0,
77
- totalEmailsSent: 0,
78
- },
79
- });
80
-
81
- strapi.log.info(`[magic-mail] [SUCCESS] Email account created: ${name}`);
82
-
83
- return account;
84
- },
85
-
86
- /**
87
- * Update email account
88
- */
89
- async updateAccount(idOrDocumentId, accountData) {
90
- const documentId = await this.resolveDocumentId(idOrDocumentId);
91
- if (!documentId) {
92
- throw new Error('Account not found');
93
- }
94
-
95
- const existingAccount = await strapi.documents(EMAIL_ACCOUNT_UID).findOne({
96
- documentId,
97
- });
98
-
99
- if (!existingAccount) {
100
- throw new Error('Account not found');
101
- }
102
-
103
- const {
104
- name,
105
- description,
106
- provider,
107
- config,
108
- fromEmail,
109
- fromName,
110
- replyTo,
111
- isActive,
112
- isPrimary,
113
- priority,
114
- dailyLimit,
115
- hourlyLimit,
116
- } = accountData;
117
-
118
- // Encrypt sensitive config data
119
- const encryptedConfig = encryptCredentials(config);
120
-
121
- // If this is being set to primary, unset other primaries
122
- if (isPrimary && !existingAccount.isPrimary) {
123
- await this.unsetAllPrimary();
124
- }
125
-
126
- const updatedAccount = await strapi.documents(EMAIL_ACCOUNT_UID).update({
127
- documentId,
128
- data: {
129
- name,
130
- description,
131
- provider,
132
- config: encryptedConfig,
133
- fromEmail,
134
- fromName,
135
- replyTo,
136
- isActive,
137
- isPrimary,
138
- priority,
139
- dailyLimit,
140
- hourlyLimit,
141
- },
142
- });
143
-
144
- strapi.log.info(`[magic-mail] [SUCCESS] Email account updated: ${name} (Active: ${isActive})`);
145
-
146
- return updatedAccount;
147
- },
148
-
149
- /**
150
- * Test email account
151
- */
152
- async testAccount(idOrDocumentId, testEmail, testOptions = {}) {
153
- const documentId = await this.resolveDocumentId(idOrDocumentId);
154
- if (!documentId) {
155
- throw new Error('Account not found');
156
- }
157
-
158
- const account = await strapi.documents(EMAIL_ACCOUNT_UID).findOne({
159
- documentId,
160
- });
161
-
162
- if (!account) {
163
- throw new Error('Account not found');
164
- }
165
-
166
- // Use provided test email or default to account's own email
167
- const recipient = testEmail || account.fromEmail;
168
-
169
- const emailRouter = strapi.plugin('magic-mail').service('email-router');
170
-
171
- // Extract test options
172
- const {
173
- priority = 'normal',
174
- type = 'transactional',
175
- unsubscribeUrl = null,
176
- } = testOptions;
177
-
178
- try {
179
- await emailRouter.send({
180
- to: recipient,
181
- from: account.fromEmail,
182
- subject: 'MagicMail Test Email',
183
- text: `This is a test email from MagicMail account: ${account.name}\n\nPriority: ${priority}\nType: ${type}\n\nProvider: ${account.provider}\nFrom: ${account.fromEmail}\n\nIf you receive this, your email account is configured correctly!`,
184
- html: `
185
- <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
186
- <h2 style="color: #0EA5E9;">MagicMail Test Email</h2>
187
- <p>This is a test email from account: <strong>${account.name}</strong></p>
188
-
189
- <div style="background: #F0F9FF; border: 1px solid #0EA5E9; border-radius: 8px; padding: 15px; margin: 20px 0;">
190
- <h3 style="margin-top: 0; color: #0369A1;">Test Configuration</h3>
191
- <ul style="margin: 10px 0; padding-left: 20px;">
192
- <li><strong>Priority:</strong> ${priority}</li>
193
- <li><strong>Type:</strong> ${type}</li>
194
- <li><strong>Provider:</strong> ${account.provider}</li>
195
- <li><strong>From:</strong> ${account.fromEmail}</li>
196
- ${unsubscribeUrl ? `<li><strong>Unsubscribe URL:</strong> ${unsubscribeUrl}</li>` : ''}
197
- </ul>
198
- </div>
199
-
200
- <div style="background: #DCFCE7; border: 1px solid #22C55E; border-radius: 8px; padding: 15px; margin: 20px 0;">
201
- <h3 style="margin-top: 0; color: #15803D;">Security Features Active</h3>
202
- <ul style="margin: 10px 0; padding-left: 20px;">
203
- <li>TLS/SSL Encryption enforced</li>
204
- <li>Email content validated</li>
205
- <li>Proper headers included</li>
206
- <li>Message-ID generated</li>
207
- ${type === 'marketing' && unsubscribeUrl ? '<li>List-Unsubscribe header added (GDPR/CAN-SPAM)</li>' : ''}
208
- </ul>
209
- </div>
210
-
211
- <p style="color: #6B7280; font-size: 14px; margin-top: 30px;">
212
- Sent at: ${new Date().toLocaleString()}<br>
213
- Via: MagicMail Email Router<br>
214
- Version: 1.0
215
- </p>
216
-
217
- ${unsubscribeUrl ? `<p style="text-align: center; margin-top: 40px; padding-top: 20px; border-top: 1px solid #E5E7EB;"><a href="${unsubscribeUrl}" style="color: #6B7280; font-size: 12px;">Unsubscribe</a></p>` : ''}
218
- </div>
219
- `,
220
- accountName: account.name,
221
- priority,
222
- type,
223
- unsubscribeUrl,
224
- });
225
-
226
- return {
227
- success: true,
228
- message: `Test email sent successfully to ${recipient}`,
229
- testConfig: { priority, type, unsubscribeUrl: !!unsubscribeUrl }
230
- };
231
- } catch (error) {
232
- return { success: false, message: error.message };
233
- }
234
- },
235
-
236
- /**
237
- * Get all accounts
238
- */
239
- async getAllAccounts() {
240
- const accounts = await strapi.documents(EMAIL_ACCOUNT_UID).findMany({
241
- sort: [{ priority: 'desc' }],
242
- });
243
-
244
- // Don't return encrypted config in list
245
- return accounts.map(account => ({
246
- ...account,
247
- config: account.config ? '***encrypted***' : null,
248
- }));
249
- },
250
-
251
- /**
252
- * Get single account with decrypted config (for editing)
253
- */
254
- async getAccountWithDecryptedConfig(idOrDocumentId) {
255
- const documentId = await this.resolveDocumentId(idOrDocumentId);
256
- if (!documentId) {
257
- throw new Error('Account not found');
258
- }
259
-
260
- const account = await strapi.documents(EMAIL_ACCOUNT_UID).findOne({
261
- documentId,
262
- });
263
-
264
- if (!account) {
265
- throw new Error('Account not found');
266
- }
267
-
268
- // Decrypt the config for editing
269
- const decryptedConfig = account.config ? decryptCredentials(account.config) : {};
270
-
271
- return {
272
- ...account,
273
- config: decryptedConfig,
274
- };
275
- },
276
-
277
- /**
278
- * Delete account
279
- */
280
- async deleteAccount(idOrDocumentId) {
281
- const documentId = await this.resolveDocumentId(idOrDocumentId);
282
- if (!documentId) {
283
- throw new Error('Account not found');
284
- }
285
-
286
- await strapi.documents(EMAIL_ACCOUNT_UID).delete({ documentId });
287
- strapi.log.info(`[magic-mail] Account deleted: ${documentId}`);
288
- },
289
-
290
- /**
291
- * Unset all primary flags
292
- */
293
- async unsetAllPrimary() {
294
- const accounts = await strapi.documents(EMAIL_ACCOUNT_UID).findMany({
295
- filters: { isPrimary: true },
296
- });
297
-
298
- for (const account of accounts) {
299
- await strapi.documents(EMAIL_ACCOUNT_UID).update({
300
- documentId: account.documentId,
301
- data: { isPrimary: false },
302
- });
303
- }
304
- },
305
-
306
- /**
307
- * Reset daily/hourly counters (called by cron)
308
- */
309
- async resetCounters(type = 'daily') {
310
- const accounts = await strapi.documents(EMAIL_ACCOUNT_UID).findMany({});
311
-
312
- for (const account of accounts) {
313
- const updateData = {};
314
-
315
- if (type === 'daily') {
316
- updateData.emailsSentToday = 0;
317
- } else if (type === 'hourly') {
318
- updateData.emailsSentThisHour = 0;
319
- }
320
-
321
- await strapi.documents(EMAIL_ACCOUNT_UID).update({
322
- documentId: account.documentId,
323
- data: updateData,
324
- });
325
- }
326
-
327
- strapi.log.info(`[magic-mail] [SUCCESS] ${type} counters reset`);
328
- },
329
- });