@tomei/mailer 0.6.0 → 0.7.1-dev.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/mailer",
3
- "version": "0.6.0",
3
+ "version": "0.7.1-dev.1",
4
4
  "description": "Tomei Mailer Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -19,20 +19,20 @@
19
19
  "@eslint/js": "^9.35.0",
20
20
  "@tsconfig/node18": "^18.2.4",
21
21
  "@types/jest": "^30.0.0",
22
- "@types/node": "^24.3.1",
22
+ "@types/node": "^24.5.2",
23
23
  "@types/nodemailer": "^7.0.1",
24
- "@typescript-eslint/eslint-plugin": "^8.43.0",
25
- "@typescript-eslint/parser": "^8.43.0",
24
+ "@typescript-eslint/eslint-plugin": "^8.44.0",
25
+ "@typescript-eslint/parser": "^8.44.0",
26
26
  "eslint": "^9.35.0",
27
27
  "eslint-config-prettier": "^10.1.8",
28
- "eslint-plugin-import": "^2.31.0",
28
+ "eslint-plugin-import": "^2.32.0",
29
29
  "eslint-plugin-prettier": "^5.5.4",
30
30
  "globals": "^16.4.0",
31
31
  "husky": "^9.1.7",
32
32
  "jest": "^30.1.3",
33
33
  "nodemailer-mock": "^2.0.9",
34
34
  "prettier": "^3.6.2",
35
- "ts-jest": "^29.4.1",
35
+ "ts-jest": "^29.4.3",
36
36
  "ts-node": "^10.9.2",
37
37
  "tsc-watch": "^7.1.1",
38
38
  "typescript": "^5.9.2"
@@ -42,6 +42,6 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@tomei/config": "^0.3.22",
45
- "nodemailer": "^6.10.1"
45
+ "nodemailer": "^7.0.6"
46
46
  }
47
47
  }
@@ -0,0 +1,93 @@
1
+ export type EmailStatus = 'success' | 'failed' | 'pending';
2
+
3
+ export class EmailLog {
4
+ id: string;
5
+ recipient: string;
6
+ subject: string;
7
+ emailType: string;
8
+ bodyHtml: string;
9
+ bodyText: string;
10
+ payload: string;
11
+ private _status: EmailStatus;
12
+ error?: string;
13
+ sentAt: Date;
14
+ createdAt: Date;
15
+ updatedAt?: Date;
16
+ resentFromId?: string;
17
+ resendMethod?: string;
18
+ resentById?: string;
19
+
20
+ constructor(params: {
21
+ id: string;
22
+ recipient: string;
23
+ subject: string;
24
+ emailType: string;
25
+ bodyHtml: string;
26
+ bodyText: string;
27
+ payload: string;
28
+ status?: EmailStatus;
29
+ error?: string;
30
+ sentAt?: Date;
31
+ createdAt?: Date;
32
+ updatedAt?: Date;
33
+ resentFromId?: string;
34
+ resendMethod?: string;
35
+ resentById?: string;
36
+ }) {
37
+ this.id = params.id;
38
+ this.recipient = params.recipient;
39
+ this.subject = params.subject;
40
+ this.emailType = params.emailType;
41
+ this.bodyHtml = params.bodyHtml;
42
+ this.bodyText = params.bodyText;
43
+ this.payload = params.payload;
44
+ this.error = params.error;
45
+ this.sentAt = params.sentAt ?? new Date();
46
+ this.createdAt = params.createdAt ?? new Date();
47
+ this.updatedAt = params.updatedAt;
48
+ this.resentFromId = params.resentFromId;
49
+ this.resendMethod = params.resendMethod;
50
+ this.resentById = params.resentById;
51
+
52
+ // Ensure stored status is lowercase and valid
53
+ const initialStatus = (params.status ?? 'pending') as string;
54
+ this._status = EmailLog.normalizeStatus(initialStatus);
55
+ }
56
+
57
+ // Enforce lowercase when reading
58
+ get status(): EmailStatus {
59
+ return this._status;
60
+ }
61
+
62
+ // Setting status always stores lowercase and validates value
63
+ set status(value: EmailStatus) {
64
+ this._status = EmailLog.normalizeStatus(value as string);
65
+ this.updatedAt = new Date();
66
+ }
67
+
68
+ // Normalize and validate incoming status strings
69
+ private static normalizeStatus(s: string): EmailStatus {
70
+ const lower = (s ?? '').toLowerCase();
71
+ if (lower === 'success' || lower === 'failed' || lower === 'pending') {
72
+ return lower as EmailStatus;
73
+ }
74
+ throw new Error(`Invalid EmailStatus value: ${s}`);
75
+ }
76
+
77
+ // Only allow transitions from pending -> success|failed
78
+ updateStatus(newStatus: EmailStatus): void {
79
+ const normalized = EmailLog.normalizeStatus(newStatus as string);
80
+ if (this._status !== 'pending') {
81
+ throw new Error(
82
+ `Invalid status transition: only 'pending' -> 'success'|'failed' allowed (current: ${this._status})`,
83
+ );
84
+ }
85
+ if (normalized !== 'success' && normalized !== 'failed') {
86
+ throw new Error(
87
+ `Invalid target status: ${normalized}. Must be 'success' or 'failed'`,
88
+ );
89
+ }
90
+ this._status = normalized;
91
+ this.updatedAt = new Date();
92
+ }
93
+ }
@@ -0,0 +1,7 @@
1
+ import { EmailLog, EmailStatus } from './EmailLog';
2
+
3
+ export interface IEmailRepository {
4
+ listAll(): Promise<EmailLog[]>;
5
+ filterByStatus(status: EmailStatus): Promise<EmailLog[]>;
6
+ findByRecipient(recipient: string): Promise<EmailLog[]>;
7
+ }
@@ -52,6 +52,33 @@ export class SMTPMailer extends MailerBase {
52
52
  'isMailerLogEnabled',
53
53
  );
54
54
 
55
+ const testReceipientEmail = ComponentConfig.getComponentConfigValue(
56
+ '@tomei/mailer',
57
+ 'testReceipientEmail',
58
+ );
59
+
60
+ const environment = ComponentConfig.getComponentConfigValue(
61
+ '@tomei/mailer',
62
+ 'environment',
63
+ );
64
+
65
+ if (
66
+ !host ||
67
+ !port ||
68
+ !user ||
69
+ !pass ||
70
+ !environment ||
71
+ !testReceipientEmail
72
+ ) {
73
+ throw new Error(
74
+ 'Host, port, user, pass, environment, or test receipient email is not defined in the configuration.',
75
+ );
76
+ }
77
+
78
+ if (environment !== 'production') {
79
+ options.to = testReceipientEmail;
80
+ }
81
+
55
82
  const transportConfig: TransportConfig = {
56
83
  host,
57
84
  port,