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,361 +0,0 @@
1
- /**
2
- * Analytics Controller
3
- * Handles tracking endpoints and analytics API
4
- * [SUCCESS] Migrated to strapi.documents() API (Strapi v5 Best Practice)
5
- */
6
-
7
- 'use strict';
8
-
9
- const EMAIL_LOG_UID = 'plugin::magic-mail.email-log';
10
- const EMAIL_EVENT_UID = 'plugin::magic-mail.email-event';
11
- const EMAIL_ACCOUNT_UID = 'plugin::magic-mail.email-account';
12
-
13
- module.exports = ({ strapi }) => ({
14
- /**
15
- * Tracking pixel endpoint
16
- * GET /magic-mail/track/open/:emailId/:recipientHash
17
- */
18
- async trackOpen(ctx) {
19
- const { emailId, recipientHash } = ctx.params;
20
-
21
- // Record the open event
22
- await strapi.plugin('magic-mail').service('analytics').recordOpen(emailId, recipientHash, ctx.request);
23
-
24
- // Return 1x1 transparent GIF
25
- const pixel = Buffer.from(
26
- 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
27
- 'base64'
28
- );
29
-
30
- ctx.type = 'image/gif';
31
- ctx.body = pixel;
32
- },
33
-
34
- /**
35
- * Click tracking endpoint
36
- * GET /magic-mail/track/click/:emailId/:linkHash/:recipientHash
37
- */
38
- async trackClick(ctx) {
39
- const { emailId, linkHash, recipientHash } = ctx.params;
40
- let { url } = ctx.query;
41
-
42
- // Try to get URL from database if not in query string
43
- if (!url) {
44
- const analyticsService = strapi.plugin('magic-mail').service('analytics');
45
- url = await analyticsService.getOriginalUrlFromHash(emailId, linkHash);
46
- }
47
-
48
- if (!url) {
49
- return ctx.badRequest('Missing target URL');
50
- }
51
-
52
- // Record the click event
53
- await strapi
54
- .plugin('magic-mail')
55
- .service('analytics')
56
- .recordClick(emailId, linkHash, recipientHash, url, ctx.request);
57
-
58
- // Redirect to the original URL
59
- ctx.redirect(url);
60
- },
61
-
62
- /**
63
- * Get analytics statistics
64
- * GET /magic-mail/analytics/stats
65
- */
66
- async getStats(ctx) {
67
- try {
68
- const filters = {
69
- // userId is documentId (string) in Strapi v5, NOT parseInt!
70
- userId: ctx.query.userId || null,
71
- templateId: ctx.query.templateId ? parseInt(ctx.query.templateId) : null,
72
- accountId: ctx.query.accountId ? parseInt(ctx.query.accountId) : null,
73
- dateFrom: ctx.query.dateFrom || null,
74
- dateTo: ctx.query.dateTo || null,
75
- };
76
-
77
- // Remove null values
78
- Object.keys(filters).forEach(key => filters[key] === null && delete filters[key]);
79
-
80
- const stats = await strapi.plugin('magic-mail').service('analytics').getStats(filters);
81
-
82
- return ctx.send({
83
- success: true,
84
- data: stats,
85
- });
86
- } catch (error) {
87
- ctx.throw(500, error);
88
- }
89
- },
90
-
91
- /**
92
- * Get email logs
93
- * GET /magic-mail/analytics/emails
94
- */
95
- async getEmailLogs(ctx) {
96
- try {
97
- const filters = {
98
- // userId is documentId (string) in Strapi v5, NOT parseInt!
99
- userId: ctx.query.userId || null,
100
- templateId: ctx.query.templateId ? parseInt(ctx.query.templateId) : null,
101
- search: ctx.query.search || null,
102
- };
103
-
104
- const pagination = {
105
- page: ctx.query.page ? parseInt(ctx.query.page) : 1,
106
- pageSize: ctx.query.pageSize ? parseInt(ctx.query.pageSize) : 25,
107
- };
108
-
109
- // Remove null values
110
- Object.keys(filters).forEach(key => filters[key] === null && delete filters[key]);
111
-
112
- const result = await strapi
113
- .plugin('magic-mail')
114
- .service('analytics')
115
- .getEmailLogs(filters, pagination);
116
-
117
- return ctx.send({
118
- success: true,
119
- ...result,
120
- });
121
- } catch (error) {
122
- ctx.throw(500, error);
123
- }
124
- },
125
-
126
- /**
127
- * Get email log details
128
- * GET /magic-mail/analytics/emails/:emailId
129
- */
130
- async getEmailDetails(ctx) {
131
- try {
132
- const { emailId } = ctx.params;
133
-
134
- const emailLog = await strapi
135
- .plugin('magic-mail')
136
- .service('analytics')
137
- .getEmailLogDetails(emailId);
138
-
139
- if (!emailLog) {
140
- return ctx.notFound('Email log not found');
141
- }
142
-
143
- return ctx.send({
144
- success: true,
145
- data: emailLog,
146
- });
147
- } catch (error) {
148
- ctx.throw(500, error);
149
- }
150
- },
151
-
152
- /**
153
- * Get user email activity
154
- * GET /magic-mail/analytics/users/:userId
155
- * Note: userId is documentId (string) in Strapi v5
156
- */
157
- async getUserActivity(ctx) {
158
- try {
159
- const { userId } = ctx.params;
160
-
161
- // userId is documentId (string) in Strapi v5, NOT parseInt!
162
- const activity = await strapi
163
- .plugin('magic-mail')
164
- .service('analytics')
165
- .getUserActivity(userId);
166
-
167
- return ctx.send({
168
- success: true,
169
- data: activity,
170
- });
171
- } catch (error) {
172
- ctx.throw(500, error);
173
- }
174
- },
175
-
176
- /**
177
- * Debug Analytics - Check database state
178
- * GET /magic-mail/analytics/debug
179
- */
180
- async debug(ctx) {
181
- try {
182
- strapi.log.info('[magic-mail] [CHECK] Running Analytics Debug...');
183
-
184
- // Get email logs using Document Service
185
- const emailLogs = await strapi.documents(EMAIL_LOG_UID).findMany({
186
- limit: 10,
187
- sort: [{ sentAt: 'desc' }],
188
- });
189
-
190
- // Get email events using Document Service
191
- const emailEvents = await strapi.documents(EMAIL_EVENT_UID).findMany({
192
- limit: 20,
193
- sort: [{ timestamp: 'desc' }],
194
- populate: ['emailLog'],
195
- });
196
-
197
- // Get stats
198
- const analyticsService = strapi.plugin('magic-mail').service('analytics');
199
- const stats = await analyticsService.getStats();
200
-
201
- // Get active accounts using Document Service
202
- const accounts = await strapi.documents(EMAIL_ACCOUNT_UID).findMany({
203
- filters: { isActive: true },
204
- fields: ['id', 'name', 'provider', 'fromEmail', 'emailsSentToday', 'totalEmailsSent'],
205
- });
206
-
207
- // Generate sample tracking URLs
208
- let sampleTrackingUrls = null;
209
- if (emailLogs.length > 0) {
210
- const testLog = emailLogs[0];
211
- const testHash = analyticsService.generateRecipientHash(testLog.emailId, testLog.recipient);
212
-
213
- const baseUrl = strapi.config.get('server.url') || 'http://localhost:1337';
214
- sampleTrackingUrls = {
215
- trackingPixel: `${baseUrl}/api/magic-mail/track/open/${testLog.emailId}/${testHash}`,
216
- clickTracking: `${baseUrl}/api/magic-mail/track/click/${testLog.emailId}/test/${testHash}?url=https://example.com`,
217
- emailId: testLog.emailId,
218
- recipient: testLog.recipient,
219
- };
220
- }
221
-
222
- return ctx.send({
223
- success: true,
224
- debug: {
225
- timestamp: new Date().toISOString(),
226
- stats,
227
- emailLogsCount: emailLogs.length,
228
- emailEventsCount: emailEvents.length,
229
- activeAccountsCount: accounts.length,
230
- recentEmailLogs: emailLogs.map(log => ({
231
- emailId: log.emailId,
232
- recipient: log.recipient,
233
- subject: log.subject,
234
- sentAt: log.sentAt,
235
- openCount: log.openCount,
236
- clickCount: log.clickCount,
237
- firstOpenedAt: log.firstOpenedAt,
238
- accountName: log.accountName,
239
- templateName: log.templateName,
240
- })),
241
- recentEvents: emailEvents.map(event => ({
242
- type: event.type,
243
- timestamp: event.timestamp,
244
- emailId: event.emailLog?.emailId,
245
- ipAddress: event.ipAddress,
246
- linkUrl: event.linkUrl,
247
- })),
248
- accounts,
249
- sampleTrackingUrls,
250
- notes: [
251
- 'If emailLogsCount is 0: Emails are not being tracked (check if enableTracking=true)',
252
- 'If openCount is 0: Tracking pixel not being loaded (check email HTML source)',
253
- 'Test tracking URLs should be publicly accessible without authentication',
254
- 'Check Strapi console logs for tracking events when opening emails',
255
- ],
256
- },
257
- });
258
- } catch (error) {
259
- strapi.log.error('[magic-mail] Debug error:', error);
260
- ctx.throw(500, error);
261
- }
262
- },
263
-
264
- /**
265
- * Delete single email log
266
- * DELETE /magic-mail/analytics/emails/:emailId
267
- */
268
- async deleteEmailLog(ctx) {
269
- try {
270
- const { emailId } = ctx.params;
271
-
272
- // Find email log using Document Service
273
- const emailLog = await strapi.documents(EMAIL_LOG_UID).findFirst({
274
- filters: { emailId },
275
- });
276
-
277
- if (!emailLog) {
278
- return ctx.notFound('Email log not found');
279
- }
280
-
281
- // Delete associated events - filter relation with documentId object (Strapi v5)
282
- const events = await strapi.documents(EMAIL_EVENT_UID).findMany({
283
- filters: { emailLog: { documentId: emailLog.documentId } },
284
- });
285
-
286
- for (const event of events) {
287
- await strapi.documents(EMAIL_EVENT_UID).delete({ documentId: event.documentId });
288
- }
289
-
290
- // Delete email log
291
- await strapi.documents(EMAIL_LOG_UID).delete({ documentId: emailLog.documentId });
292
-
293
- strapi.log.info(`[magic-mail] [DELETE] Deleted email log: ${emailId}`);
294
-
295
- return ctx.send({
296
- success: true,
297
- message: 'Email log deleted successfully',
298
- });
299
- } catch (error) {
300
- strapi.log.error('[magic-mail] Error deleting email log:', error);
301
- ctx.throw(500, error);
302
- }
303
- },
304
-
305
- /**
306
- * Clear all email logs
307
- * DELETE /magic-mail/analytics/emails
308
- */
309
- async clearAllEmailLogs(ctx) {
310
- try {
311
- // Optional: Add query params for filtered deletion
312
- const { olderThan } = ctx.query; // e.g., ?olderThan=2024-01-01
313
-
314
- const filters = {};
315
- if (olderThan) {
316
- filters.sentAt = { $lt: new Date(olderThan) };
317
- }
318
-
319
- // Get all email logs to delete using Document Service
320
- const emailLogs = await strapi.documents(EMAIL_LOG_UID).findMany({
321
- filters,
322
- fields: ['id', 'documentId'],
323
- limit: 100000,
324
- });
325
-
326
- if (emailLogs.length === 0) {
327
- return ctx.send({
328
- success: true,
329
- message: 'No email logs to delete',
330
- deletedCount: 0,
331
- });
332
- }
333
-
334
- // Delete all associated events and logs
335
- for (const log of emailLogs) {
336
- // Delete events for this log - filter relation with documentId object (Strapi v5)
337
- const events = await strapi.documents(EMAIL_EVENT_UID).findMany({
338
- filters: { emailLog: { documentId: log.documentId } },
339
- });
340
-
341
- for (const event of events) {
342
- await strapi.documents(EMAIL_EVENT_UID).delete({ documentId: event.documentId });
343
- }
344
-
345
- // Delete the log itself
346
- await strapi.documents(EMAIL_LOG_UID).delete({ documentId: log.documentId });
347
- }
348
-
349
- strapi.log.info(`[magic-mail] [DELETE] Cleared ${emailLogs.length} email logs`);
350
-
351
- return ctx.send({
352
- success: true,
353
- message: `Successfully deleted ${emailLogs.length} email log(s)`,
354
- deletedCount: emailLogs.length,
355
- });
356
- } catch (error) {
357
- strapi.log.error('[magic-mail] Error clearing email logs:', error);
358
- ctx.throw(500, error);
359
- }
360
- },
361
- });
@@ -1,26 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Main Controller
5
- * Handles email sending requests
6
- */
7
-
8
- module.exports = {
9
- /**
10
- * Send email via MagicMail router
11
- */
12
- async send(ctx) {
13
- try {
14
- const emailRouter = strapi.plugin('magic-mail').service('email-router');
15
- const result = await emailRouter.send(ctx.request.body);
16
-
17
- ctx.body = {
18
- success: true,
19
- ...result,
20
- };
21
- } catch (err) {
22
- strapi.log.error('[magic-mail] Error sending email:', err);
23
- ctx.throw(500, err.message || 'Failed to send email');
24
- }
25
- },
26
- };