strapi-plugin-magic-mail 2.2.4 → 2.2.5

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 (70) hide show
  1. package/dist/server/index.js +1 -1
  2. package/dist/server/index.mjs +1 -1
  3. package/package.json +1 -3
  4. package/admin/jsconfig.json +0 -10
  5. package/admin/src/components/AddAccountModal.jsx +0 -1943
  6. package/admin/src/components/Initializer.jsx +0 -14
  7. package/admin/src/components/LicenseGuard.jsx +0 -475
  8. package/admin/src/components/PluginIcon.jsx +0 -5
  9. package/admin/src/hooks/useAuthRefresh.js +0 -44
  10. package/admin/src/hooks/useLicense.js +0 -158
  11. package/admin/src/index.js +0 -87
  12. package/admin/src/pages/Analytics.jsx +0 -762
  13. package/admin/src/pages/App.jsx +0 -111
  14. package/admin/src/pages/EmailDesigner/EditorPage.jsx +0 -1424
  15. package/admin/src/pages/EmailDesigner/TemplateList.jsx +0 -1807
  16. package/admin/src/pages/HomePage.jsx +0 -1170
  17. package/admin/src/pages/LicensePage.jsx +0 -430
  18. package/admin/src/pages/RoutingRules.jsx +0 -1141
  19. package/admin/src/pages/Settings.jsx +0 -603
  20. package/admin/src/pluginId.js +0 -3
  21. package/admin/src/translations/de.json +0 -71
  22. package/admin/src/translations/en.json +0 -70
  23. package/admin/src/translations/es.json +0 -71
  24. package/admin/src/translations/fr.json +0 -71
  25. package/admin/src/translations/pt.json +0 -71
  26. package/admin/src/utils/fetchWithRetry.js +0 -123
  27. package/admin/src/utils/getTranslation.js +0 -5
  28. package/admin/src/utils/theme.js +0 -85
  29. package/server/jsconfig.json +0 -10
  30. package/server/src/bootstrap.js +0 -157
  31. package/server/src/config/features.js +0 -260
  32. package/server/src/config/index.js +0 -9
  33. package/server/src/content-types/email-account/schema.json +0 -93
  34. package/server/src/content-types/email-event/index.js +0 -8
  35. package/server/src/content-types/email-event/schema.json +0 -57
  36. package/server/src/content-types/email-link/index.js +0 -8
  37. package/server/src/content-types/email-link/schema.json +0 -49
  38. package/server/src/content-types/email-log/index.js +0 -8
  39. package/server/src/content-types/email-log/schema.json +0 -106
  40. package/server/src/content-types/email-template/schema.json +0 -74
  41. package/server/src/content-types/email-template-version/schema.json +0 -60
  42. package/server/src/content-types/index.js +0 -33
  43. package/server/src/content-types/routing-rule/schema.json +0 -59
  44. package/server/src/controllers/accounts.js +0 -229
  45. package/server/src/controllers/analytics.js +0 -361
  46. package/server/src/controllers/controller.js +0 -26
  47. package/server/src/controllers/email-designer.js +0 -474
  48. package/server/src/controllers/index.js +0 -21
  49. package/server/src/controllers/license.js +0 -269
  50. package/server/src/controllers/oauth.js +0 -474
  51. package/server/src/controllers/routing-rules.js +0 -129
  52. package/server/src/controllers/test.js +0 -301
  53. package/server/src/destroy.js +0 -27
  54. package/server/src/index.js +0 -25
  55. package/server/src/middlewares/index.js +0 -3
  56. package/server/src/policies/index.js +0 -3
  57. package/server/src/register.js +0 -5
  58. package/server/src/routes/admin.js +0 -469
  59. package/server/src/routes/content-api.js +0 -37
  60. package/server/src/routes/index.js +0 -9
  61. package/server/src/services/account-manager.js +0 -329
  62. package/server/src/services/analytics.js +0 -512
  63. package/server/src/services/email-designer.js +0 -717
  64. package/server/src/services/email-router.js +0 -1446
  65. package/server/src/services/index.js +0 -17
  66. package/server/src/services/license-guard.js +0 -423
  67. package/server/src/services/oauth.js +0 -515
  68. package/server/src/services/service.js +0 -7
  69. package/server/src/utils/encryption.js +0 -81
  70. 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
- });