@webiny/api-mailer 6.3.0-beta.2 → 6.3.0-beta.4

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 (90) hide show
  1. package/domain/CodeMailerSettings/abstractions.d.ts +8 -0
  2. package/domain/CodeMailerSettings/abstractions.js +4 -0
  3. package/domain/CodeMailerSettings/abstractions.js.map +1 -0
  4. package/domain/MailTransport/abstractions.d.ts +8 -0
  5. package/domain/MailTransport/abstractions.js +1 -0
  6. package/domain/MailTransport/abstractions.js.map +1 -1
  7. package/domain/errors.d.ts +4 -0
  8. package/domain/errors.js +8 -0
  9. package/domain/errors.js.map +1 -1
  10. package/exports/api/mailer.d.ts +4 -0
  11. package/exports/api/mailer.js +6 -0
  12. package/exports/api/mailer.js.map +1 -0
  13. package/features/CodeMailerSettings/CodeMailerSettingsImpl.d.ts +12 -0
  14. package/features/CodeMailerSettings/CodeMailerSettingsImpl.js +22 -0
  15. package/features/CodeMailerSettings/CodeMailerSettingsImpl.js.map +1 -0
  16. package/features/{Encryption → CodeMailerSettings}/feature.d.ts +1 -1
  17. package/features/CodeMailerSettings/feature.js +10 -0
  18. package/features/CodeMailerSettings/feature.js.map +1 -0
  19. package/features/DummyTransport/DummyMailTransportFactory.d.ts +1 -0
  20. package/features/DummyTransport/DummyMailTransportFactory.js +1 -0
  21. package/features/DummyTransport/DummyMailTransportFactory.js.map +1 -1
  22. package/features/GetSettings/GetSettingsRepository.d.ts +6 -5
  23. package/features/GetSettings/GetSettingsRepository.js +29 -10
  24. package/features/GetSettings/GetSettingsRepository.js.map +1 -1
  25. package/features/GetSettings/GetSettingsUseCase.d.ts +3 -4
  26. package/features/GetSettings/GetSettingsUseCase.js +2 -2
  27. package/features/GetSettings/GetSettingsUseCase.js.map +1 -1
  28. package/features/GetSettings/abstractions.d.ts +11 -5
  29. package/features/GetSettings/abstractions.js.map +1 -1
  30. package/features/GetSettings/index.d.ts +1 -1
  31. package/features/GetSettings/index.js +1 -1
  32. package/features/GetSettings/index.js.map +1 -1
  33. package/features/MailerService/ActiveTransport.d.ts +10 -0
  34. package/features/MailerService/ActiveTransport.js +20 -0
  35. package/features/MailerService/ActiveTransport.js.map +1 -0
  36. package/features/MailerService/MailerService.d.ts +3 -2
  37. package/features/MailerService/MailerService.js +16 -15
  38. package/features/MailerService/MailerService.js.map +1 -1
  39. package/features/MailerService/feature.js +2 -0
  40. package/features/MailerService/feature.js.map +1 -1
  41. package/features/SaveSettings/SaveSettingsRepository.d.ts +1 -1
  42. package/features/SaveSettings/SaveSettingsRepository.js +12 -10
  43. package/features/SaveSettings/SaveSettingsRepository.js.map +1 -1
  44. package/features/SaveSettings/SaveSettingsUseCase.d.ts +5 -1
  45. package/features/SaveSettings/SaveSettingsUseCase.js +26 -8
  46. package/features/SaveSettings/SaveSettingsUseCase.js.map +1 -1
  47. package/features/SaveSettings/abstractions.d.ts +15 -7
  48. package/features/SaveSettings/abstractions.js +10 -1
  49. package/features/SaveSettings/abstractions.js.map +1 -1
  50. package/features/SaveSettings/index.d.ts +1 -1
  51. package/features/SaveSettings/index.js +1 -1
  52. package/features/SaveSettings/index.js.map +1 -1
  53. package/features/SaveSettings/validation.js +7 -3
  54. package/features/SaveSettings/validation.js.map +1 -1
  55. package/features/SendMail/SendMailUseCase.js +9 -6
  56. package/features/SendMail/SendMailUseCase.js.map +1 -1
  57. package/features/SendMail/index.d.ts +1 -0
  58. package/features/SendMail/index.js +3 -0
  59. package/features/SendMail/index.js.map +1 -0
  60. package/features/SmtpTransport/SmtpMailTransport.d.ts +51 -1
  61. package/features/SmtpTransport/SmtpMailTransport.js +7 -1
  62. package/features/SmtpTransport/SmtpMailTransport.js.map +1 -1
  63. package/features/SmtpTransport/SmtpMailTransportFactory.d.ts +1 -0
  64. package/features/SmtpTransport/SmtpMailTransportFactory.js +1 -0
  65. package/features/SmtpTransport/SmtpMailTransportFactory.js.map +1 -1
  66. package/graphql/settings.js +44 -32
  67. package/graphql/settings.js.map +1 -1
  68. package/index.js +3 -3
  69. package/index.js.map +1 -1
  70. package/package.json +20 -24
  71. package/utils/isMailboxAddress.d.ts +6 -0
  72. package/utils/isMailboxAddress.js +12 -0
  73. package/utils/isMailboxAddress.js.map +1 -0
  74. package/domain/Encryption/abstractions.d.ts +0 -8
  75. package/domain/Encryption/abstractions.js +0 -4
  76. package/domain/Encryption/abstractions.js.map +0 -1
  77. package/features/Encryption/PasswordEncryption.d.ts +0 -9
  78. package/features/Encryption/PasswordEncryption.js +0 -23
  79. package/features/Encryption/PasswordEncryption.js.map +0 -1
  80. package/features/Encryption/feature.js +0 -10
  81. package/features/Encryption/feature.js.map +0 -1
  82. package/features/Encryption/utils/password.d.ts +0 -7
  83. package/features/Encryption/utils/password.js +0 -56
  84. package/features/Encryption/utils/password.js.map +0 -1
  85. package/features/Encryption/utils/secret.d.ts +0 -1
  86. package/features/Encryption/utils/secret.js +0 -11
  87. package/features/Encryption/utils/secret.js.map +0 -1
  88. package/features/MailerService/TransportFactory.d.ts +0 -2
  89. package/features/MailerService/TransportFactory.js +0 -31
  90. package/features/MailerService/TransportFactory.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { Encryption } from "../../domain/Encryption/abstractions.js";
1
+ import { Encryption } from "@webiny/api-core/features/encryption/index.js";
2
2
  import { SaveSettingsRepository, type SaveSettingsInput } from "./abstractions.js";
3
3
  import { KeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
4
4
  declare class SaveSettingsRepositoryImpl implements SaveSettingsRepository.Interface {
@@ -1,5 +1,5 @@
1
1
  import { Result } from "@webiny/feature/api";
2
- import { Encryption } from "../../domain/Encryption/abstractions.js";
2
+ import { Encryption } from "@webiny/api-core/features/encryption/index.js";
3
3
  import { SaveSettingsRepository } from "./abstractions.js";
4
4
  import { SettingsPersistenceError } from "../../domain/errors.js";
5
5
  import { KeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
@@ -19,11 +19,11 @@ class SaveSettingsRepositoryImpl {
19
19
  // If updating and no password provided, keep the existing password
20
20
  let passwordToStore = input.password || "";
21
21
  if (!input.password && existingSettings) {
22
- passwordToStore = await this.encryption.decrypt(transportSettings.password || "");
22
+ passwordToStore = this.encryption.decrypt(transportSettings.password || "");
23
23
  }
24
24
 
25
25
  // Encrypt password
26
- const encryptedPassword = await this.encryption.encrypt(passwordToStore);
26
+ const encryptedPassword = this.encryption.encrypt(passwordToStore);
27
27
 
28
28
  // Prepare data
29
29
  const data = {
@@ -35,18 +35,20 @@ class SaveSettingsRepositoryImpl {
35
35
  replyTo: input.replyTo ?? transportSettings.replyTo
36
36
  };
37
37
 
38
- // Save settings
38
+ // Save settings.
39
39
  const result = await this.keyValueStore.set(MAILER_TRANSPORT_SETTINGS, data);
40
40
  if (result.isFail()) {
41
41
  return Result.fail(new SettingsPersistenceError(result.error));
42
42
  }
43
43
 
44
- // Return without encrypted password
45
- const returnSettings = {
46
- ...data,
47
- password: "" // Don't return password
48
- };
49
- return Result.ok(returnSettings);
44
+ // Return the stored state without the password. Callers that need the
45
+ // plaintext password go through GetSettingsRepository.get(transportName).
46
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
47
+ const {
48
+ password: _password,
49
+ ...savedSettings
50
+ } = data;
51
+ return Result.ok(savedSettings);
50
52
  }
51
53
  }
52
54
  export const SaveSettingsRepositoryImplementation = SaveSettingsRepository.createImplementation({
@@ -1 +1 @@
1
- {"version":3,"names":["Result","Encryption","SaveSettingsRepository","SettingsPersistenceError","KeyValueStore","MAILER_TRANSPORT_SETTINGS","DEFAULT_PORT","SaveSettingsRepositoryImpl","constructor","keyValueStore","encryption","execute","input","existingResult","get","existingSettings","isOk","value","transportSettings","passwordToStore","password","decrypt","encryptedPassword","encrypt","data","host","port","user","from","replyTo","result","set","isFail","fail","error","returnSettings","ok","SaveSettingsRepositoryImplementation","createImplementation","implementation","dependencies"],"sources":["SaveSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { Encryption } from \"~/domain/Encryption/abstractions.js\";\nimport { SaveSettingsRepository, type SaveSettingsInput } from \"./abstractions.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport { SettingsPersistenceError } from \"~/domain/errors.js\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport { MAILER_TRANSPORT_SETTINGS } from \"~/constants.js\";\n\nconst DEFAULT_PORT = 25;\n\nclass SaveSettingsRepositoryImpl implements SaveSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private encryption: Encryption.Interface\n ) {}\n\n async execute(input: SaveSettingsInput): SaveSettingsRepository.Return {\n // Check if settings exist\n const existingResult =\n await this.keyValueStore.get<TransportSettings>(MAILER_TRANSPORT_SETTINGS);\n const existingSettings = existingResult.isOk() ? existingResult.value : null;\n const transportSettings: Partial<TransportSettings> = existingSettings ?? {};\n\n // If updating and no password provided, keep the existing password\n let passwordToStore = input.password || \"\";\n if (!input.password && existingSettings) {\n passwordToStore = await this.encryption.decrypt(transportSettings.password || \"\");\n }\n\n // Encrypt password\n const encryptedPassword = await this.encryption.encrypt(passwordToStore);\n\n // Prepare data\n const data = {\n host: input.host ?? transportSettings.host,\n port: input.port ?? transportSettings.port ?? DEFAULT_PORT,\n user: input.user ?? transportSettings.user,\n password: encryptedPassword,\n from: input.from ?? transportSettings.from,\n replyTo: input.replyTo ?? transportSettings.replyTo\n };\n\n // Save settings\n const result = await this.keyValueStore.set(MAILER_TRANSPORT_SETTINGS, data);\n\n if (result.isFail()) {\n return Result.fail(new SettingsPersistenceError(result.error));\n }\n\n // Return without encrypted password\n const returnSettings: TransportSettings = {\n ...data,\n password: \"\" // Don't return password\n };\n\n return Result.ok(returnSettings);\n }\n}\n\nexport const SaveSettingsRepositoryImplementation = SaveSettingsRepository.createImplementation({\n implementation: SaveSettingsRepositoryImpl,\n dependencies: [KeyValueStore, Encryption]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SAASC,UAAU;AACnB,SAASC,sBAAsB;AAE/B,SAASC,wBAAwB;AACjC,SAASC,aAAa,QAAQ,kDAAkD;AAChF,SAASC,yBAAyB;AAElC,MAAMC,YAAY,GAAG,EAAE;AAEvB,MAAMC,0BAA0B,CAA6C;EACzEC,WAAWA,CACCC,aAAsC,EACtCC,UAAgC,EAC1C;IAAA,KAFUD,aAAsC,GAAtCA,aAAsC;IAAA,KACtCC,UAAgC,GAAhCA,UAAgC;EACzC;EAEH,MAAMC,OAAOA,CAACC,KAAwB,EAAiC;IACnE;IACA,MAAMC,cAAc,GAChB,MAAM,IAAI,CAACJ,aAAa,CAACK,GAAG,CAAoBT,yBAAyB,CAAC;IAC9E,MAAMU,gBAAgB,GAAGF,cAAc,CAACG,IAAI,CAAC,CAAC,GAAGH,cAAc,CAACI,KAAK,GAAG,IAAI;IAC5E,MAAMC,iBAA6C,GAAGH,gBAAgB,IAAI,CAAC,CAAC;;IAE5E;IACA,IAAII,eAAe,GAAGP,KAAK,CAACQ,QAAQ,IAAI,EAAE;IAC1C,IAAI,CAACR,KAAK,CAACQ,QAAQ,IAAIL,gBAAgB,EAAE;MACrCI,eAAe,GAAG,MAAM,IAAI,CAACT,UAAU,CAACW,OAAO,CAACH,iBAAiB,CAACE,QAAQ,IAAI,EAAE,CAAC;IACrF;;IAEA;IACA,MAAME,iBAAiB,GAAG,MAAM,IAAI,CAACZ,UAAU,CAACa,OAAO,CAACJ,eAAe,CAAC;;IAExE;IACA,MAAMK,IAAI,GAAG;MACTC,IAAI,EAAEb,KAAK,CAACa,IAAI,IAAIP,iBAAiB,CAACO,IAAI;MAC1CC,IAAI,EAAEd,KAAK,CAACc,IAAI,IAAIR,iBAAiB,CAACQ,IAAI,IAAIpB,YAAY;MAC1DqB,IAAI,EAAEf,KAAK,CAACe,IAAI,IAAIT,iBAAiB,CAACS,IAAI;MAC1CP,QAAQ,EAAEE,iBAAiB;MAC3BM,IAAI,EAAEhB,KAAK,CAACgB,IAAI,IAAIV,iBAAiB,CAACU,IAAI;MAC1CC,OAAO,EAAEjB,KAAK,CAACiB,OAAO,IAAIX,iBAAiB,CAACW;IAChD,CAAC;;IAED;IACA,MAAMC,MAAM,GAAG,MAAM,IAAI,CAACrB,aAAa,CAACsB,GAAG,CAAC1B,yBAAyB,EAAEmB,IAAI,CAAC;IAE5E,IAAIM,MAAM,CAACE,MAAM,CAAC,CAAC,EAAE;MACjB,OAAOhC,MAAM,CAACiC,IAAI,CAAC,IAAI9B,wBAAwB,CAAC2B,MAAM,CAACI,KAAK,CAAC,CAAC;IAClE;;IAEA;IACA,MAAMC,cAAiC,GAAG;MACtC,GAAGX,IAAI;MACPJ,QAAQ,EAAE,EAAE,CAAC;IACjB,CAAC;IAED,OAAOpB,MAAM,CAACoC,EAAE,CAACD,cAAc,CAAC;EACpC;AACJ;AAEA,OAAO,MAAME,oCAAoC,GAAGnC,sBAAsB,CAACoC,oBAAoB,CAAC;EAC5FC,cAAc,EAAEhC,0BAA0B;EAC1CiC,YAAY,EAAE,CAACpC,aAAa,EAAEH,UAAU;AAC5C,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["Result","Encryption","SaveSettingsRepository","SettingsPersistenceError","KeyValueStore","MAILER_TRANSPORT_SETTINGS","DEFAULT_PORT","SaveSettingsRepositoryImpl","constructor","keyValueStore","encryption","execute","input","existingResult","get","existingSettings","isOk","value","transportSettings","passwordToStore","password","decrypt","encryptedPassword","encrypt","data","host","port","user","from","replyTo","result","set","isFail","fail","error","_password","savedSettings","ok","SaveSettingsRepositoryImplementation","createImplementation","implementation","dependencies"],"sources":["SaveSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { Encryption } from \"@webiny/api-core/features/encryption/index.js\";\nimport { SaveSettingsRepository, type SaveSettingsInput } from \"./abstractions.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport { SettingsPersistenceError } from \"~/domain/errors.js\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport { MAILER_TRANSPORT_SETTINGS } from \"~/constants.js\";\n\nconst DEFAULT_PORT = 25;\n\nclass SaveSettingsRepositoryImpl implements SaveSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private encryption: Encryption.Interface\n ) {}\n\n async execute(input: SaveSettingsInput): SaveSettingsRepository.Return {\n // Check if settings exist\n const existingResult =\n await this.keyValueStore.get<TransportSettings>(MAILER_TRANSPORT_SETTINGS);\n const existingSettings = existingResult.isOk() ? existingResult.value : null;\n const transportSettings: Partial<TransportSettings> = existingSettings ?? {};\n\n // If updating and no password provided, keep the existing password\n let passwordToStore = input.password || \"\";\n if (!input.password && existingSettings) {\n passwordToStore = this.encryption.decrypt(transportSettings.password || \"\");\n }\n\n // Encrypt password\n const encryptedPassword = this.encryption.encrypt(passwordToStore);\n\n // Prepare data\n const data = {\n host: input.host ?? transportSettings.host,\n port: input.port ?? transportSettings.port ?? DEFAULT_PORT,\n user: input.user ?? transportSettings.user,\n password: encryptedPassword,\n from: input.from ?? transportSettings.from,\n replyTo: input.replyTo ?? transportSettings.replyTo\n };\n\n // Save settings.\n const result = await this.keyValueStore.set(MAILER_TRANSPORT_SETTINGS, data);\n\n if (result.isFail()) {\n return Result.fail(new SettingsPersistenceError(result.error));\n }\n\n // Return the stored state without the password. Callers that need the\n // plaintext password go through GetSettingsRepository.get(transportName).\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { password: _password, ...savedSettings } = data as TransportSettings;\n return Result.ok(savedSettings);\n }\n}\n\nexport const SaveSettingsRepositoryImplementation = SaveSettingsRepository.createImplementation({\n implementation: SaveSettingsRepositoryImpl,\n dependencies: [KeyValueStore, Encryption]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SAASC,UAAU,QAAQ,+CAA+C;AAC1E,SAASC,sBAAsB;AAE/B,SAASC,wBAAwB;AACjC,SAASC,aAAa,QAAQ,kDAAkD;AAChF,SAASC,yBAAyB;AAElC,MAAMC,YAAY,GAAG,EAAE;AAEvB,MAAMC,0BAA0B,CAA6C;EACzEC,WAAWA,CACCC,aAAsC,EACtCC,UAAgC,EAC1C;IAAA,KAFUD,aAAsC,GAAtCA,aAAsC;IAAA,KACtCC,UAAgC,GAAhCA,UAAgC;EACzC;EAEH,MAAMC,OAAOA,CAACC,KAAwB,EAAiC;IACnE;IACA,MAAMC,cAAc,GAChB,MAAM,IAAI,CAACJ,aAAa,CAACK,GAAG,CAAoBT,yBAAyB,CAAC;IAC9E,MAAMU,gBAAgB,GAAGF,cAAc,CAACG,IAAI,CAAC,CAAC,GAAGH,cAAc,CAACI,KAAK,GAAG,IAAI;IAC5E,MAAMC,iBAA6C,GAAGH,gBAAgB,IAAI,CAAC,CAAC;;IAE5E;IACA,IAAII,eAAe,GAAGP,KAAK,CAACQ,QAAQ,IAAI,EAAE;IAC1C,IAAI,CAACR,KAAK,CAACQ,QAAQ,IAAIL,gBAAgB,EAAE;MACrCI,eAAe,GAAG,IAAI,CAACT,UAAU,CAACW,OAAO,CAACH,iBAAiB,CAACE,QAAQ,IAAI,EAAE,CAAC;IAC/E;;IAEA;IACA,MAAME,iBAAiB,GAAG,IAAI,CAACZ,UAAU,CAACa,OAAO,CAACJ,eAAe,CAAC;;IAElE;IACA,MAAMK,IAAI,GAAG;MACTC,IAAI,EAAEb,KAAK,CAACa,IAAI,IAAIP,iBAAiB,CAACO,IAAI;MAC1CC,IAAI,EAAEd,KAAK,CAACc,IAAI,IAAIR,iBAAiB,CAACQ,IAAI,IAAIpB,YAAY;MAC1DqB,IAAI,EAAEf,KAAK,CAACe,IAAI,IAAIT,iBAAiB,CAACS,IAAI;MAC1CP,QAAQ,EAAEE,iBAAiB;MAC3BM,IAAI,EAAEhB,KAAK,CAACgB,IAAI,IAAIV,iBAAiB,CAACU,IAAI;MAC1CC,OAAO,EAAEjB,KAAK,CAACiB,OAAO,IAAIX,iBAAiB,CAACW;IAChD,CAAC;;IAED;IACA,MAAMC,MAAM,GAAG,MAAM,IAAI,CAACrB,aAAa,CAACsB,GAAG,CAAC1B,yBAAyB,EAAEmB,IAAI,CAAC;IAE5E,IAAIM,MAAM,CAACE,MAAM,CAAC,CAAC,EAAE;MACjB,OAAOhC,MAAM,CAACiC,IAAI,CAAC,IAAI9B,wBAAwB,CAAC2B,MAAM,CAACI,KAAK,CAAC,CAAC;IAClE;;IAEA;IACA;IACA;IACA,MAAM;MAAEd,QAAQ,EAAEe,SAAS;MAAE,GAAGC;IAAc,CAAC,GAAGZ,IAAyB;IAC3E,OAAOxB,MAAM,CAACqC,EAAE,CAACD,aAAa,CAAC;EACnC;AACJ;AAEA,OAAO,MAAME,oCAAoC,GAAGpC,sBAAsB,CAACqC,oBAAoB,CAAC;EAC5FC,cAAc,EAAEjC,0BAA0B;EAC1CkC,YAAY,EAAE,CAACrC,aAAa,EAAEH,UAAU;AAC5C,CAAC,CAAC","ignoreList":[]}
@@ -1,11 +1,15 @@
1
1
  import { EventPublisher as EventPublisherAbstraction } from "@webiny/api-core/features/eventPublisher/index.js";
2
2
  import { SaveSettingsUseCase, SaveSettingsRepository, type SaveSettingsInput } from "./abstractions.js";
3
3
  import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
4
+ import { CodeMailerSettings } from "../../domain/CodeMailerSettings/abstractions.js";
5
+ import { ActiveTransport } from "../../domain/MailTransport/abstractions.js";
4
6
  declare class SaveSettingsUseCaseImpl implements SaveSettingsUseCase.Interface {
5
7
  private identityContext;
6
8
  private eventPublisher;
7
9
  private repository;
8
- constructor(identityContext: IdentityContext.Interface, eventPublisher: EventPublisherAbstraction.Interface, repository: SaveSettingsRepository.Interface);
10
+ private codeSettings;
11
+ private activeTransport;
12
+ constructor(identityContext: IdentityContext.Interface, eventPublisher: EventPublisherAbstraction.Interface, repository: SaveSettingsRepository.Interface, codeSettings: CodeMailerSettings.Interface, activeTransport: ActiveTransport.Interface);
9
13
  execute(input: SaveSettingsInput): SaveSettingsUseCase.Return;
10
14
  }
11
15
  export declare const SaveSettingsUseCaseImplementation: typeof SaveSettingsUseCaseImpl & {
@@ -3,13 +3,17 @@ import { EventPublisher } from "@webiny/api-core/features/eventPublisher/index.j
3
3
  import { SaveSettingsUseCase, SaveSettingsRepository } from "./abstractions.js";
4
4
  import { MailerSettingsBeforeSaveEvent, MailerSettingsAfterSaveEvent } from "./events.js";
5
5
  import { saveValidation } from "./validation.js";
6
- import { SettingsValidationError, SettingsPersistenceError, SettingsNotAuthorized } from "../../domain/errors.js";
6
+ import { SettingsValidationError, SettingsPersistenceError, SettingsNotAuthorized, SettingsLockedByCode } from "../../domain/errors.js";
7
7
  import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
8
+ import { CodeMailerSettings } from "../../domain/CodeMailerSettings/abstractions.js";
9
+ import { ActiveTransport } from "../../domain/MailTransport/abstractions.js";
8
10
  class SaveSettingsUseCaseImpl {
9
- constructor(identityContext, eventPublisher, repository) {
11
+ constructor(identityContext, eventPublisher, repository, codeSettings, activeTransport) {
10
12
  this.identityContext = identityContext;
11
13
  this.eventPublisher = eventPublisher;
12
14
  this.repository = repository;
15
+ this.codeSettings = codeSettings;
16
+ this.activeTransport = activeTransport;
13
17
  }
14
18
  async execute(input) {
15
19
  const permission = await this.identityContext.getPermission("mailer.settings");
@@ -17,25 +21,39 @@ class SaveSettingsUseCaseImpl {
17
21
  return Result.fail(new SettingsNotAuthorized());
18
22
  }
19
23
 
20
- // Validate input
24
+ // Validate input.
21
25
  const validationResult = saveValidation.safeParse(input);
22
26
  if (!validationResult.success) {
23
27
  return Result.fail(new SettingsValidationError(validationResult.error.issues));
24
28
  }
25
29
 
26
- // Publish before save event
30
+ // Refuse when settings are defined via code.
31
+ const transportName = this.activeTransport.name();
32
+ if (transportName && this.codeSettings.get(transportName) !== null) {
33
+ return Result.fail(new SettingsLockedByCode());
34
+ }
35
+
36
+ // Publish before save event. Strip the password — subscribers (audit
37
+ // logs, telemetry) must never see the plaintext value from the input.
38
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
39
+ const {
40
+ password: _beforePassword,
41
+ ...inputForEvent
42
+ } = input;
27
43
  const beforeSaveEvent = new MailerSettingsBeforeSaveEvent({
28
- input
44
+ input: inputForEvent
29
45
  });
30
46
  await this.eventPublisher.publish(beforeSaveEvent);
31
47
 
32
- // Save settings
48
+ // Save settings.
33
49
  const result = await this.repository.execute(input);
34
50
  if (result.isFail()) {
35
51
  return Result.fail(new SettingsPersistenceError(result.error));
36
52
  }
37
53
 
38
- // Publish after save event
54
+ // Publish after save event. The repository return is already password-free
55
+ // (its type is Omit<TransportSettings, "password">), so no runtime strip
56
+ // is needed here.
39
57
  const afterSaveEvent = new MailerSettingsAfterSaveEvent({
40
58
  settings: result.value
41
59
  });
@@ -45,7 +63,7 @@ class SaveSettingsUseCaseImpl {
45
63
  }
46
64
  export const SaveSettingsUseCaseImplementation = SaveSettingsUseCase.createImplementation({
47
65
  implementation: SaveSettingsUseCaseImpl,
48
- dependencies: [IdentityContext, EventPublisher, SaveSettingsRepository]
66
+ dependencies: [IdentityContext, EventPublisher, SaveSettingsRepository, CodeMailerSettings, ActiveTransport]
49
67
  });
50
68
 
51
69
  //# sourceMappingURL=SaveSettingsUseCase.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Result","EventPublisher","SaveSettingsUseCase","SaveSettingsRepository","MailerSettingsBeforeSaveEvent","MailerSettingsAfterSaveEvent","saveValidation","SettingsValidationError","SettingsPersistenceError","SettingsNotAuthorized","IdentityContext","SaveSettingsUseCaseImpl","constructor","identityContext","eventPublisher","repository","execute","input","permission","getPermission","fail","validationResult","safeParse","success","error","issues","beforeSaveEvent","publish","result","isFail","afterSaveEvent","settings","value","SaveSettingsUseCaseImplementation","createImplementation","implementation","dependencies"],"sources":["SaveSettingsUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n EventPublisher,\n EventPublisher as EventPublisherAbstraction\n} from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport {\n SaveSettingsUseCase,\n SaveSettingsRepository,\n type SaveSettingsInput\n} from \"./abstractions.js\";\nimport { MailerSettingsBeforeSaveEvent, MailerSettingsAfterSaveEvent } from \"./events.js\";\nimport { saveValidation } from \"./validation.js\";\nimport {\n SettingsValidationError,\n SettingsPersistenceError,\n SettingsNotAuthorized\n} from \"~/domain/errors.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\n\nclass SaveSettingsUseCaseImpl implements SaveSettingsUseCase.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private eventPublisher: EventPublisherAbstraction.Interface,\n private repository: SaveSettingsRepository.Interface\n ) {}\n\n async execute(input: SaveSettingsInput): SaveSettingsUseCase.Return {\n const permission = await this.identityContext.getPermission(\"mailer.settings\");\n\n if (!permission) {\n return Result.fail(new SettingsNotAuthorized());\n }\n\n // Validate input\n const validationResult = saveValidation.safeParse(input);\n if (!validationResult.success) {\n return Result.fail(new SettingsValidationError(validationResult.error.issues));\n }\n\n // Publish before save event\n const beforeSaveEvent = new MailerSettingsBeforeSaveEvent({ input });\n await this.eventPublisher.publish(beforeSaveEvent);\n\n // Save settings\n const result = await this.repository.execute(input);\n\n if (result.isFail()) {\n return Result.fail(new SettingsPersistenceError(result.error));\n }\n\n // Publish after save event\n const afterSaveEvent = new MailerSettingsAfterSaveEvent({ settings: result.value });\n await this.eventPublisher.publish(afterSaveEvent);\n\n return result;\n }\n}\n\nexport const SaveSettingsUseCaseImplementation = SaveSettingsUseCase.createImplementation({\n implementation: SaveSettingsUseCaseImpl,\n dependencies: [IdentityContext, EventPublisher, SaveSettingsRepository]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SACIC,cAAc,QAEX,mDAAmD;AAC1D,SACIC,mBAAmB,EACnBC,sBAAsB;AAG1B,SAASC,6BAA6B,EAAEC,4BAA4B;AACpE,SAASC,cAAc;AACvB,SACIC,uBAAuB,EACvBC,wBAAwB,EACxBC,qBAAqB;AAEzB,SAASC,eAAe,QAAQ,6DAA6D;AAE7F,MAAMC,uBAAuB,CAA0C;EACnEC,WAAWA,CACCC,eAA0C,EAC1CC,cAAmD,EACnDC,UAA4C,EACtD;IAAA,KAHUF,eAA0C,GAA1CA,eAA0C;IAAA,KAC1CC,cAAmD,GAAnDA,cAAmD;IAAA,KACnDC,UAA4C,GAA5CA,UAA4C;EACrD;EAEH,MAAMC,OAAOA,CAACC,KAAwB,EAA8B;IAChE,MAAMC,UAAU,GAAG,MAAM,IAAI,CAACL,eAAe,CAACM,aAAa,CAAC,iBAAiB,CAAC;IAE9E,IAAI,CAACD,UAAU,EAAE;MACb,OAAOlB,MAAM,CAACoB,IAAI,CAAC,IAAIX,qBAAqB,CAAC,CAAC,CAAC;IACnD;;IAEA;IACA,MAAMY,gBAAgB,GAAGf,cAAc,CAACgB,SAAS,CAACL,KAAK,CAAC;IACxD,IAAI,CAACI,gBAAgB,CAACE,OAAO,EAAE;MAC3B,OAAOvB,MAAM,CAACoB,IAAI,CAAC,IAAIb,uBAAuB,CAACc,gBAAgB,CAACG,KAAK,CAACC,MAAM,CAAC,CAAC;IAClF;;IAEA;IACA,MAAMC,eAAe,GAAG,IAAItB,6BAA6B,CAAC;MAAEa;IAAM,CAAC,CAAC;IACpE,MAAM,IAAI,CAACH,cAAc,CAACa,OAAO,CAACD,eAAe,CAAC;;IAElD;IACA,MAAME,MAAM,GAAG,MAAM,IAAI,CAACb,UAAU,CAACC,OAAO,CAACC,KAAK,CAAC;IAEnD,IAAIW,MAAM,CAACC,MAAM,CAAC,CAAC,EAAE;MACjB,OAAO7B,MAAM,CAACoB,IAAI,CAAC,IAAIZ,wBAAwB,CAACoB,MAAM,CAACJ,KAAK,CAAC,CAAC;IAClE;;IAEA;IACA,MAAMM,cAAc,GAAG,IAAIzB,4BAA4B,CAAC;MAAE0B,QAAQ,EAAEH,MAAM,CAACI;IAAM,CAAC,CAAC;IACnF,MAAM,IAAI,CAAClB,cAAc,CAACa,OAAO,CAACG,cAAc,CAAC;IAEjD,OAAOF,MAAM;EACjB;AACJ;AAEA,OAAO,MAAMK,iCAAiC,GAAG/B,mBAAmB,CAACgC,oBAAoB,CAAC;EACtFC,cAAc,EAAExB,uBAAuB;EACvCyB,YAAY,EAAE,CAAC1B,eAAe,EAAET,cAAc,EAAEE,sBAAsB;AAC1E,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["Result","EventPublisher","SaveSettingsUseCase","SaveSettingsRepository","MailerSettingsBeforeSaveEvent","MailerSettingsAfterSaveEvent","saveValidation","SettingsValidationError","SettingsPersistenceError","SettingsNotAuthorized","SettingsLockedByCode","IdentityContext","CodeMailerSettings","ActiveTransport","SaveSettingsUseCaseImpl","constructor","identityContext","eventPublisher","repository","codeSettings","activeTransport","execute","input","permission","getPermission","fail","validationResult","safeParse","success","error","issues","transportName","name","get","password","_beforePassword","inputForEvent","beforeSaveEvent","publish","result","isFail","afterSaveEvent","settings","value","SaveSettingsUseCaseImplementation","createImplementation","implementation","dependencies"],"sources":["SaveSettingsUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n EventPublisher,\n EventPublisher as EventPublisherAbstraction\n} from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport {\n SaveSettingsUseCase,\n SaveSettingsRepository,\n type SaveSettingsInput\n} from \"./abstractions.js\";\nimport { MailerSettingsBeforeSaveEvent, MailerSettingsAfterSaveEvent } from \"./events.js\";\nimport { saveValidation } from \"./validation.js\";\nimport {\n SettingsValidationError,\n SettingsPersistenceError,\n SettingsNotAuthorized,\n SettingsLockedByCode\n} from \"~/domain/errors.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { CodeMailerSettings } from \"~/domain/CodeMailerSettings/abstractions.js\";\nimport { ActiveTransport } from \"~/domain/MailTransport/abstractions.js\";\n\nclass SaveSettingsUseCaseImpl implements SaveSettingsUseCase.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private eventPublisher: EventPublisherAbstraction.Interface,\n private repository: SaveSettingsRepository.Interface,\n private codeSettings: CodeMailerSettings.Interface,\n private activeTransport: ActiveTransport.Interface\n ) {}\n\n async execute(input: SaveSettingsInput): SaveSettingsUseCase.Return {\n const permission = await this.identityContext.getPermission(\"mailer.settings\");\n\n if (!permission) {\n return Result.fail(new SettingsNotAuthorized());\n }\n\n // Validate input.\n const validationResult = saveValidation.safeParse(input);\n if (!validationResult.success) {\n return Result.fail(new SettingsValidationError(validationResult.error.issues));\n }\n\n // Refuse when settings are defined via code.\n const transportName = this.activeTransport.name();\n if (transportName && this.codeSettings.get(transportName) !== null) {\n return Result.fail(new SettingsLockedByCode());\n }\n\n // Publish before save event. Strip the password — subscribers (audit\n // logs, telemetry) must never see the plaintext value from the input.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { password: _beforePassword, ...inputForEvent } = input;\n const beforeSaveEvent = new MailerSettingsBeforeSaveEvent({ input: inputForEvent });\n await this.eventPublisher.publish(beforeSaveEvent);\n\n // Save settings.\n const result = await this.repository.execute(input);\n\n if (result.isFail()) {\n return Result.fail(new SettingsPersistenceError(result.error));\n }\n\n // Publish after save event. The repository return is already password-free\n // (its type is Omit<TransportSettings, \"password\">), so no runtime strip\n // is needed here.\n const afterSaveEvent = new MailerSettingsAfterSaveEvent({ settings: result.value });\n await this.eventPublisher.publish(afterSaveEvent);\n\n return result;\n }\n}\n\nexport const SaveSettingsUseCaseImplementation = SaveSettingsUseCase.createImplementation({\n implementation: SaveSettingsUseCaseImpl,\n dependencies: [\n IdentityContext,\n EventPublisher,\n SaveSettingsRepository,\n CodeMailerSettings,\n ActiveTransport\n ]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SACIC,cAAc,QAEX,mDAAmD;AAC1D,SACIC,mBAAmB,EACnBC,sBAAsB;AAG1B,SAASC,6BAA6B,EAAEC,4BAA4B;AACpE,SAASC,cAAc;AACvB,SACIC,uBAAuB,EACvBC,wBAAwB,EACxBC,qBAAqB,EACrBC,oBAAoB;AAExB,SAASC,eAAe,QAAQ,6DAA6D;AAC7F,SAASC,kBAAkB;AAC3B,SAASC,eAAe;AAExB,MAAMC,uBAAuB,CAA0C;EACnEC,WAAWA,CACCC,eAA0C,EAC1CC,cAAmD,EACnDC,UAA4C,EAC5CC,YAA0C,EAC1CC,eAA0C,EACpD;IAAA,KALUJ,eAA0C,GAA1CA,eAA0C;IAAA,KAC1CC,cAAmD,GAAnDA,cAAmD;IAAA,KACnDC,UAA4C,GAA5CA,UAA4C;IAAA,KAC5CC,YAA0C,GAA1CA,YAA0C;IAAA,KAC1CC,eAA0C,GAA1CA,eAA0C;EACnD;EAEH,MAAMC,OAAOA,CAACC,KAAwB,EAA8B;IAChE,MAAMC,UAAU,GAAG,MAAM,IAAI,CAACP,eAAe,CAACQ,aAAa,CAAC,iBAAiB,CAAC;IAE9E,IAAI,CAACD,UAAU,EAAE;MACb,OAAOvB,MAAM,CAACyB,IAAI,CAAC,IAAIhB,qBAAqB,CAAC,CAAC,CAAC;IACnD;;IAEA;IACA,MAAMiB,gBAAgB,GAAGpB,cAAc,CAACqB,SAAS,CAACL,KAAK,CAAC;IACxD,IAAI,CAACI,gBAAgB,CAACE,OAAO,EAAE;MAC3B,OAAO5B,MAAM,CAACyB,IAAI,CAAC,IAAIlB,uBAAuB,CAACmB,gBAAgB,CAACG,KAAK,CAACC,MAAM,CAAC,CAAC;IAClF;;IAEA;IACA,MAAMC,aAAa,GAAG,IAAI,CAACX,eAAe,CAACY,IAAI,CAAC,CAAC;IACjD,IAAID,aAAa,IAAI,IAAI,CAACZ,YAAY,CAACc,GAAG,CAACF,aAAa,CAAC,KAAK,IAAI,EAAE;MAChE,OAAO/B,MAAM,CAACyB,IAAI,CAAC,IAAIf,oBAAoB,CAAC,CAAC,CAAC;IAClD;;IAEA;IACA;IACA;IACA,MAAM;MAAEwB,QAAQ,EAAEC,eAAe;MAAE,GAAGC;IAAc,CAAC,GAAGd,KAAK;IAC7D,MAAMe,eAAe,GAAG,IAAIjC,6BAA6B,CAAC;MAAEkB,KAAK,EAAEc;IAAc,CAAC,CAAC;IACnF,MAAM,IAAI,CAACnB,cAAc,CAACqB,OAAO,CAACD,eAAe,CAAC;;IAElD;IACA,MAAME,MAAM,GAAG,MAAM,IAAI,CAACrB,UAAU,CAACG,OAAO,CAACC,KAAK,CAAC;IAEnD,IAAIiB,MAAM,CAACC,MAAM,CAAC,CAAC,EAAE;MACjB,OAAOxC,MAAM,CAACyB,IAAI,CAAC,IAAIjB,wBAAwB,CAAC+B,MAAM,CAACV,KAAK,CAAC,CAAC;IAClE;;IAEA;IACA;IACA;IACA,MAAMY,cAAc,GAAG,IAAIpC,4BAA4B,CAAC;MAAEqC,QAAQ,EAAEH,MAAM,CAACI;IAAM,CAAC,CAAC;IACnF,MAAM,IAAI,CAAC1B,cAAc,CAACqB,OAAO,CAACG,cAAc,CAAC;IAEjD,OAAOF,MAAM;EACjB;AACJ;AAEA,OAAO,MAAMK,iCAAiC,GAAG1C,mBAAmB,CAAC2C,oBAAoB,CAAC;EACtFC,cAAc,EAAEhC,uBAAuB;EACvCiC,YAAY,EAAE,CACVpC,eAAe,EACfV,cAAc,EACdE,sBAAsB,EACtBS,kBAAkB,EAClBC,eAAe;AAEvB,CAAC,CAAC","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  import { Result } from "@webiny/feature/api";
2
2
  import type { DomainEvent, IEventHandler } from "@webiny/api-core/features/eventPublisher/index.js";
3
3
  import type { TransportSettings } from "../../types.js";
4
- import { SettingsValidationError, SettingsPersistenceError, SettingsNotAuthorized } from "../../domain/errors.js";
4
+ import { SettingsValidationError, SettingsPersistenceError, SettingsNotAuthorized, SettingsLockedByCode } from "../../domain/errors.js";
5
5
  export interface SaveSettingsInput {
6
6
  host: string;
7
7
  port?: number;
@@ -14,31 +14,39 @@ export interface ISaveSettingsErrors {
14
14
  validation: SettingsValidationError;
15
15
  persistence: SettingsPersistenceError;
16
16
  notAuthorized: SettingsNotAuthorized;
17
+ lockedByCode: SettingsLockedByCode;
17
18
  }
18
19
  type SaveSettingsError = ISaveSettingsErrors[keyof ISaveSettingsErrors];
20
+ /**
21
+ * Save-side returns are password-free. The only path that exposes the password
22
+ * to in-process callers is GetSettingsRepository.get / GetSettingsUseCase.execute
23
+ * (used by MailerService to authenticate SMTP). Everything else — events,
24
+ * GraphQL responses, logs, audit trails — must use this Omit shape.
25
+ */
26
+ export type SavedTransportSettings = Omit<TransportSettings, "password">;
19
27
  export interface ISaveSettingsRepository {
20
- execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;
28
+ execute(input: SaveSettingsInput): Promise<Result<SavedTransportSettings, SaveSettingsError>>;
21
29
  }
22
30
  export declare const SaveSettingsRepository: import("@webiny/di").Abstraction<ISaveSettingsRepository>;
23
31
  export declare namespace SaveSettingsRepository {
24
32
  type Interface = ISaveSettingsRepository;
25
- type Return = Promise<Result<TransportSettings, SaveSettingsError>>;
33
+ type Return = Promise<Result<SavedTransportSettings, SaveSettingsError>>;
26
34
  type Error = SaveSettingsError;
27
35
  }
28
36
  export interface ISaveSettings {
29
- execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;
37
+ execute(input: SaveSettingsInput): Promise<Result<SavedTransportSettings, SaveSettingsError>>;
30
38
  }
31
39
  export declare const SaveSettingsUseCase: import("@webiny/di").Abstraction<ISaveSettings>;
32
40
  export declare namespace SaveSettingsUseCase {
33
41
  type Interface = ISaveSettings;
34
- type Return = Promise<Result<TransportSettings, SaveSettingsError>>;
42
+ type Return = Promise<Result<SavedTransportSettings, SaveSettingsError>>;
35
43
  type Error = SaveSettingsError;
36
44
  }
37
45
  export interface MailerSettingsBeforeSavePayload {
38
- input: SaveSettingsInput;
46
+ input: Omit<SaveSettingsInput, "password">;
39
47
  }
40
48
  export interface MailerSettingsAfterSavePayload {
41
- settings: TransportSettings;
49
+ settings: Omit<TransportSettings, "password">;
42
50
  }
43
51
  export declare const MailerSettingsBeforeSaveEventHandler: import("@webiny/di").Abstraction<IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>>;
44
52
  export declare namespace MailerSettingsBeforeSaveEventHandler {
@@ -1,8 +1,17 @@
1
1
  import { createAbstraction } from "@webiny/feature/api";
2
+
3
+ /**
4
+ * Save-side returns are password-free. The only path that exposes the password
5
+ * to in-process callers is GetSettingsRepository.get / GetSettingsUseCase.execute
6
+ * (used by MailerService to authenticate SMTP). Everything else — events,
7
+ * GraphQL responses, logs, audit trails — must use this Omit shape.
8
+ */
9
+
2
10
  export const SaveSettingsRepository = createAbstraction("SaveSettingsRepository");
3
11
  export const SaveSettingsUseCase = createAbstraction("SaveSettingsUseCase");
4
12
 
5
- // Domain Events
13
+ // Domain Events. Both payloads exclude `password` so subscribers (audit logs,
14
+ // telemetry, etc.) cannot accidentally persist plaintext or ciphertext secrets.
6
15
 
7
16
  // Event Handler Abstractions
8
17
  export const MailerSettingsBeforeSaveEventHandler = createAbstraction("MailerSettingsBeforeSaveEventHandler");
@@ -1 +1 @@
1
- {"version":3,"names":["createAbstraction","SaveSettingsRepository","SaveSettingsUseCase","MailerSettingsBeforeSaveEventHandler","MailerSettingsAfterSaveEventHandler"],"sources":["abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport type { DomainEvent, IEventHandler } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport {\n SettingsValidationError,\n SettingsPersistenceError,\n SettingsNotAuthorized\n} from \"~/domain/errors.js\";\n\nexport interface SaveSettingsInput {\n host: string;\n port?: number;\n user: string;\n password?: string;\n from: string;\n replyTo?: string;\n}\n\nexport interface ISaveSettingsErrors {\n validation: SettingsValidationError;\n persistence: SettingsPersistenceError;\n notAuthorized: SettingsNotAuthorized;\n}\n\ntype SaveSettingsError = ISaveSettingsErrors[keyof ISaveSettingsErrors];\n\nexport interface ISaveSettingsRepository {\n execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;\n}\n\nexport const SaveSettingsRepository =\n createAbstraction<ISaveSettingsRepository>(\"SaveSettingsRepository\");\n\nexport namespace SaveSettingsRepository {\n export type Interface = ISaveSettingsRepository;\n export type Return = Promise<Result<TransportSettings, SaveSettingsError>>;\n export type Error = SaveSettingsError;\n}\n\nexport interface ISaveSettings {\n execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;\n}\n\nexport const SaveSettingsUseCase = createAbstraction<ISaveSettings>(\"SaveSettingsUseCase\");\n\nexport namespace SaveSettingsUseCase {\n export type Interface = ISaveSettings;\n export type Return = Promise<Result<TransportSettings, SaveSettingsError>>;\n export type Error = SaveSettingsError;\n}\n\n// Domain Events\nexport interface MailerSettingsBeforeSavePayload {\n input: SaveSettingsInput;\n}\n\nexport interface MailerSettingsAfterSavePayload {\n settings: TransportSettings;\n}\n\n// Event Handler Abstractions\nexport const MailerSettingsBeforeSaveEventHandler = createAbstraction<\n IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>\n>(\"MailerSettingsBeforeSaveEventHandler\");\n\nexport namespace MailerSettingsBeforeSaveEventHandler {\n export type Interface = IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>;\n export type Event = DomainEvent<MailerSettingsBeforeSavePayload>;\n}\n\nexport const MailerSettingsAfterSaveEventHandler = createAbstraction<\n IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>\n>(\"MailerSettingsAfterSaveEventHandler\");\n\nexport namespace MailerSettingsAfterSaveEventHandler {\n export type Interface = IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>;\n export type Event = DomainEvent<MailerSettingsAfterSavePayload>;\n}\n"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,qBAAqB;AA+BvD,OAAO,MAAMC,sBAAsB,GAC/BD,iBAAiB,CAA0B,wBAAwB,CAAC;AAYxE,OAAO,MAAME,mBAAmB,GAAGF,iBAAiB,CAAgB,qBAAqB,CAAC;;AAQ1F;;AASA;AACA,OAAO,MAAMG,oCAAoC,GAAGH,iBAAiB,CAEnE,sCAAsC,CAAC;AAOzC,OAAO,MAAMI,mCAAmC,GAAGJ,iBAAiB,CAElE,qCAAqC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["createAbstraction","SaveSettingsRepository","SaveSettingsUseCase","MailerSettingsBeforeSaveEventHandler","MailerSettingsAfterSaveEventHandler"],"sources":["abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport type { DomainEvent, IEventHandler } from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport {\n SettingsValidationError,\n SettingsPersistenceError,\n SettingsNotAuthorized,\n SettingsLockedByCode\n} from \"~/domain/errors.js\";\n\nexport interface SaveSettingsInput {\n host: string;\n port?: number;\n user: string;\n password?: string;\n from: string;\n replyTo?: string;\n}\n\nexport interface ISaveSettingsErrors {\n validation: SettingsValidationError;\n persistence: SettingsPersistenceError;\n notAuthorized: SettingsNotAuthorized;\n lockedByCode: SettingsLockedByCode;\n}\n\ntype SaveSettingsError = ISaveSettingsErrors[keyof ISaveSettingsErrors];\n\n/**\n * Save-side returns are password-free. The only path that exposes the password\n * to in-process callers is GetSettingsRepository.get / GetSettingsUseCase.execute\n * (used by MailerService to authenticate SMTP). Everything else — events,\n * GraphQL responses, logs, audit trails — must use this Omit shape.\n */\nexport type SavedTransportSettings = Omit<TransportSettings, \"password\">;\n\nexport interface ISaveSettingsRepository {\n execute(input: SaveSettingsInput): Promise<Result<SavedTransportSettings, SaveSettingsError>>;\n}\n\nexport const SaveSettingsRepository =\n createAbstraction<ISaveSettingsRepository>(\"SaveSettingsRepository\");\n\nexport namespace SaveSettingsRepository {\n export type Interface = ISaveSettingsRepository;\n export type Return = Promise<Result<SavedTransportSettings, SaveSettingsError>>;\n export type Error = SaveSettingsError;\n}\n\nexport interface ISaveSettings {\n execute(input: SaveSettingsInput): Promise<Result<SavedTransportSettings, SaveSettingsError>>;\n}\n\nexport const SaveSettingsUseCase = createAbstraction<ISaveSettings>(\"SaveSettingsUseCase\");\n\nexport namespace SaveSettingsUseCase {\n export type Interface = ISaveSettings;\n export type Return = Promise<Result<SavedTransportSettings, SaveSettingsError>>;\n export type Error = SaveSettingsError;\n}\n\n// Domain Events. Both payloads exclude `password` so subscribers (audit logs,\n// telemetry, etc.) cannot accidentally persist plaintext or ciphertext secrets.\nexport interface MailerSettingsBeforeSavePayload {\n input: Omit<SaveSettingsInput, \"password\">;\n}\n\nexport interface MailerSettingsAfterSavePayload {\n settings: Omit<TransportSettings, \"password\">;\n}\n\n// Event Handler Abstractions\nexport const MailerSettingsBeforeSaveEventHandler = createAbstraction<\n IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>\n>(\"MailerSettingsBeforeSaveEventHandler\");\n\nexport namespace MailerSettingsBeforeSaveEventHandler {\n export type Interface = IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>;\n export type Event = DomainEvent<MailerSettingsBeforeSavePayload>;\n}\n\nexport const MailerSettingsAfterSaveEventHandler = createAbstraction<\n IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>\n>(\"MailerSettingsAfterSaveEventHandler\");\n\nexport namespace MailerSettingsAfterSaveEventHandler {\n export type Interface = IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>;\n export type Event = DomainEvent<MailerSettingsAfterSavePayload>;\n}\n"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,qBAAqB;;AA6BvD;AACA;AACA;AACA;AACA;AACA;;AAOA,OAAO,MAAMC,sBAAsB,GAC/BD,iBAAiB,CAA0B,wBAAwB,CAAC;AAYxE,OAAO,MAAME,mBAAmB,GAAGF,iBAAiB,CAAgB,qBAAqB,CAAC;;AAQ1F;AACA;;AASA;AACA,OAAO,MAAMG,oCAAoC,GAAGH,iBAAiB,CAEnE,sCAAsC,CAAC;AAOzC,OAAO,MAAMI,mCAAmC,GAAGJ,iBAAiB,CAElE,qCAAqC,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- export { SaveSettingsUseCase, MailerSettingsAfterSaveEventHandler, MailerSettingsBeforeSaveEventHandler } from "./abstractions.js";
1
+ export { SaveSettingsUseCase, SaveSettingsRepository, MailerSettingsAfterSaveEventHandler, MailerSettingsBeforeSaveEventHandler } from "./abstractions.js";
@@ -1,3 +1,3 @@
1
- export { SaveSettingsUseCase, MailerSettingsAfterSaveEventHandler, MailerSettingsBeforeSaveEventHandler } from "./abstractions.js";
1
+ export { SaveSettingsUseCase, SaveSettingsRepository, MailerSettingsAfterSaveEventHandler, MailerSettingsBeforeSaveEventHandler } from "./abstractions.js";
2
2
 
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["SaveSettingsUseCase","MailerSettingsAfterSaveEventHandler","MailerSettingsBeforeSaveEventHandler"],"sources":["index.ts"],"sourcesContent":["export {\n SaveSettingsUseCase,\n MailerSettingsAfterSaveEventHandler,\n MailerSettingsBeforeSaveEventHandler\n} from \"./abstractions.js\";\n"],"mappings":"AAAA,SACIA,mBAAmB,EACnBC,mCAAmC,EACnCC,oCAAoC","ignoreList":[]}
1
+ {"version":3,"names":["SaveSettingsUseCase","SaveSettingsRepository","MailerSettingsAfterSaveEventHandler","MailerSettingsBeforeSaveEventHandler"],"sources":["index.ts"],"sourcesContent":["export {\n SaveSettingsUseCase,\n SaveSettingsRepository,\n MailerSettingsAfterSaveEventHandler,\n MailerSettingsBeforeSaveEventHandler\n} from \"./abstractions.js\";\n"],"mappings":"AAAA,SACIA,mBAAmB,EACnBC,sBAAsB,EACtBC,mCAAmC,EACnCC,oCAAoC","ignoreList":[]}
@@ -1,11 +1,15 @@
1
1
  import zod from "zod";
2
+ import { isMailboxAddress } from "../../utils/isMailboxAddress.js";
2
3
  const password = zod.string().describe("Password");
4
+ const mailboxAddress = zod.string().refine(isMailboxAddress, {
5
+ message: "Invalid email address."
6
+ });
3
7
  const common = {
4
- from: zod.string().email().describe("Mail from"),
8
+ from: mailboxAddress.describe("Mail from"),
5
9
  port: zod.number().optional().nullish().describe("Port"),
6
10
  replyTo: zod.preprocess(
7
- // We need to set empty strings to `null` before email validation kicks in
8
- value => value === "" ? null : value, zod.string().email().optional().nullish()).describe("Mail reply-to"),
11
+ // We need to set empty strings to `null` before address validation kicks in.
12
+ value => value === "" ? null : value, mailboxAddress.optional().nullish()).describe("Mail reply-to"),
9
13
  host: zod.string().describe("Hostname"),
10
14
  user: zod.string().describe("User")
11
15
  };
@@ -1 +1 @@
1
- {"version":3,"names":["zod","password","string","describe","common","from","email","port","number","optional","nullish","replyTo","preprocess","value","host","user","saveValidation","object","transform","undefined"],"sources":["validation.ts"],"sourcesContent":["import zod from \"zod\";\n\nconst password = zod.string().describe(\"Password\");\n\nconst common = {\n from: zod.string().email().describe(\"Mail from\"),\n port: zod.number().optional().nullish().describe(\"Port\"),\n replyTo: zod\n .preprocess(\n // We need to set empty strings to `null` before email validation kicks in\n value => (value === \"\" ? null : value),\n zod.string().email().optional().nullish()\n )\n .describe(\"Mail reply-to\"),\n host: zod.string().describe(\"Hostname\"),\n user: zod.string().describe(\"User\")\n};\n\nexport const saveValidation = zod.object({\n ...common,\n password: password\n .nullish()\n .optional()\n .transform(value => {\n return value === undefined ? null : value;\n })\n});\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,KAAK;AAErB,MAAMC,QAAQ,GAAGD,GAAG,CAACE,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,UAAU,CAAC;AAElD,MAAMC,MAAM,GAAG;EACXC,IAAI,EAAEL,GAAG,CAACE,MAAM,CAAC,CAAC,CAACI,KAAK,CAAC,CAAC,CAACH,QAAQ,CAAC,WAAW,CAAC;EAChDI,IAAI,EAAEP,GAAG,CAACQ,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC,CAACC,OAAO,CAAC,CAAC,CAACP,QAAQ,CAAC,MAAM,CAAC;EACxDQ,OAAO,EAAEX,GAAG,CACPY,UAAU;EACP;EACAC,KAAK,IAAKA,KAAK,KAAK,EAAE,GAAG,IAAI,GAAGA,KAAM,EACtCb,GAAG,CAACE,MAAM,CAAC,CAAC,CAACI,KAAK,CAAC,CAAC,CAACG,QAAQ,CAAC,CAAC,CAACC,OAAO,CAAC,CAC5C,CAAC,CACAP,QAAQ,CAAC,eAAe,CAAC;EAC9BW,IAAI,EAAEd,GAAG,CAACE,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,UAAU,CAAC;EACvCY,IAAI,EAAEf,GAAG,CAACE,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,MAAM;AACtC,CAAC;AAED,OAAO,MAAMa,cAAc,GAAGhB,GAAG,CAACiB,MAAM,CAAC;EACrC,GAAGb,MAAM;EACTH,QAAQ,EAAEA,QAAQ,CACbS,OAAO,CAAC,CAAC,CACTD,QAAQ,CAAC,CAAC,CACVS,SAAS,CAACL,KAAK,IAAI;IAChB,OAAOA,KAAK,KAAKM,SAAS,GAAG,IAAI,GAAGN,KAAK;EAC7C,CAAC;AACT,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["zod","isMailboxAddress","password","string","describe","mailboxAddress","refine","message","common","from","port","number","optional","nullish","replyTo","preprocess","value","host","user","saveValidation","object","transform","undefined"],"sources":["validation.ts"],"sourcesContent":["import zod from \"zod\";\nimport { isMailboxAddress } from \"~/utils/isMailboxAddress.js\";\n\nconst password = zod.string().describe(\"Password\");\n\nconst mailboxAddress = zod.string().refine(isMailboxAddress, { message: \"Invalid email address.\" });\n\nconst common = {\n from: mailboxAddress.describe(\"Mail from\"),\n port: zod.number().optional().nullish().describe(\"Port\"),\n replyTo: zod\n .preprocess(\n // We need to set empty strings to `null` before address validation kicks in.\n value => (value === \"\" ? null : value),\n mailboxAddress.optional().nullish()\n )\n .describe(\"Mail reply-to\"),\n host: zod.string().describe(\"Hostname\"),\n user: zod.string().describe(\"User\")\n};\n\nexport const saveValidation = zod.object({\n ...common,\n password: password\n .nullish()\n .optional()\n .transform(value => {\n return value === undefined ? null : value;\n })\n});\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,KAAK;AACrB,SAASC,gBAAgB;AAEzB,MAAMC,QAAQ,GAAGF,GAAG,CAACG,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,UAAU,CAAC;AAElD,MAAMC,cAAc,GAAGL,GAAG,CAACG,MAAM,CAAC,CAAC,CAACG,MAAM,CAACL,gBAAgB,EAAE;EAAEM,OAAO,EAAE;AAAyB,CAAC,CAAC;AAEnG,MAAMC,MAAM,GAAG;EACXC,IAAI,EAAEJ,cAAc,CAACD,QAAQ,CAAC,WAAW,CAAC;EAC1CM,IAAI,EAAEV,GAAG,CAACW,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC,CAACC,OAAO,CAAC,CAAC,CAACT,QAAQ,CAAC,MAAM,CAAC;EACxDU,OAAO,EAAEd,GAAG,CACPe,UAAU;EACP;EACAC,KAAK,IAAKA,KAAK,KAAK,EAAE,GAAG,IAAI,GAAGA,KAAM,EACtCX,cAAc,CAACO,QAAQ,CAAC,CAAC,CAACC,OAAO,CAAC,CACtC,CAAC,CACAT,QAAQ,CAAC,eAAe,CAAC;EAC9Ba,IAAI,EAAEjB,GAAG,CAACG,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,UAAU,CAAC;EACvCc,IAAI,EAAElB,GAAG,CAACG,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,MAAM;AACtC,CAAC;AAED,OAAO,MAAMe,cAAc,GAAGnB,GAAG,CAACoB,MAAM,CAAC;EACrC,GAAGZ,MAAM;EACTN,QAAQ,EAAEA,QAAQ,CACbW,OAAO,CAAC,CAAC,CACTD,QAAQ,CAAC,CAAC,CACVS,SAAS,CAACL,KAAK,IAAI;IAChB,OAAOA,KAAK,KAAKM,SAAS,GAAG,IAAI,GAAGN,KAAK;EAC7C,CAAC;AACT,CAAC,CAAC","ignoreList":[]}
@@ -5,15 +5,18 @@ import { MailBeforeSendEvent, MailAfterSendEvent, MailSendErrorEvent } from "./e
5
5
  import { MailerService } from "../../domain/MailerService/abstractions.js";
6
6
  import { MailValidationError } from "../../domain/errors.js";
7
7
  import { Result } from "@webiny/feature/api";
8
+ import { isMailboxAddress } from "../../utils/isMailboxAddress.js";
8
9
  const requiredString = zod.string();
9
- const requiredEmail = requiredString.email();
10
+ const mailboxAddress = zod.string().refine(isMailboxAddress, {
11
+ message: "Invalid email address."
12
+ });
10
13
  const schema = zod.object({
11
- to: zod.array(requiredEmail).optional(),
12
- from: zod.string().email().optional(),
14
+ to: zod.array(mailboxAddress).optional(),
15
+ from: mailboxAddress.optional(),
13
16
  subject: requiredString.max(1024).min(2),
14
- cc: zod.array(requiredEmail).optional(),
15
- bcc: zod.array(requiredEmail).optional(),
16
- replyTo: zod.string().email().optional(),
17
+ cc: zod.array(mailboxAddress).optional(),
18
+ bcc: zod.array(mailboxAddress).optional(),
19
+ replyTo: mailboxAddress.optional(),
17
20
  text: zod.string().optional(),
18
21
  html: zod.string().optional()
19
22
  }).refine(data => {
@@ -1 +1 @@
1
- {"version":3,"names":["zod","EventPublisher","SendMailUseCase","MailBeforeSendEvent","MailAfterSendEvent","MailSendErrorEvent","MailerService","MailValidationError","Result","requiredString","string","requiredEmail","email","schema","object","to","array","optional","from","subject","max","min","cc","bcc","replyTo","text","html","refine","data","SendMailUseCaseImpl","constructor","mailerService","eventPublisher","execute","validation","safeParse","success","fail","error","issues","publish","result","sendMail","isFail","response","value","SendMailUseCaseImplementation","createImplementation","implementation","dependencies"],"sources":["SendMailUseCase.ts"],"sourcesContent":["import zod from \"zod\";\nimport {\n EventPublisher,\n EventPublisher as EventPublisherAbstraction\n} from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport { SendMailUseCase } from \"./abstractions.js\";\nimport { MailBeforeSendEvent, MailAfterSendEvent, MailSendErrorEvent } from \"./events.js\";\nimport { MailerService } from \"~/domain/MailerService/abstractions.js\";\nimport type { TransportSendData } from \"~/types.js\";\nimport { MailValidationError } from \"~/domain/errors.js\";\nimport { Result } from \"@webiny/feature/api\";\n\nconst requiredString = zod.string();\nconst requiredEmail = requiredString.email();\n\nconst schema = zod\n .object({\n to: zod.array(requiredEmail).optional(),\n from: zod.string().email().optional(),\n subject: requiredString.max(1024).min(2),\n cc: zod.array(requiredEmail).optional(),\n bcc: zod.array(requiredEmail).optional(),\n replyTo: zod.string().email().optional(),\n text: zod.string().optional(),\n html: zod.string().optional()\n })\n .refine(data => {\n return !!data.text || !!data.html;\n }, \"Either text or html is required.\");\n\nclass SendMailUseCaseImpl implements SendMailUseCase.Interface {\n constructor(\n private mailerService: MailerService.Interface,\n private eventPublisher: EventPublisherAbstraction.Interface\n ) {}\n\n async execute(data: TransportSendData) {\n const validation = schema.safeParse(data);\n if (!validation.success) {\n return Result.fail(new MailValidationError(validation.error.issues));\n }\n\n // Publish before send event\n await this.eventPublisher.publish(new MailBeforeSendEvent({ data }));\n\n // Send mail\n const result = await this.mailerService.sendMail(data);\n\n if (result.isFail()) {\n // Publish error event\n await this.eventPublisher.publish(\n new MailSendErrorEvent({\n data,\n error: result.error\n })\n );\n\n return result;\n }\n\n // Publish after send event\n await this.eventPublisher.publish(\n new MailAfterSendEvent({\n data,\n response: result.value\n })\n );\n\n return result;\n }\n}\n\nexport const SendMailUseCaseImplementation = SendMailUseCase.createImplementation({\n implementation: SendMailUseCaseImpl,\n dependencies: [MailerService, EventPublisher]\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["zod","EventPublisher","SendMailUseCase","MailBeforeSendEvent","MailAfterSendEvent","MailSendErrorEvent","MailerService","MailValidationError","Result","isMailboxAddress","requiredString","string","mailboxAddress","refine","message","schema","object","to","array","optional","from","subject","max","min","cc","bcc","replyTo","text","html","data","SendMailUseCaseImpl","constructor","mailerService","eventPublisher","execute","validation","safeParse","success","fail","error","issues","publish","result","sendMail","isFail","response","value","SendMailUseCaseImplementation","createImplementation","implementation","dependencies"],"sources":["SendMailUseCase.ts"],"sourcesContent":["import zod from \"zod\";\nimport {\n EventPublisher,\n EventPublisher as EventPublisherAbstraction\n} from \"@webiny/api-core/features/eventPublisher/index.js\";\nimport { SendMailUseCase } from \"./abstractions.js\";\nimport { MailBeforeSendEvent, MailAfterSendEvent, MailSendErrorEvent } from \"./events.js\";\nimport { MailerService } from \"~/domain/MailerService/abstractions.js\";\nimport type { TransportSendData } from \"~/types.js\";\nimport { MailValidationError } from \"~/domain/errors.js\";\nimport { Result } from \"@webiny/feature/api\";\nimport { isMailboxAddress } from \"~/utils/isMailboxAddress.js\";\n\nconst requiredString = zod.string();\nconst mailboxAddress = zod.string().refine(isMailboxAddress, { message: \"Invalid email address.\" });\n\nconst schema = zod\n .object({\n to: zod.array(mailboxAddress).optional(),\n from: mailboxAddress.optional(),\n subject: requiredString.max(1024).min(2),\n cc: zod.array(mailboxAddress).optional(),\n bcc: zod.array(mailboxAddress).optional(),\n replyTo: mailboxAddress.optional(),\n text: zod.string().optional(),\n html: zod.string().optional()\n })\n .refine(data => {\n return !!data.text || !!data.html;\n }, \"Either text or html is required.\");\n\nclass SendMailUseCaseImpl implements SendMailUseCase.Interface {\n constructor(\n private mailerService: MailerService.Interface,\n private eventPublisher: EventPublisherAbstraction.Interface\n ) {}\n\n async execute(data: TransportSendData) {\n const validation = schema.safeParse(data);\n if (!validation.success) {\n return Result.fail(new MailValidationError(validation.error.issues));\n }\n\n // Publish before send event\n await this.eventPublisher.publish(new MailBeforeSendEvent({ data }));\n\n // Send mail\n const result = await this.mailerService.sendMail(data);\n\n if (result.isFail()) {\n // Publish error event\n await this.eventPublisher.publish(\n new MailSendErrorEvent({\n data,\n error: result.error\n })\n );\n\n return result;\n }\n\n // Publish after send event\n await this.eventPublisher.publish(\n new MailAfterSendEvent({\n data,\n response: result.value\n })\n );\n\n return result;\n }\n}\n\nexport const SendMailUseCaseImplementation = SendMailUseCase.createImplementation({\n implementation: SendMailUseCaseImpl,\n dependencies: [MailerService, EventPublisher]\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export { SendMailUseCase, MailAfterSendEventHandler, MailBeforeSendEventHandler, MailSendErrorEventHandler } from "./abstractions.js";
@@ -0,0 +1,3 @@
1
+ export { SendMailUseCase, MailAfterSendEventHandler, MailBeforeSendEventHandler, MailSendErrorEventHandler } from "./abstractions.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SendMailUseCase","MailAfterSendEventHandler","MailBeforeSendEventHandler","MailSendErrorEventHandler"],"sources":["index.ts"],"sourcesContent":["export {\n SendMailUseCase,\n MailAfterSendEventHandler,\n MailBeforeSendEventHandler,\n MailSendErrorEventHandler\n} from \"./abstractions.js\";\n"],"mappings":"AAAA,SACIA,eAAe,EACfC,yBAAyB,EACzBC,0BAA0B,EAC1BC,yBAAyB","ignoreList":[]}
@@ -7,12 +7,62 @@ export declare class SmtpMailTransport implements MailTransport.Interface {
7
7
  send(params: MailTransport.SendParams): Promise<{
8
8
  result: string;
9
9
  error: null;
10
+ } | {
11
+ result: null;
12
+ error: {
13
+ message: string;
14
+ code: string;
15
+ data: {
16
+ envelope: import("nodemailer/lib/mime-node").Envelope;
17
+ messageId: string;
18
+ accepted: Array<string | import("nodemailer/lib/mailer").Address>;
19
+ rejected: Array<string | import("nodemailer/lib/mailer").Address>;
20
+ pending: Array<string | import("nodemailer/lib/mailer").Address>;
21
+ response: string;
22
+ };
23
+ };
10
24
  } | {
11
25
  result: null;
12
26
  error: {
13
27
  message: any;
14
28
  code: any;
15
- data: any;
29
+ data: {
30
+ command: any;
31
+ response: any;
32
+ responseCode: any;
33
+ to: string[];
34
+ cc?: string[];
35
+ bcc?: string[];
36
+ from?: string;
37
+ subject: string;
38
+ text?: string;
39
+ html?: string;
40
+ replyTo?: string;
41
+ } | {
42
+ command: any;
43
+ response: any;
44
+ responseCode: any;
45
+ to?: string[];
46
+ cc: string[];
47
+ bcc?: string[];
48
+ from?: string;
49
+ subject: string;
50
+ text?: string;
51
+ html?: string;
52
+ replyTo?: string;
53
+ } | {
54
+ command: any;
55
+ response: any;
56
+ responseCode: any;
57
+ to?: string[];
58
+ cc?: string[];
59
+ bcc: string[];
60
+ from?: string;
61
+ subject: string;
62
+ text?: string;
63
+ html?: string;
64
+ replyTo?: string;
65
+ };
16
66
  };
17
67
  }>;
18
68
  }
@@ -43,6 +43,10 @@ export class SmtpMailTransport {
43
43
  }
44
44
  };
45
45
  } catch (ex) {
46
+ // Allow-list specific nodemailer/SMTP error fields. Spreading `ex`
47
+ // or `ex.data` blindly would risk surfacing the transporter's auth
48
+ // config (or anything else a future nodemailer version stamps onto
49
+ // its errors) in error responses.
46
50
  return {
47
51
  result: null,
48
52
  error: {
@@ -50,7 +54,9 @@ export class SmtpMailTransport {
50
54
  code: ex.code,
51
55
  data: {
52
56
  ...params,
53
- ...ex.data
57
+ command: ex.command,
58
+ response: ex.response,
59
+ responseCode: ex.responseCode
54
60
  }
55
61
  }
56
62
  };
@@ -1 +1 @@
1
- {"version":3,"names":["nodemailer","SmtpMailTransport","name","constructor","config","transporter","createTransport","send","params","replyTo","text","html","to","bcc","cc","from","subject","result","sendMail","messageId","response","error","message","code","data","ex"],"sources":["SmtpMailTransport.ts"],"sourcesContent":["import type { Transporter } from \"nodemailer\";\nimport nodemailer from \"nodemailer\";\nimport type SMTPTransport from \"nodemailer/lib/smtp-transport\";\nimport { MailTransport } from \"~/domain/MailTransport/abstractions.js\";\n\nexport class SmtpMailTransport implements MailTransport.Interface {\n public readonly name = \"Mailer/SmtpTransport\";\n private readonly transporter: Transporter<SMTPTransport.SentMessageInfo>;\n\n constructor(config: SMTPTransport.Options) {\n this.transporter = nodemailer.createTransport(config);\n }\n\n async send(params: MailTransport.SendParams) {\n const { replyTo, text, html, to, bcc, cc, from, subject } = params;\n\n try {\n const result = await this.transporter.sendMail({\n replyTo,\n bcc,\n cc,\n from,\n text,\n html,\n to,\n subject\n });\n\n if (result.messageId) {\n return {\n result: result.response,\n error: null\n };\n }\n\n return {\n result: null,\n error: {\n message:\n \"nodemailer.sendMail does not have a messageId in the result. Something went wrong...\",\n code: \"MAILER_ERROR\",\n data: {\n ...result\n }\n }\n };\n } catch (ex: any) {\n return {\n result: null,\n error: {\n message: ex.message,\n code: ex.code,\n data: {\n ...params,\n ...ex.data\n }\n }\n };\n }\n }\n}\n"],"mappings":"AACA,OAAOA,UAAU,MAAM,YAAY;AAInC,OAAO,MAAMC,iBAAiB,CAAoC;EAC9CC,IAAI,GAAG,sBAAsB;EAG7CC,WAAWA,CAACC,MAA6B,EAAE;IACvC,IAAI,CAACC,WAAW,GAAGL,UAAU,CAACM,eAAe,CAACF,MAAM,CAAC;EACzD;EAEA,MAAMG,IAAIA,CAACC,MAAgC,EAAE;IACzC,MAAM;MAAEC,OAAO;MAAEC,IAAI;MAAEC,IAAI;MAAEC,EAAE;MAAEC,GAAG;MAAEC,EAAE;MAAEC,IAAI;MAAEC;IAAQ,CAAC,GAAGR,MAAM;IAElE,IAAI;MACA,MAAMS,MAAM,GAAG,MAAM,IAAI,CAACZ,WAAW,CAACa,QAAQ,CAAC;QAC3CT,OAAO;QACPI,GAAG;QACHC,EAAE;QACFC,IAAI;QACJL,IAAI;QACJC,IAAI;QACJC,EAAE;QACFI;MACJ,CAAC,CAAC;MAEF,IAAIC,MAAM,CAACE,SAAS,EAAE;QAClB,OAAO;UACHF,MAAM,EAAEA,MAAM,CAACG,QAAQ;UACvBC,KAAK,EAAE;QACX,CAAC;MACL;MAEA,OAAO;QACHJ,MAAM,EAAE,IAAI;QACZI,KAAK,EAAE;UACHC,OAAO,EACH,sFAAsF;UAC1FC,IAAI,EAAE,cAAc;UACpBC,IAAI,EAAE;YACF,GAAGP;UACP;QACJ;MACJ,CAAC;IACL,CAAC,CAAC,OAAOQ,EAAO,EAAE;MACd,OAAO;QACHR,MAAM,EAAE,IAAI;QACZI,KAAK,EAAE;UACHC,OAAO,EAAEG,EAAE,CAACH,OAAO;UACnBC,IAAI,EAAEE,EAAE,CAACF,IAAI;UACbC,IAAI,EAAE;YACF,GAAGhB,MAAM;YACT,GAAGiB,EAAE,CAACD;UACV;QACJ;MACJ,CAAC;IACL;EACJ;AACJ","ignoreList":[]}
1
+ {"version":3,"names":["nodemailer","SmtpMailTransport","name","constructor","config","transporter","createTransport","send","params","replyTo","text","html","to","bcc","cc","from","subject","result","sendMail","messageId","response","error","message","code","data","ex","command","responseCode"],"sources":["SmtpMailTransport.ts"],"sourcesContent":["import type { Transporter } from \"nodemailer\";\nimport nodemailer from \"nodemailer\";\nimport type SMTPTransport from \"nodemailer/lib/smtp-transport\";\nimport { MailTransport } from \"~/domain/MailTransport/abstractions.js\";\n\nexport class SmtpMailTransport implements MailTransport.Interface {\n public readonly name = \"Mailer/SmtpTransport\";\n private readonly transporter: Transporter<SMTPTransport.SentMessageInfo>;\n\n constructor(config: SMTPTransport.Options) {\n this.transporter = nodemailer.createTransport(config);\n }\n\n async send(params: MailTransport.SendParams) {\n const { replyTo, text, html, to, bcc, cc, from, subject } = params;\n\n try {\n const result = await this.transporter.sendMail({\n replyTo,\n bcc,\n cc,\n from,\n text,\n html,\n to,\n subject\n });\n\n if (result.messageId) {\n return {\n result: result.response,\n error: null\n };\n }\n\n return {\n result: null,\n error: {\n message:\n \"nodemailer.sendMail does not have a messageId in the result. Something went wrong...\",\n code: \"MAILER_ERROR\",\n data: {\n ...result\n }\n }\n };\n } catch (ex: any) {\n // Allow-list specific nodemailer/SMTP error fields. Spreading `ex`\n // or `ex.data` blindly would risk surfacing the transporter's auth\n // config (or anything else a future nodemailer version stamps onto\n // its errors) in error responses.\n return {\n result: null,\n error: {\n message: ex.message,\n code: ex.code,\n data: {\n ...params,\n command: ex.command,\n response: ex.response,\n responseCode: ex.responseCode\n }\n }\n };\n }\n }\n}\n"],"mappings":"AACA,OAAOA,UAAU,MAAM,YAAY;AAInC,OAAO,MAAMC,iBAAiB,CAAoC;EAC9CC,IAAI,GAAG,sBAAsB;EAG7CC,WAAWA,CAACC,MAA6B,EAAE;IACvC,IAAI,CAACC,WAAW,GAAGL,UAAU,CAACM,eAAe,CAACF,MAAM,CAAC;EACzD;EAEA,MAAMG,IAAIA,CAACC,MAAgC,EAAE;IACzC,MAAM;MAAEC,OAAO;MAAEC,IAAI;MAAEC,IAAI;MAAEC,EAAE;MAAEC,GAAG;MAAEC,EAAE;MAAEC,IAAI;MAAEC;IAAQ,CAAC,GAAGR,MAAM;IAElE,IAAI;MACA,MAAMS,MAAM,GAAG,MAAM,IAAI,CAACZ,WAAW,CAACa,QAAQ,CAAC;QAC3CT,OAAO;QACPI,GAAG;QACHC,EAAE;QACFC,IAAI;QACJL,IAAI;QACJC,IAAI;QACJC,EAAE;QACFI;MACJ,CAAC,CAAC;MAEF,IAAIC,MAAM,CAACE,SAAS,EAAE;QAClB,OAAO;UACHF,MAAM,EAAEA,MAAM,CAACG,QAAQ;UACvBC,KAAK,EAAE;QACX,CAAC;MACL;MAEA,OAAO;QACHJ,MAAM,EAAE,IAAI;QACZI,KAAK,EAAE;UACHC,OAAO,EACH,sFAAsF;UAC1FC,IAAI,EAAE,cAAc;UACpBC,IAAI,EAAE;YACF,GAAGP;UACP;QACJ;MACJ,CAAC;IACL,CAAC,CAAC,OAAOQ,EAAO,EAAE;MACd;MACA;MACA;MACA;MACA,OAAO;QACHR,MAAM,EAAE,IAAI;QACZI,KAAK,EAAE;UACHC,OAAO,EAAEG,EAAE,CAACH,OAAO;UACnBC,IAAI,EAAEE,EAAE,CAACF,IAAI;UACbC,IAAI,EAAE;YACF,GAAGhB,MAAM;YACTkB,OAAO,EAAED,EAAE,CAACC,OAAO;YACnBN,QAAQ,EAAEK,EAAE,CAACL,QAAQ;YACrBO,YAAY,EAAEF,EAAE,CAACE;UACrB;QACJ;MACJ,CAAC;IACL;EACJ;AACJ","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  import { MailTransportFactory } from "../../domain/MailTransport/abstractions.js";
2
2
  import type { TransportSettings } from "../../types.js";
3
3
  declare class SmtpMailTransportFactoryImpl implements MailTransportFactory.Interface {
4
+ readonly name = "Mailer/SmtpTransport";
4
5
  createTransport(settings: TransportSettings): MailTransportFactory.Return;
5
6
  }
6
7
  export declare const SmtpMailTransportFactory: typeof SmtpMailTransportFactoryImpl & {
@@ -2,6 +2,7 @@ import { MailTransportFactory } from "../../domain/MailTransport/abstractions.js
2
2
  import { SmtpMailTransport } from "./SmtpMailTransport.js";
3
3
  import { SmtpConfig } from "./SmtpConfig.js";
4
4
  class SmtpMailTransportFactoryImpl {
5
+ name = "Mailer/SmtpTransport";
5
6
  async createTransport(settings) {
6
7
  return new SmtpMailTransport(SmtpConfig.fromTransportSettings(settings));
7
8
  }
@@ -1 +1 @@
1
- {"version":3,"names":["MailTransportFactory","SmtpMailTransport","SmtpConfig","SmtpMailTransportFactoryImpl","createTransport","settings","fromTransportSettings","SmtpMailTransportFactory","createImplementation","implementation","dependencies"],"sources":["SmtpMailTransportFactory.ts"],"sourcesContent":["import { MailTransportFactory } from \"~/domain/MailTransport/abstractions.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport { SmtpMailTransport } from \"~/features/SmtpTransport/SmtpMailTransport.js\";\nimport { SmtpConfig } from \"~/features/SmtpTransport/SmtpConfig.js\";\n\nclass SmtpMailTransportFactoryImpl implements MailTransportFactory.Interface {\n async createTransport(settings: TransportSettings): MailTransportFactory.Return {\n return new SmtpMailTransport(SmtpConfig.fromTransportSettings(settings));\n }\n}\n\nexport const SmtpMailTransportFactory = MailTransportFactory.createImplementation({\n implementation: SmtpMailTransportFactoryImpl,\n dependencies: []\n});\n"],"mappings":"AAAA,SAASA,oBAAoB;AAE7B,SAASC,iBAAiB;AAC1B,SAASC,UAAU;AAEnB,MAAMC,4BAA4B,CAA2C;EACzE,MAAMC,eAAeA,CAACC,QAA2B,EAA+B;IAC5E,OAAO,IAAIJ,iBAAiB,CAACC,UAAU,CAACI,qBAAqB,CAACD,QAAQ,CAAC,CAAC;EAC5E;AACJ;AAEA,OAAO,MAAME,wBAAwB,GAAGP,oBAAoB,CAACQ,oBAAoB,CAAC;EAC9EC,cAAc,EAAEN,4BAA4B;EAC5CO,YAAY,EAAE;AAClB,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["MailTransportFactory","SmtpMailTransport","SmtpConfig","SmtpMailTransportFactoryImpl","name","createTransport","settings","fromTransportSettings","SmtpMailTransportFactory","createImplementation","implementation","dependencies"],"sources":["SmtpMailTransportFactory.ts"],"sourcesContent":["import { MailTransportFactory } from \"~/domain/MailTransport/abstractions.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport { SmtpMailTransport } from \"~/features/SmtpTransport/SmtpMailTransport.js\";\nimport { SmtpConfig } from \"~/features/SmtpTransport/SmtpConfig.js\";\n\nclass SmtpMailTransportFactoryImpl implements MailTransportFactory.Interface {\n public readonly name = \"Mailer/SmtpTransport\";\n\n async createTransport(settings: TransportSettings): MailTransportFactory.Return {\n return new SmtpMailTransport(SmtpConfig.fromTransportSettings(settings));\n }\n}\n\nexport const SmtpMailTransportFactory = MailTransportFactory.createImplementation({\n implementation: SmtpMailTransportFactoryImpl,\n dependencies: []\n});\n"],"mappings":"AAAA,SAASA,oBAAoB;AAE7B,SAASC,iBAAiB;AAC1B,SAASC,UAAU;AAEnB,MAAMC,4BAA4B,CAA2C;EACzDC,IAAI,GAAG,sBAAsB;EAE7C,MAAMC,eAAeA,CAACC,QAA2B,EAA+B;IAC5E,OAAO,IAAIL,iBAAiB,CAACC,UAAU,CAACK,qBAAqB,CAACD,QAAQ,CAAC,CAAC;EAC5E;AACJ;AAEA,OAAO,MAAME,wBAAwB,GAAGR,oBAAoB,CAACS,oBAAoB,CAAC;EAC9EC,cAAc,EAAEP,4BAA4B;EAC5CQ,YAAY,EAAE;AAClB,CAAC,CAAC","ignoreList":[]}