@venizia/ignis 0.4.6 → 0.4.7-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/LICENSE.md +1 -4
- package/README.md +2 -2
- package/dist/esm/base/applications/base.d.ts.map +1 -1
- package/dist/esm/base/applications/base.js +19 -15
- package/dist/esm/base/applications/base.js.map +1 -1
- package/dist/esm/base/applications/server.d.ts +14 -9
- package/dist/esm/base/applications/server.d.ts.map +1 -1
- package/dist/esm/base/applications/server.js +36 -29
- package/dist/esm/base/applications/server.js.map +1 -1
- package/dist/esm/base/controllers/grpc/adapter.d.ts.map +1 -1
- package/dist/esm/base/controllers/grpc/adapter.js +5 -1
- package/dist/esm/base/controllers/grpc/adapter.js.map +1 -1
- package/dist/esm/base/middlewares/request-spy/request-spy.middleware.d.ts.map +1 -1
- package/dist/esm/base/middlewares/request-spy/request-spy.middleware.js +9 -3
- package/dist/esm/base/middlewares/request-spy/request-spy.middleware.js.map +1 -1
- package/dist/esm/common/constants.d.ts.map +1 -1
- package/dist/esm/common/constants.js +2 -2
- package/dist/esm/common/constants.js.map +1 -1
- package/dist/esm/components/api-reference/ui/scalar.d.ts.map +1 -1
- package/dist/esm/components/api-reference/ui/scalar.js +2 -1
- package/dist/esm/components/api-reference/ui/scalar.js.map +1 -1
- package/dist/esm/components/api-reference/ui/swagger.d.ts.map +1 -1
- package/dist/esm/components/api-reference/ui/swagger.js +2 -1
- package/dist/esm/components/api-reference/ui/swagger.js.map +1 -1
- package/dist/esm/components/auth/authenticate/component.js +2 -2
- package/dist/esm/components/auth/authenticate/component.js.map +1 -1
- package/dist/esm/components/auth/authenticate/controllers/factory.d.ts +139 -136
- package/dist/esm/components/auth/authenticate/controllers/factory.d.ts.map +1 -1
- package/dist/esm/components/auth/authenticate/controllers/factory.js +175 -172
- package/dist/esm/components/auth/authenticate/controllers/factory.js.map +1 -1
- package/dist/esm/components/auth/authenticate/controllers/jwks/definitions.js +2 -2
- package/dist/esm/components/auth/authenticate/controllers/jwks/definitions.js.map +1 -1
- package/dist/esm/components/auth/authenticate/controllers/service-certs/definitions.js +2 -2
- package/dist/esm/components/auth/authenticate/controllers/service-certs/definitions.js.map +1 -1
- package/dist/esm/components/auth/authenticate/services/bearer/abstract.service.d.ts.map +1 -1
- package/dist/esm/components/auth/authenticate/services/bearer/abstract.service.js +4 -2
- package/dist/esm/components/auth/authenticate/services/bearer/abstract.service.js.map +1 -1
- package/dist/esm/components/auth/authenticate/services/service/signer.service.d.ts.map +1 -1
- package/dist/esm/components/auth/authenticate/services/service/signer.service.js +6 -4
- package/dist/esm/components/auth/authenticate/services/service/signer.service.js.map +1 -1
- package/dist/esm/components/auth/authorize/adapters/base-filtered.js +2 -2
- package/dist/esm/components/auth/authorize/adapters/base-filtered.js.map +1 -1
- package/dist/esm/components/auth/authorize/adapters/custom-grant-expander.d.ts.map +1 -1
- package/dist/esm/components/auth/authorize/adapters/custom-grant-expander.js +2 -2
- package/dist/esm/components/auth/authorize/adapters/custom-grant-expander.js.map +1 -1
- package/dist/esm/components/auth/authorize/adapters/scoped-casbin/adapter.d.ts.map +1 -1
- package/dist/esm/components/auth/authorize/adapters/scoped-casbin/adapter.js +6 -3
- package/dist/esm/components/auth/authorize/adapters/scoped-casbin/adapter.js.map +1 -1
- package/dist/esm/components/auth/authorize/enforcers/casbin-module.d.ts.map +1 -1
- package/dist/esm/components/auth/authorize/enforcers/casbin-module.js +2 -1
- package/dist/esm/components/auth/authorize/enforcers/casbin-module.js.map +1 -1
- package/dist/esm/components/auth/authorize/enforcers/casbin.enforcer.d.ts.map +1 -1
- package/dist/esm/components/auth/authorize/enforcers/casbin.enforcer.js +9 -3
- package/dist/esm/components/auth/authorize/enforcers/casbin.enforcer.js.map +1 -1
- package/dist/esm/components/auth/models/entities/columns.d.ts +99 -0
- package/dist/esm/components/auth/models/entities/columns.d.ts.map +1 -0
- package/dist/esm/components/auth/models/entities/columns.js +133 -0
- package/dist/esm/components/auth/models/entities/columns.js.map +1 -0
- package/dist/esm/components/auth/models/entities/index.d.ts +1 -2
- package/dist/esm/components/auth/models/entities/index.d.ts.map +1 -1
- package/dist/esm/components/auth/models/entities/index.js +1 -2
- package/dist/esm/components/auth/models/entities/index.js.map +1 -1
- package/dist/esm/components/auth/models/entities/permission.model.d.ts +1 -12
- package/dist/esm/components/auth/models/entities/permission.model.d.ts.map +1 -1
- package/dist/esm/components/auth/models/entities/permission.model.js +1 -36
- package/dist/esm/components/auth/models/entities/permission.model.js.map +1 -1
- package/dist/esm/components/auth/models/entities/policy-definition.model.d.ts +1 -49
- package/dist/esm/components/auth/models/entities/policy-definition.model.d.ts.map +1 -1
- package/dist/esm/components/auth/models/entities/policy-definition.model.js +1 -69
- package/dist/esm/components/auth/models/entities/policy-definition.model.js.map +1 -1
- package/dist/esm/components/controller/grpc/grpc.component.js +2 -2
- package/dist/esm/components/controller/grpc/grpc.component.js.map +1 -1
- package/dist/esm/components/health-check/component.d.ts.map +1 -1
- package/dist/esm/components/health-check/component.js +5 -3
- package/dist/esm/components/health-check/component.js.map +1 -1
- package/dist/esm/components/health-check/controller.js +5 -5
- package/dist/esm/components/health-check/controller.js.map +1 -1
- package/dist/esm/components/index.d.ts +0 -1
- package/dist/esm/components/index.d.ts.map +1 -1
- package/dist/esm/components/index.js +0 -1
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/components/mail/helpers/executors/bull-mq-executor.helper.d.ts.map +1 -1
- package/dist/esm/components/mail/helpers/executors/bull-mq-executor.helper.js +2 -1
- package/dist/esm/components/mail/helpers/executors/bull-mq-executor.helper.js.map +1 -1
- package/dist/esm/components/mail/helpers/transporters/amazon-ses-transporter.helper.d.ts.map +1 -1
- package/dist/esm/components/mail/helpers/transporters/amazon-ses-transporter.helper.js +13 -9
- package/dist/esm/components/mail/helpers/transporters/amazon-ses-transporter.helper.js.map +1 -1
- package/dist/esm/components/mail/helpers/transporters/mailgun-transporter.helper.d.ts.map +1 -1
- package/dist/esm/components/mail/helpers/transporters/mailgun-transporter.helper.js +5 -3
- package/dist/esm/components/mail/helpers/transporters/mailgun-transporter.helper.js.map +1 -1
- package/dist/esm/components/mail/helpers/transporters/nodemail-transporter.helper.d.ts.map +1 -1
- package/dist/esm/components/mail/helpers/transporters/nodemail-transporter.helper.js +9 -7
- package/dist/esm/components/mail/helpers/transporters/nodemail-transporter.helper.js.map +1 -1
- package/dist/esm/components/mail/services/generators/verification-data.d.ts.map +1 -1
- package/dist/esm/components/mail/services/generators/verification-data.js +7 -3
- package/dist/esm/components/mail/services/generators/verification-data.js.map +1 -1
- package/dist/esm/components/mail/services/mail.service.d.ts.map +1 -1
- package/dist/esm/components/mail/services/mail.service.js +12 -9
- package/dist/esm/components/mail/services/mail.service.js.map +1 -1
- package/dist/esm/components/mail/utilities/address.utility.d.ts +12 -8
- package/dist/esm/components/mail/utilities/address.utility.d.ts.map +1 -1
- package/dist/esm/components/mail/utilities/address.utility.js +30 -27
- package/dist/esm/components/mail/utilities/address.utility.js.map +1 -1
- package/dist/esm/components/mail/utilities/attachment.utility.d.ts +31 -29
- package/dist/esm/components/mail/utilities/attachment.utility.d.ts.map +1 -1
- package/dist/esm/components/mail/utilities/attachment.utility.js +94 -86
- package/dist/esm/components/mail/utilities/attachment.utility.js.map +1 -1
- package/dist/esm/components/mail/utilities/body.utility.d.ts +6 -4
- package/dist/esm/components/mail/utilities/body.utility.d.ts.map +1 -1
- package/dist/esm/components/mail/utilities/body.utility.js +14 -12
- package/dist/esm/components/mail/utilities/body.utility.js.map +1 -1
- package/dist/esm/components/mail/utilities/mime.utility.d.ts +23 -17
- package/dist/esm/components/mail/utilities/mime.utility.d.ts.map +1 -1
- package/dist/esm/components/mail/utilities/mime.utility.js +109 -98
- package/dist/esm/components/mail/utilities/mime.utility.js.map +1 -1
- package/dist/esm/components/mail/utilities/verification.utility.d.ts +8 -2
- package/dist/esm/components/mail/utilities/verification.utility.d.ts.map +1 -1
- package/dist/esm/components/mail/utilities/verification.utility.js +7 -5
- package/dist/esm/components/mail/utilities/verification.utility.js.map +1 -1
- package/dist/esm/components/socket-io/component.js +3 -3
- package/dist/esm/components/socket-io/component.js.map +1 -1
- package/dist/esm/components/socket-io/handlers/bun.handler.d.ts +13 -11
- package/dist/esm/components/socket-io/handlers/bun.handler.d.ts.map +1 -1
- package/dist/esm/components/socket-io/handlers/bun.handler.js +32 -30
- package/dist/esm/components/socket-io/handlers/bun.handler.js.map +1 -1
- package/dist/esm/components/static-asset/common/commit-token.d.ts +21 -16
- package/dist/esm/components/static-asset/common/commit-token.d.ts.map +1 -1
- package/dist/esm/components/static-asset/common/commit-token.js +35 -28
- package/dist/esm/components/static-asset/common/commit-token.js.map +1 -1
- package/dist/esm/components/static-asset/common/constants.d.ts +0 -2
- package/dist/esm/components/static-asset/common/constants.d.ts.map +1 -1
- package/dist/esm/components/static-asset/common/constants.js +1 -3
- package/dist/esm/components/static-asset/common/constants.js.map +1 -1
- package/dist/esm/components/static-asset/common/types.d.ts +0 -4
- package/dist/esm/components/static-asset/common/types.d.ts.map +1 -1
- package/dist/esm/components/static-asset/common/types.js.map +1 -1
- package/dist/esm/components/static-asset/component.js +2 -2
- package/dist/esm/components/static-asset/component.js.map +1 -1
- package/dist/esm/components/static-asset/controller/base.definition.d.ts +6 -6
- package/dist/esm/components/static-asset/controller/base.definition.d.ts.map +1 -1
- package/dist/esm/components/static-asset/controller/base.definition.js +224 -224
- package/dist/esm/components/static-asset/controller/base.definition.js.map +1 -1
- package/dist/esm/components/static-asset/controller/factory.d.ts +23 -23
- package/dist/esm/components/static-asset/controller/factory.d.ts.map +1 -1
- package/dist/esm/components/static-asset/controller/factory.js +104 -74
- package/dist/esm/components/static-asset/controller/factory.js.map +1 -1
- package/dist/esm/components/static-asset/controller/key-scope.d.ts +28 -26
- package/dist/esm/components/static-asset/controller/key-scope.d.ts.map +1 -1
- package/dist/esm/components/static-asset/controller/key-scope.js +34 -30
- package/dist/esm/components/static-asset/controller/key-scope.js.map +1 -1
- package/dist/esm/components/static-asset/controller/meta-link.d.ts +37 -33
- package/dist/esm/components/static-asset/controller/meta-link.d.ts.map +1 -1
- package/dist/esm/components/static-asset/controller/meta-link.js +86 -84
- package/dist/esm/components/static-asset/controller/meta-link.js.map +1 -1
- package/dist/esm/components/static-asset/controller/route-options.d.ts +18 -16
- package/dist/esm/components/static-asset/controller/route-options.d.ts.map +1 -1
- package/dist/esm/components/static-asset/controller/route-options.js +28 -26
- package/dist/esm/components/static-asset/controller/route-options.js.map +1 -1
- package/dist/esm/components/static-asset/models/base.model.js +3 -3
- package/dist/esm/components/static-asset/models/base.model.js.map +1 -1
- package/dist/esm/components/websocket/component.js +2 -2
- package/dist/esm/components/websocket/component.js.map +1 -1
- package/dist/esm/components/websocket/handlers/bun.handler.d.ts +6 -4
- package/dist/esm/components/websocket/handlers/bun.handler.d.ts.map +1 -1
- package/dist/esm/components/websocket/handlers/bun.handler.js +21 -19
- package/dist/esm/components/websocket/handlers/bun.handler.js.map +1 -1
- package/dist/esm/testing/assert-application-boots.d.ts +6 -1
- package/dist/esm/testing/assert-application-boots.d.ts.map +1 -1
- package/dist/esm/testing/assert-application-boots.js +139 -129
- package/dist/esm/testing/assert-application-boots.js.map +1 -1
- package/dist/esm/utilities/drizzle-result.utility.d.ts +6 -8
- package/dist/esm/utilities/drizzle-result.utility.d.ts.map +1 -1
- package/dist/esm/utilities/drizzle-result.utility.js +23 -49
- package/dist/esm/utilities/drizzle-result.utility.js.map +1 -1
- package/dist/esm/utilities/network.utility.d.ts.map +1 -1
- package/dist/esm/utilities/network.utility.js +1 -1
- package/dist/esm/utilities/network.utility.js.map +1 -1
- package/dist/presets/app/files/src/boot.test.ts +2 -2
- package/dist/presets/app/files/src/controllers/hello.controller.ts +2 -2
- package/dist/presets/app/preset.json +4 -4
- package/dist/presets/lib/preset.json +4 -4
- package/dist/presets/shared/files/.configs/formatters/.ignore +4 -0
- package/dist/presets/shared/files/.configs/lints/.ignore +4 -0
- package/dist/presets/shared/files/.configs/lints/eslint.config.mjs +4 -0
- package/dist/presets/shared/files/.configs/lints/oxlint.config.mts +4 -0
- package/dist/presets/shared/files/README.md +15 -0
- package/dist/presets/shared/files/src/index.test.ts +8 -0
- package/dist/presets/shared/files/src/index.ts +8 -0
- package/dist/presets/shared/files/tsconfig.json +20 -0
- package/dist/presets/shared/preset.json +35 -0
- package/package.json +11 -11
- package/dist/esm/components/auth/models/entities/role.model.d.ts +0 -10
- package/dist/esm/components/auth/models/entities/role.model.d.ts.map +0 -1
- package/dist/esm/components/auth/models/entities/role.model.js +0 -15
- package/dist/esm/components/auth/models/entities/role.model.js.map +0 -1
- package/dist/esm/components/auth/models/entities/user.model.d.ts +0 -28
- package/dist/esm/components/auth/models/entities/user.model.d.ts.map +0 -1
- package/dist/esm/components/auth/models/entities/user.model.js +0 -17
- package/dist/esm/components/auth/models/entities/user.model.js.map +0 -1
- package/dist/esm/components/controller/index.d.ts +0 -2
- package/dist/esm/components/controller/index.d.ts.map +0 -1
- package/dist/esm/components/controller/index.js +0 -7
- package/dist/esm/components/controller/index.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { HTTP } from '@venizia/ignis-helpers/common';
|
|
|
2
2
|
import { BaseHelper, getError } from '@venizia/ignis-helpers/core';
|
|
3
3
|
import { ModuleUtility } from '@venizia/ignis-helpers';
|
|
4
4
|
import { MailErrorCodes } from '../../common/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { MailAttachmentUtility } from '../../utilities/attachment.utility.js';
|
|
6
6
|
export class MailgunTransportHelper extends BaseHelper {
|
|
7
7
|
constructor(opts) {
|
|
8
8
|
super({ scope: MailgunTransportHelper.name });
|
|
@@ -59,7 +59,9 @@ export class MailgunTransportHelper extends BaseHelper {
|
|
|
59
59
|
}
|
|
60
60
|
if (message.attachments && message.attachments.length > 0) {
|
|
61
61
|
// No root: MailService resolved paths already; one that reaches here is refused, not read.
|
|
62
|
-
const attachments = await
|
|
62
|
+
const attachments = await MailAttachmentUtility.resolve({
|
|
63
|
+
attachments: message.attachments,
|
|
64
|
+
});
|
|
63
65
|
mailgunMessage.attachment = attachments.map((attachment) => {
|
|
64
66
|
return { filename: attachment.filename, data: attachment.content };
|
|
65
67
|
});
|
|
@@ -74,7 +76,7 @@ export class MailgunTransportHelper extends BaseHelper {
|
|
|
74
76
|
}
|
|
75
77
|
catch (error) {
|
|
76
78
|
this.logger.for(this.send.name).error('Mailgun send failed: %s', error);
|
|
77
|
-
|
|
79
|
+
MailAttachmentUtility.release({ attachments: message.attachments });
|
|
78
80
|
return {
|
|
79
81
|
success: false,
|
|
80
82
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mailgun-transporter.helper.js","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/transporters/mailgun-transporter.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AASvD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"mailgun-transporter.helper.js","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/transporters/mailgun-transporter.helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { HTTP } from '@venizia/ignis-helpers/common';\nimport type { AnyType } from '@venizia/ignis-helpers/common';\nimport { BaseHelper, getError } from '@venizia/ignis-helpers/core';\nimport { ModuleUtility } from '@venizia/ignis-helpers';\nimport type {\n IMailAttachment,\n IMailMessage,\n IMailSendResult,\n IMailTransport,\n TMailgunConfig,\n TMailgunModule,\n} from '../../common';\nimport { MailErrorCodes } from '../../common';\nimport { MailAttachmentUtility } from '../../utilities/attachment.utility';\n\nexport class MailgunTransportHelper extends BaseHelper implements IMailTransport {\n private client: AnyType; // IMessagesClient from mailgun.js\n private domain: string;\n private module?: TMailgunModule;\n\n constructor(opts: { config: TMailgunConfig; module?: TMailgunModule }) {\n super({ scope: MailgunTransportHelper.name });\n\n this.module = opts.module;\n this.configure(opts.config);\n }\n\n configure(config: TMailgunConfig) {\n this.validateConfig(config);\n\n this.domain = config.domain;\n this.client = this.buildClient(config);\n }\n\n /** Credentials and domain are checked here, not on the first send; the error never echoes a credential value back. */\n private validateConfig(config: TMailgunConfig): void {\n const missingKeys = (['username', 'key', 'domain'] as const).filter((key) => {\n return !config?.[key];\n });\n\n if (missingKeys.length === 0) {\n return;\n }\n\n this.logger\n .for(this.configure.name)\n .error('Invalid Mailgun configuration | Missing keys: %s', missingKeys.join(', '));\n\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.INVALID_CONFIGURATION,\n message: `Invalid Mailgun configuration | Missing required keys: ${missingKeys.join(', ')}`,\n });\n }\n\n /** Client factory seam - overridden in tests to run the helper without the mailgun.js peer. */\n protected buildClient(config: TMailgunConfig): AnyType {\n const Mailgun = this.module ?? ModuleUtility.loadSync<AnyType>({ module: 'mailgun.js' });\n const mailgun = new Mailgun(FormData);\n const client = mailgun.client(config);\n\n return client.messages;\n }\n\n async send(message: IMailMessage): Promise<IMailSendResult> {\n try {\n const mailgunMessage: AnyType = {\n from: message.from,\n to: Array.isArray(message.to) ? message.to : [message.to],\n subject: message.subject,\n text: message.text,\n html: message.html,\n cc: message.cc,\n bcc: message.bcc,\n };\n\n if (message.replyTo) {\n mailgunMessage['h:Reply-To'] = message.replyTo;\n }\n\n if (message.headers) {\n Object.entries(message.headers).forEach(([key, value]) => {\n mailgunMessage[`h:${key}`] = value;\n });\n }\n\n if (message.attachments && message.attachments.length > 0) {\n // No root: MailService resolved paths already; one that reaches here is refused, not read.\n const attachments = await MailAttachmentUtility.resolve({\n attachments: message.attachments,\n });\n\n mailgunMessage.attachment = attachments.map((attachment: IMailAttachment) => {\n return { filename: attachment.filename, data: attachment.content };\n });\n }\n\n this.logger.for(this.send.name).debug('Sending email with Mailgun to: %s', mailgunMessage.to);\n const result: AnyType = await this.client.create(this.domain, mailgunMessage);\n\n return {\n success: true,\n messageId: result.id,\n response: result,\n };\n } catch (error) {\n this.logger.for(this.send.name).error('Mailgun send failed: %s', error);\n MailAttachmentUtility.release({ attachments: message.attachments });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async verify(): Promise<boolean> {\n try {\n this.logger.for(this.verify.name).info('Verifying Mailgun API connection');\n // Mailgun has no verify endpoint - a test-mode send is the lightweight credential check.\n await this.client.create(this.domain, {\n from: 'verify@' + this.domain,\n to: ['verify@' + this.domain],\n subject: 'Verification Test',\n text: 'This is a verification test',\n 'o:testmode': 'yes', // Use test mode to avoid actually sending\n });\n\n this.logger.for(this.verify.name).info('Mailgun API connection verified successfully');\n return true;\n } catch (error) {\n this.logger.for(this.verify.name).error('Mailgun API verification failed: %s', error);\n return false;\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodemail-transporter.helper.d.ts","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/transporters/nodemail-transporter.helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"nodemail-transporter.helper.d.ts","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/transporters/nodemail-transporter.helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AAItB,qBAAa,yBAA0B,SAAQ,UAAW,YAAW,cAAc;IACjF,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,MAAM,CAAC,CAAoB;gBAEvB,IAAI,EAAE;QAAE,MAAM,EAAE,iBAAiB,CAAC;QAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;KAAE;IAO3E,SAAS,CAAC,MAAM,EAAE,iBAAiB;IAInC,8FAA8F;IAC9F,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO;IAKxD,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IA6CrD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAY1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseHelper } from '@venizia/ignis-helpers/core';
|
|
2
2
|
import { ModuleUtility } from '@venizia/ignis-helpers';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { MailAttachmentUtility } from '../../utilities/attachment.utility.js';
|
|
4
|
+
import { MailBodyUtility } from '../../utilities/body.utility.js';
|
|
5
5
|
export class NodemailerTransportHelper extends BaseHelper {
|
|
6
6
|
constructor(opts) {
|
|
7
7
|
super({ scope: NodemailerTransportHelper.name });
|
|
@@ -18,11 +18,13 @@ export class NodemailerTransportHelper extends BaseHelper {
|
|
|
18
18
|
}
|
|
19
19
|
async send(message) {
|
|
20
20
|
try {
|
|
21
|
-
|
|
21
|
+
MailBodyUtility.assertIsText({ message });
|
|
22
22
|
// No root: MailService resolved paths already; one that reaches here is refused, not read.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
:
|
|
23
|
+
let attachments;
|
|
24
|
+
if (message.attachments) {
|
|
25
|
+
const resolved = await MailAttachmentUtility.resolve({ attachments: message.attachments });
|
|
26
|
+
attachments = resolved;
|
|
27
|
+
}
|
|
26
28
|
const mailOptions = {
|
|
27
29
|
from: message.from,
|
|
28
30
|
to: Array.isArray(message.to) ? message.to.join(', ') : message.to,
|
|
@@ -48,7 +50,7 @@ export class NodemailerTransportHelper extends BaseHelper {
|
|
|
48
50
|
}
|
|
49
51
|
catch (error) {
|
|
50
52
|
this.logger.for(this.send.name).error('Nodemailer send failed: %s', error);
|
|
51
|
-
|
|
53
|
+
MailAttachmentUtility.release({ attachments: message.attachments });
|
|
52
54
|
return {
|
|
53
55
|
success: false,
|
|
54
56
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodemail-transporter.helper.js","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/transporters/nodemail-transporter.helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAQvD,OAAO,
|
|
1
|
+
{"version":3,"file":"nodemail-transporter.helper.js","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/transporters/nodemail-transporter.helper.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnyType } from '@venizia/ignis-helpers/common';\nimport { BaseHelper } from '@venizia/ignis-helpers/core';\nimport { ModuleUtility } from '@venizia/ignis-helpers';\nimport type {\n IMailMessage,\n IMailSendResult,\n IMailTransport,\n TNodemailerConfig,\n TNodemailerModule,\n} from '../../common';\nimport { MailAttachmentUtility } from '../../utilities/attachment.utility';\nimport { MailBodyUtility } from '../../utilities/body.utility';\n\nexport class NodemailerTransportHelper extends BaseHelper implements IMailTransport {\n private transporter: AnyType;\n private module?: TNodemailerModule;\n\n constructor(opts: { config: TNodemailerConfig; module?: TNodemailerModule }) {\n super({ scope: NodemailerTransportHelper.name });\n\n this.module = opts.module;\n this.configure(opts.config);\n }\n\n configure(config: TNodemailerConfig) {\n this.transporter = this.buildTransporter(config);\n }\n\n /** Client factory seam - overridden in tests to run the helper without a real SMTP client. */\n protected buildTransporter(config: TNodemailerConfig): AnyType {\n const nodemailer = this.module ?? ModuleUtility.loadSync<AnyType>({ module: 'nodemailer' });\n return nodemailer.createTransport(config);\n }\n\n async send(message: IMailMessage): Promise<IMailSendResult> {\n try {\n MailBodyUtility.assertIsText({ message });\n\n // No root: MailService resolved paths already; one that reaches here is refused, not read.\n let attachments: Awaited<ReturnType<typeof MailAttachmentUtility.resolve>> | undefined;\n if (message.attachments) {\n const resolved = await MailAttachmentUtility.resolve({ attachments: message.attachments });\n attachments = resolved;\n }\n\n const mailOptions = {\n from: message.from,\n to: Array.isArray(message.to) ? message.to.join(', ') : message.to,\n cc: message.cc,\n bcc: message.bcc,\n replyTo: message.replyTo,\n subject: message.subject,\n text: message.text,\n html: message.html,\n attachments,\n headers: message.headers,\n // Nodemailer's own switches: no field it is handed can make it open a file or fetch a URL.\n disableFileAccess: true,\n disableUrlAccess: true,\n };\n\n this.logger.for(this.send.name).debug('Sending email with nodemailer to: %s', mailOptions.to);\n const info = await this.transporter.sendMail(mailOptions);\n\n return {\n success: true,\n messageId: info.messageId,\n response: info.response,\n };\n } catch (error) {\n this.logger.for(this.send.name).error('Nodemailer send failed: %s', error);\n MailAttachmentUtility.release({ attachments: message.attachments });\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async verify(): Promise<boolean> {\n try {\n this.logger.for(this.verify.name).info('Verifying SMTP connection');\n await this.transporter.verify();\n this.logger.for(this.verify.name).info('SMTP connection verified successfully');\n return true;\n } catch (error) {\n this.logger.for(this.verify.name).error('SMTP verification failed: %s', error);\n return false;\n }\n }\n\n async close(): Promise<void> {\n this.logger.for(this.close.name).info('Closing nodemailer transport');\n this.transporter.close();\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-data.d.ts","sourceRoot":"","sources":["../../../../../../src/components/mail/services/generators/verification-data.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,KAAK,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,0BAA0B,EAC1B,8BAA8B,EAC9B,2BAA2B,EAC5B,MAAM,cAAc,CAAC;AAItB,qBAAa,gCACX,SAAQ,UACR,YAAW,0BAA0B;IAInC,OAAO,CAAC,aAAa;IAGrB,OAAO,CAAC,cAAc;gBAHd,aAAa,EAAE,0BAA0B,EAGzC,cAAc,EAAE,2BAA2B;IAKrD,wBAAwB,CAAC,OAAO,EAAE,8BAA8B,GAAG,iBAAiB;
|
|
1
|
+
{"version":3,"file":"verification-data.d.ts","sourceRoot":"","sources":["../../../../../../src/components/mail/services/generators/verification-data.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,KAAK,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,0BAA0B,EAC1B,8BAA8B,EAC9B,2BAA2B,EAC5B,MAAM,cAAc,CAAC;AAItB,qBAAa,gCACX,SAAQ,UACR,YAAW,0BAA0B;IAInC,OAAO,CAAC,aAAa;IAGrB,OAAO,CAAC,cAAc;gBAHd,aAAa,EAAE,0BAA0B,EAGzC,cAAc,EAAE,2BAA2B;IAKrD,wBAAwB,CAAC,OAAO,EAAE,8BAA8B,GAAG,iBAAiB;CAsBrF"}
|
|
@@ -14,7 +14,7 @@ var DefaultVerificationDataGenerator_1;
|
|
|
14
14
|
import { inject } from '../../../../base/metadata/index.js';
|
|
15
15
|
import { BaseHelper } from '@venizia/ignis-helpers/core';
|
|
16
16
|
import { MailKeys } from '../../common/index.js';
|
|
17
|
-
import {
|
|
17
|
+
import { MailVerificationUtility } from '../../utilities/index.js';
|
|
18
18
|
let DefaultVerificationDataGenerator = DefaultVerificationDataGenerator_1 = class DefaultVerificationDataGenerator extends BaseHelper {
|
|
19
19
|
constructor(codeGenerator, tokenGenerator) {
|
|
20
20
|
super({ scope: DefaultVerificationDataGenerator_1.name });
|
|
@@ -28,11 +28,15 @@ let DefaultVerificationDataGenerator = DefaultVerificationDataGenerator_1 = clas
|
|
|
28
28
|
return {
|
|
29
29
|
verificationCode: code,
|
|
30
30
|
codeGeneratedAt: now,
|
|
31
|
-
codeExpiresAt: getExpiryTime(
|
|
31
|
+
codeExpiresAt: MailVerificationUtility.getExpiryTime({
|
|
32
|
+
minutes: options.codeExpiryMinutes,
|
|
33
|
+
}).toISOString(),
|
|
32
34
|
codeAttempts: 0,
|
|
33
35
|
verificationToken: token,
|
|
34
36
|
tokenGeneratedAt: now,
|
|
35
|
-
tokenExpiresAt: getExpiryTimeInHours(
|
|
37
|
+
tokenExpiresAt: MailVerificationUtility.getExpiryTimeInHours({
|
|
38
|
+
hours: options.tokenExpiryHours,
|
|
39
|
+
}).toISOString(),
|
|
36
40
|
lastCodeSentAt: now,
|
|
37
41
|
};
|
|
38
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-data.js","sourceRoot":"","sources":["../../../../../../src/components/mail/services/generators/verification-data.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AASzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"verification-data.js","sourceRoot":"","sources":["../../../../../../src/components/mail/services/generators/verification-data.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AASzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,IAAa,gCAAgC,wCAA7C,MAAa,gCACX,SAAQ,UAAU;IAGlB,YAEU,aAAyC,EAGzC,cAA2C;QAEnD,KAAK,CAAC,EAAE,KAAK,EAAE,kCAAgC,CAAC,IAAI,EAAE,CAAC,CAAC;QALhD,kBAAa,GAAb,aAAa,CAA4B;QAGzC,mBAAc,GAAd,cAAc,CAA6B;IAGrD,CAAC;IAED,wBAAwB,CAAC,OAAuC;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,OAAO;YACL,gBAAgB,EAAE,IAAI;YACtB,eAAe,EAAE,GAAG;YACpB,aAAa,EAAE,uBAAuB,CAAC,aAAa,CAAC;gBACnD,OAAO,EAAE,OAAO,CAAC,iBAAiB;aACnC,CAAC,CAAC,WAAW,EAAE;YAChB,YAAY,EAAE,CAAC;YAEf,iBAAiB,EAAE,KAAK;YACxB,gBAAgB,EAAE,GAAG;YACrB,cAAc,EAAE,uBAAuB,CAAC,oBAAoB,CAAC;gBAC3D,KAAK,EAAE,OAAO,CAAC,gBAAgB;aAChC,CAAC,CAAC,WAAW,EAAE;YAEhB,cAAc,EAAE,GAAG;SACpB,CAAC;IACJ,CAAC;CACF,CAAA;AApCY,gCAAgC;IAKxC,WAAA,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,gCAAgC,EAAE,CAAC,CAAA;IAG1D,WAAA,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,iCAAiC,EAAE,CAAC,CAAA;;GARnD,gCAAgC,CAoC5C","sourcesContent":["import { inject } from '@/base/metadata';\nimport { BaseHelper } from '@venizia/ignis-helpers/core';\n// Interfaces are `import type`: with emitDecoratorMetadata on, a value import of a type-only name survives transpilation and the ESM named-import check fails at load.\nimport type {\n IVerificationCodeGenerator,\n IVerificationData,\n IVerificationDataGenerator,\n IVerificationGenerationOptions,\n IVerificationTokenGenerator,\n} from '../../common';\nimport { MailKeys } from '../../common';\nimport { MailVerificationUtility } from '../../utilities';\n\nexport class DefaultVerificationDataGenerator\n extends BaseHelper\n implements IVerificationDataGenerator\n{\n constructor(\n @inject({ key: MailKeys.MAIL_VERIFICATION_CODE_GENERATOR })\n private codeGenerator: IVerificationCodeGenerator,\n\n @inject({ key: MailKeys.MAIL_VERIFICATION_TOKEN_GENERATOR })\n private tokenGenerator: IVerificationTokenGenerator,\n ) {\n super({ scope: DefaultVerificationDataGenerator.name });\n }\n\n generateVerificationData(options: IVerificationGenerationOptions): IVerificationData {\n const code = this.codeGenerator.generateCode(options.codeLength);\n const token = this.tokenGenerator.generateToken(options.tokenBytes);\n const now = new Date().toISOString();\n\n return {\n verificationCode: code,\n codeGeneratedAt: now,\n codeExpiresAt: MailVerificationUtility.getExpiryTime({\n minutes: options.codeExpiryMinutes,\n }).toISOString(),\n codeAttempts: 0,\n\n verificationToken: token,\n tokenGeneratedAt: now,\n tokenExpiresAt: MailVerificationUtility.getExpiryTimeInHours({\n hours: options.tokenExpiryHours,\n }).toISOString(),\n\n lastCodeSentAt: now,\n };\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mail.service.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/services/mail.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,WAAW,CAAC;AAInB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAK7D,qBAAa,WAAY,SAAQ,WAAY,YAAW,YAAY;IAGhE,SAAS,CAAC,OAAO,EAAE,YAAY;IAE/B,SAAS,CAAC,SAAS,EAAE,cAAc;IAEnC,SAAS,CAAC,cAAc,CAAC,EAAE,mBAAmB;gBAJpC,OAAO,EAAE,YAAY,EAErB,SAAS,EAAE,cAAc,EAEzB,cAAc,CAAC,EAAE,mBAAmB,YAAA;IAQ1C,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mail.service.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/services/mail.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,WAAW,CAAC;AAInB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAK7D,qBAAa,WAAY,SAAQ,WAAY,YAAW,YAAY;IAGhE,SAAS,CAAC,OAAO,EAAE,YAAY;IAE/B,SAAS,CAAC,SAAS,EAAE,cAAc;IAEnC,SAAS,CAAC,cAAc,CAAC,EAAE,mBAAmB;gBAJpC,OAAO,EAAE,YAAY,EAErB,SAAS,EAAE,cAAc,EAEzB,cAAc,CAAC,EAAE,mBAAmB,YAAA;IAQ1C,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAkDrD,SAAS,CACb,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GACjC,OAAO,CAAC,eAAe,EAAE,CAAC;IA6CvB,YAAY,CAAC,IAAI,EAAE;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;KACjC,GAAG,OAAO,CAAC,eAAe,CAAC;IA4CtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAiBhC,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAyBtD,SAAS,CAAC,cAAc,IAAI,MAAM;CAcnC"}
|
|
@@ -16,9 +16,9 @@ import { BaseService } from '@venizia/ignis-kernel';
|
|
|
16
16
|
import { MailDefaults, MailErrorCodes, MailErrors, MailKeys } from '../common/index.js';
|
|
17
17
|
import { inject } from '../../../base/metadata/index.js';
|
|
18
18
|
import { getError, isApplicationError } from '@venizia/ignis-helpers/core';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
19
|
+
import { PromiseUtility } from '@venizia/ignis-helpers';
|
|
20
|
+
import { MailAttachmentUtility } from '../utilities/attachment.utility.js';
|
|
21
|
+
import { MailBodyUtility } from '../utilities/body.utility.js';
|
|
22
22
|
let MailService = MailService_1 = class MailService extends BaseService {
|
|
23
23
|
constructor(options, transport, templateEngine) {
|
|
24
24
|
super({ scope: MailService_1.name });
|
|
@@ -38,11 +38,12 @@ let MailService = MailService_1 = class MailService extends BaseService {
|
|
|
38
38
|
};
|
|
39
39
|
// The one place the attachment policy applies: every transport receives bytes, never a path.
|
|
40
40
|
if (message.attachments) {
|
|
41
|
-
|
|
41
|
+
const result2 = await MailAttachmentUtility.resolve({
|
|
42
42
|
attachments: message.attachments,
|
|
43
43
|
attachmentRoot: this.options.attachmentRoot,
|
|
44
44
|
maxBytes: this.options.maxAttachmentBytes ?? MailDefaults.MAX_ATTACHMENT_BYTES,
|
|
45
45
|
});
|
|
46
|
+
emailMessage.attachments = result2;
|
|
46
47
|
}
|
|
47
48
|
this.logger.for(this.send.name).debug('Sending email to: %s', emailMessage.to);
|
|
48
49
|
const result = await this.transport.send(emailMessage);
|
|
@@ -58,7 +59,7 @@ let MailService = MailService_1 = class MailService extends BaseService {
|
|
|
58
59
|
}
|
|
59
60
|
catch (error) {
|
|
60
61
|
this.logger.for(this.send.name).error('Error sending email: %s', error);
|
|
61
|
-
|
|
62
|
+
MailAttachmentUtility.release({ attachments: message.attachments });
|
|
62
63
|
// An error the framework already shaped carries its own status and message code; re-wrapping as 500 would report a caller mistake as a server fault.
|
|
63
64
|
if (isApplicationError(error)) {
|
|
64
65
|
throw error;
|
|
@@ -80,7 +81,8 @@ let MailService = MailService_1 = class MailService extends BaseService {
|
|
|
80
81
|
.info('Sending batch of %d emails with concurrency: %d', messages.length, concurrency);
|
|
81
82
|
const tasks = messages.map((message) => async () => {
|
|
82
83
|
try {
|
|
83
|
-
|
|
84
|
+
const result = await this.send(message);
|
|
85
|
+
return result;
|
|
84
86
|
}
|
|
85
87
|
catch (error) {
|
|
86
88
|
return {
|
|
@@ -89,7 +91,7 @@ let MailService = MailService_1 = class MailService extends BaseService {
|
|
|
89
91
|
};
|
|
90
92
|
}
|
|
91
93
|
});
|
|
92
|
-
const results = await
|
|
94
|
+
const results = await PromiseUtility.executeWithLimit({
|
|
93
95
|
tasks,
|
|
94
96
|
limit: concurrency,
|
|
95
97
|
});
|
|
@@ -139,7 +141,8 @@ let MailService = MailService_1 = class MailService extends BaseService {
|
|
|
139
141
|
html,
|
|
140
142
|
...options,
|
|
141
143
|
};
|
|
142
|
-
|
|
144
|
+
const result = await this.send(message);
|
|
145
|
+
return result;
|
|
143
146
|
}
|
|
144
147
|
catch (error) {
|
|
145
148
|
this.logger.for(this.sendTemplate.name).error('Error sending template email: %s', error);
|
|
@@ -182,7 +185,7 @@ let MailService = MailService_1 = class MailService extends BaseService {
|
|
|
182
185
|
message: 'Email must have either text or html content',
|
|
183
186
|
});
|
|
184
187
|
}
|
|
185
|
-
|
|
188
|
+
MailBodyUtility.assertIsText({ message });
|
|
186
189
|
}
|
|
187
190
|
getDefaultFrom() {
|
|
188
191
|
const { from, fromName } = this.options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mail.service.js","sourceRoot":"","sources":["../../../../../src/components/mail/services/mail.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { HTTP } from '@venizia/ignis-helpers/common';\nimport { BaseService } from '@venizia/ignis-kernel';\nimport type {\n IMailMessage,\n IMailSendResult,\n IMailService,\n IMailTemplateEngine,\n IMailTransport,\n TMailOptions,\n} from '../common';\nimport { MailDefaults, MailErrorCodes, MailErrors, MailKeys } from '../common';\nimport { inject } from '@/base/metadata';\nimport { getError, isApplicationError } from '@venizia/ignis-helpers/core';\nimport { type AnyType } from '@venizia/ignis-helpers/common';\nimport { executePromiseWithLimit } from '@venizia/ignis-helpers';\nimport { releaseAttachmentStreams, resolveMailAttachments } from '../utilities/attachment.utility';\nimport { assertMailBodyIsText } from '../utilities/body.utility';\n\nexport class MailService extends BaseService implements IMailService {\n constructor(\n @inject({ key: MailKeys.MAIL_OPTIONS })\n protected options: TMailOptions,\n @inject({ key: MailKeys.MAIL_TRANSPORT_INSTANCE })\n protected transport: IMailTransport,\n @inject({ key: MailKeys.MAIL_TEMPLATE_ENGINE, isOptional: true })\n protected templateEngine?: IMailTemplateEngine,\n ) {\n super({ scope: MailService.name });\n this.logger\n .for(this.constructor.name)\n .info('Mail service initialized with provider: %s', this.options.provider);\n }\n\n async send(message: IMailMessage): Promise<IMailSendResult> {\n try {\n this.validateMessage(message);\n\n const emailMessage: IMailMessage = {\n ...message,\n from: message.from ?? this.getDefaultFrom(),\n };\n\n // The one place the attachment policy applies: every transport receives bytes, never a path.\n if (message.attachments) {\n emailMessage.attachments = await resolveMailAttachments({\n attachments: message.attachments,\n attachmentRoot: this.options.attachmentRoot,\n maxBytes: this.options.maxAttachmentBytes ?? MailDefaults.MAX_ATTACHMENT_BYTES,\n });\n }\n\n this.logger.for(this.send.name).debug('Sending email to: %s', emailMessage.to);\n const result = await this.transport.send(emailMessage);\n\n if (result.success) {\n this.logger\n .for(this.send.name)\n .debug('Email sent successfully. MessageId: %s', result.messageId);\n } else {\n this.logger.for(this.send.name).debug('Email send failed: %s', result.error);\n }\n\n return result;\n } catch (error) {\n this.logger.for(this.send.name).error('Error sending email: %s', error);\n releaseAttachmentStreams({ attachments: message.attachments });\n\n // An error the framework already shaped carries its own status and message code; re-wrapping as 500 would report a caller mistake as a server fault.\n if (isApplicationError(error)) {\n throw error;\n }\n\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.SEND_FAILED,\n // The raw text can carry a file path or a provider detail; it rides in `cause`, which only development responses show.\n message: 'Failed to send email',\n cause: error,\n });\n }\n }\n\n async sendBatch(\n messages: IMailMessage[],\n options?: { concurrency?: number },\n ): Promise<IMailSendResult[]> {\n try {\n const concurrency = options?.concurrency ?? MailDefaults.BATCH_CONCURRENCY;\n this.logger\n .for(this.sendBatch.name)\n .info('Sending batch of %d emails with concurrency: %d', messages.length, concurrency);\n\n const tasks = messages.map((message) => async () => {\n try {\n return await this.send(message);\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n });\n\n const results = await executePromiseWithLimit<IMailSendResult>({\n tasks,\n limit: concurrency,\n });\n\n const successCount = results.filter((r) => r.success).length;\n this.logger\n .for(this.sendBatch.name)\n .info(\n 'Batch send completed. Success: %d, Failed: %d',\n successCount,\n results.length - successCount,\n );\n\n return results;\n } catch (error) {\n this.logger.for(this.sendBatch.name).error('Error sending batch emails: %s', error);\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.BATCH_SEND_FAILED,\n message: 'Failed to send batch emails',\n cause: error,\n });\n }\n }\n\n async sendTemplate(opts: {\n templateName: string;\n data: Record<string, AnyType>;\n recipients: string | string[];\n options?: Partial<IMailMessage>;\n }): Promise<IMailSendResult> {\n const { templateName, data, recipients, options } = opts;\n\n try {\n if (!this.templateEngine) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.INVALID_CONFIGURATION,\n message: 'Template engine not configured',\n });\n }\n\n this.logger.for(this.sendTemplate.name).debug('Rendering template: %s', templateName);\n const html = this.templateEngine.render({\n templateName,\n data,\n requireValidate: options?.requireValidate,\n });\n\n const templateData = this.templateEngine.getTemplate(templateName);\n\n const message: IMailMessage = {\n to: recipients,\n subject:\n options?.subject ??\n (templateData?.subject !== undefined\n ? this.templateEngine.render({\n templateData: templateData.subject,\n data,\n requireValidate: options?.requireValidate,\n })\n : 'No Subject'),\n html,\n ...options,\n };\n\n return await this.send(message);\n } catch (error) {\n this.logger.for(this.sendTemplate.name).error('Error sending template email: %s', error);\n throw error;\n }\n }\n\n async verify(): Promise<boolean> {\n try {\n this.logger.for(this.verify.name).debug('Verifying mail transport connection');\n const isValid = await this.transport.verify();\n this.logger.for(this.verify.name).debug('Verification result: %s', isValid);\n return isValid;\n } catch (error) {\n this.logger.for(this.verify.name).error('Verification failed: %s', error);\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.VERIFICATION_FAILED,\n message: 'Mail transport verification failed',\n cause: error,\n });\n }\n }\n\n protected validateMessage(message: IMailMessage): void {\n if (!message.to || (Array.isArray(message.to) && message.to.length === 0)) {\n throw getError({\n error: MailErrors.INVALID_RECIPIENT,\n message: 'Recipient email address is required',\n });\n }\n\n if (!message.subject) {\n throw getError({\n error: MailErrors.INVALID_CONFIGURATION,\n message: 'Email subject is required',\n });\n }\n\n if (!message.text && !message.html) {\n throw getError({\n error: MailErrors.INVALID_CONFIGURATION,\n message: 'Email must have either text or html content',\n });\n }\n\n assertMailBodyIsText({ message });\n }\n\n protected getDefaultFrom(): string {\n const { from, fromName } = this.options;\n\n // A display name is only renderable around an address: `\"Name\" <undefined>` is not a sender.\n if (!from) {\n return MailDefaults.FALLBACK_FROM;\n }\n\n if (!fromName) {\n return from;\n }\n\n return `\"${fromName}\" <${from}>`;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mail.service.js","sourceRoot":"","sources":["../../../../../src/components/mail/services/mail.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASpD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,IAAa,WAAW,mBAAxB,MAAa,WAAY,SAAQ,WAAW;IAC1C,YAEY,OAAqB,EAErB,SAAyB,EAEzB,cAAoC;QAE9C,KAAK,CAAC,EAAE,KAAK,EAAE,aAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QANzB,YAAO,GAAP,OAAO,CAAc;QAErB,cAAS,GAAT,SAAS,CAAgB;QAEzB,mBAAc,GAAd,cAAc,CAAsB;QAG9C,IAAI,CAAC,MAAM;aACR,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;aAC1B,IAAI,CAAC,4CAA4C,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAqB;QAC9B,IAAI,CAAC;YACH,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAE9B,MAAM,YAAY,GAAiB;gBACjC,GAAG,OAAO;gBACV,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,cAAc,EAAE;aAC5C,CAAC;YAEF,6FAA6F;YAC7F,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACxB,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC;oBAClD,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;oBAC3C,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,kBAAkB,IAAI,YAAY,CAAC,oBAAoB;iBAC/E,CAAC,CAAC;gBACH,YAAY,CAAC,WAAW,GAAG,OAAO,CAAC;YACrC,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,sBAAsB,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;YAC/E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAEvD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM;qBACR,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;qBACnB,KAAK,CAAC,wCAAwC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;YACvE,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,uBAAuB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/E,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YACxE,qBAAqB,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;YAEpE,qJAAqJ;YACrJ,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,QAAQ,CAAC;gBACb,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB;gBACrD,WAAW,EAAE,cAAc,CAAC,WAAW;gBACvC,uHAAuH;gBACvH,OAAO,EAAE,sBAAsB;gBAC/B,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CACb,QAAwB,EACxB,OAAkC;QAElC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,YAAY,CAAC,iBAAiB,CAAC;YAC3E,IAAI,CAAC,MAAM;iBACR,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;iBACxB,IAAI,CAAC,iDAAiD,EAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAEzF,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE;gBACjD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACxC,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO;wBACL,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;qBAChE,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,gBAAgB,CAAkB;gBACrE,KAAK;gBACL,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;YAC7D,IAAI,CAAC,MAAM;iBACR,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;iBACxB,IAAI,CACH,+CAA+C,EAC/C,YAAY,EACZ,OAAO,CAAC,MAAM,GAAG,YAAY,CAC9B,CAAC;YAEJ,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACpF,MAAM,QAAQ,CAAC;gBACb,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB;gBACrD,WAAW,EAAE,cAAc,CAAC,iBAAiB;gBAC7C,OAAO,EAAE,6BAA6B;gBACtC,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAKlB;QACC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAEzD,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,MAAM,QAAQ,CAAC;oBACb,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB;oBACrD,WAAW,EAAE,cAAc,CAAC,qBAAqB;oBACjD,OAAO,EAAE,gCAAgC;iBAC1C,CAAC,CAAC;YACL,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;YACtF,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;gBACtC,YAAY;gBACZ,IAAI;gBACJ,eAAe,EAAE,OAAO,EAAE,eAAe;aAC1C,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YAEnE,MAAM,OAAO,GAAiB;gBAC5B,EAAE,EAAE,UAAU;gBACd,OAAO,EACL,OAAO,EAAE,OAAO;oBAChB,CAAC,YAAY,EAAE,OAAO,KAAK,SAAS;wBAClC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;4BACzB,YAAY,EAAE,YAAY,CAAC,OAAO;4BAClC,IAAI;4BACJ,eAAe,EAAE,OAAO,EAAE,eAAe;yBAC1C,CAAC;wBACJ,CAAC,CAAC,YAAY,CAAC;gBACnB,IAAI;gBACJ,GAAG,OAAO;aACX,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;YACzF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YAC/E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,yBAAyB,EAAE,OAAO,CAAC,CAAC;YAC5E,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAC1E,MAAM,QAAQ,CAAC;gBACb,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB;gBACrD,WAAW,EAAE,cAAc,CAAC,mBAAmB;gBAC/C,OAAO,EAAE,oCAAoC;gBAC7C,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAES,eAAe,CAAC,OAAqB;QAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAC1E,MAAM,QAAQ,CAAC;gBACb,KAAK,EAAE,UAAU,CAAC,iBAAiB;gBACnC,OAAO,EAAE,qCAAqC;aAC/C,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM,QAAQ,CAAC;gBACb,KAAK,EAAE,UAAU,CAAC,qBAAqB;gBACvC,OAAO,EAAE,2BAA2B;aACrC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,QAAQ,CAAC;gBACb,KAAK,EAAE,UAAU,CAAC,qBAAqB;gBACvC,OAAO,EAAE,6CAA6C;aACvD,CAAC,CAAC;QACL,CAAC;QAED,eAAe,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC;IAES,cAAc;QACtB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAExC,6FAA6F;QAC7F,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,YAAY,CAAC,aAAa,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,QAAQ,MAAM,IAAI,GAAG,CAAC;IACnC,CAAC;CACF,CAAA;AA1NY,WAAW;IAEnB,WAAA,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAA;IAEtC,WAAA,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,uBAAuB,EAAE,CAAC,CAAA;IAEjD,WAAA,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,oBAAoB,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;;GANxD,WAAW,CA0NvB","sourcesContent":["import { HTTP } from '@venizia/ignis-helpers/common';\nimport { BaseService } from '@venizia/ignis-kernel';\nimport type {\n IMailMessage,\n IMailSendResult,\n IMailService,\n IMailTemplateEngine,\n IMailTransport,\n TMailOptions,\n} from '../common';\nimport { MailDefaults, MailErrorCodes, MailErrors, MailKeys } from '../common';\nimport { inject } from '@/base/metadata';\nimport { getError, isApplicationError } from '@venizia/ignis-helpers/core';\nimport { type AnyType } from '@venizia/ignis-helpers/common';\nimport { PromiseUtility } from '@venizia/ignis-helpers';\nimport { MailAttachmentUtility } from '../utilities/attachment.utility';\nimport { MailBodyUtility } from '../utilities/body.utility';\n\nexport class MailService extends BaseService implements IMailService {\n constructor(\n @inject({ key: MailKeys.MAIL_OPTIONS })\n protected options: TMailOptions,\n @inject({ key: MailKeys.MAIL_TRANSPORT_INSTANCE })\n protected transport: IMailTransport,\n @inject({ key: MailKeys.MAIL_TEMPLATE_ENGINE, isOptional: true })\n protected templateEngine?: IMailTemplateEngine,\n ) {\n super({ scope: MailService.name });\n this.logger\n .for(this.constructor.name)\n .info('Mail service initialized with provider: %s', this.options.provider);\n }\n\n async send(message: IMailMessage): Promise<IMailSendResult> {\n try {\n this.validateMessage(message);\n\n const emailMessage: IMailMessage = {\n ...message,\n from: message.from ?? this.getDefaultFrom(),\n };\n\n // The one place the attachment policy applies: every transport receives bytes, never a path.\n if (message.attachments) {\n const result2 = await MailAttachmentUtility.resolve({\n attachments: message.attachments,\n attachmentRoot: this.options.attachmentRoot,\n maxBytes: this.options.maxAttachmentBytes ?? MailDefaults.MAX_ATTACHMENT_BYTES,\n });\n emailMessage.attachments = result2;\n }\n\n this.logger.for(this.send.name).debug('Sending email to: %s', emailMessage.to);\n const result = await this.transport.send(emailMessage);\n\n if (result.success) {\n this.logger\n .for(this.send.name)\n .debug('Email sent successfully. MessageId: %s', result.messageId);\n } else {\n this.logger.for(this.send.name).debug('Email send failed: %s', result.error);\n }\n\n return result;\n } catch (error) {\n this.logger.for(this.send.name).error('Error sending email: %s', error);\n MailAttachmentUtility.release({ attachments: message.attachments });\n\n // An error the framework already shaped carries its own status and message code; re-wrapping as 500 would report a caller mistake as a server fault.\n if (isApplicationError(error)) {\n throw error;\n }\n\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.SEND_FAILED,\n // The raw text can carry a file path or a provider detail; it rides in `cause`, which only development responses show.\n message: 'Failed to send email',\n cause: error,\n });\n }\n }\n\n async sendBatch(\n messages: IMailMessage[],\n options?: { concurrency?: number },\n ): Promise<IMailSendResult[]> {\n try {\n const concurrency = options?.concurrency ?? MailDefaults.BATCH_CONCURRENCY;\n this.logger\n .for(this.sendBatch.name)\n .info('Sending batch of %d emails with concurrency: %d', messages.length, concurrency);\n\n const tasks = messages.map((message) => async () => {\n try {\n const result = await this.send(message);\n return result;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n });\n\n const results = await PromiseUtility.executeWithLimit<IMailSendResult>({\n tasks,\n limit: concurrency,\n });\n\n const successCount = results.filter((r) => r.success).length;\n this.logger\n .for(this.sendBatch.name)\n .info(\n 'Batch send completed. Success: %d, Failed: %d',\n successCount,\n results.length - successCount,\n );\n\n return results;\n } catch (error) {\n this.logger.for(this.sendBatch.name).error('Error sending batch emails: %s', error);\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.BATCH_SEND_FAILED,\n message: 'Failed to send batch emails',\n cause: error,\n });\n }\n }\n\n async sendTemplate(opts: {\n templateName: string;\n data: Record<string, AnyType>;\n recipients: string | string[];\n options?: Partial<IMailMessage>;\n }): Promise<IMailSendResult> {\n const { templateName, data, recipients, options } = opts;\n\n try {\n if (!this.templateEngine) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.INVALID_CONFIGURATION,\n message: 'Template engine not configured',\n });\n }\n\n this.logger.for(this.sendTemplate.name).debug('Rendering template: %s', templateName);\n const html = this.templateEngine.render({\n templateName,\n data,\n requireValidate: options?.requireValidate,\n });\n\n const templateData = this.templateEngine.getTemplate(templateName);\n\n const message: IMailMessage = {\n to: recipients,\n subject:\n options?.subject ??\n (templateData?.subject !== undefined\n ? this.templateEngine.render({\n templateData: templateData.subject,\n data,\n requireValidate: options?.requireValidate,\n })\n : 'No Subject'),\n html,\n ...options,\n };\n\n const result = await this.send(message);\n return result;\n } catch (error) {\n this.logger.for(this.sendTemplate.name).error('Error sending template email: %s', error);\n throw error;\n }\n }\n\n async verify(): Promise<boolean> {\n try {\n this.logger.for(this.verify.name).debug('Verifying mail transport connection');\n const isValid = await this.transport.verify();\n this.logger.for(this.verify.name).debug('Verification result: %s', isValid);\n return isValid;\n } catch (error) {\n this.logger.for(this.verify.name).error('Verification failed: %s', error);\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n messageCode: MailErrorCodes.VERIFICATION_FAILED,\n message: 'Mail transport verification failed',\n cause: error,\n });\n }\n }\n\n protected validateMessage(message: IMailMessage): void {\n if (!message.to || (Array.isArray(message.to) && message.to.length === 0)) {\n throw getError({\n error: MailErrors.INVALID_RECIPIENT,\n message: 'Recipient email address is required',\n });\n }\n\n if (!message.subject) {\n throw getError({\n error: MailErrors.INVALID_CONFIGURATION,\n message: 'Email subject is required',\n });\n }\n\n if (!message.text && !message.html) {\n throw getError({\n error: MailErrors.INVALID_CONFIGURATION,\n message: 'Email must have either text or html content',\n });\n }\n\n MailBodyUtility.assertIsText({ message });\n }\n\n protected getDefaultFrom(): string {\n const { from, fromName } = this.options;\n\n // A display name is only renderable around an address: `\"Name\" <undefined>` is not a sender.\n if (!from) {\n return MailDefaults.FALLBACK_FROM;\n }\n\n if (!fromName) {\n return from;\n }\n\n return `\"${fromName}\" <${from}>`;\n }\n}\n"]}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
export declare class MailAddressUtility {
|
|
2
|
+
/**
|
|
3
|
+
* Splits one or more RFC 5322 mailbox strings into individual addresses. A caller-supplied `to`
|
|
4
|
+
* is frequently a single comma-separated string (`"a@x.com, b@y.com"`), not an array - treating
|
|
5
|
+
* it as one opaque address turns it into a single malformed recipient. Splitting only at
|
|
6
|
+
* top-level commas (outside a quoted display name) keeps `"Doe, Jane" <jane@x.com>` intact while
|
|
7
|
+
* still separating `"Doe, Jane" <jane@x.com>, bob@y.com` into its two mailboxes.
|
|
8
|
+
*/
|
|
9
|
+
static splitList(opts: {
|
|
10
|
+
value: string | string[];
|
|
11
|
+
}): string[];
|
|
12
|
+
}
|
|
9
13
|
//# sourceMappingURL=address.utility.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"address.utility.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/address.utility.ts"],"names":[],"mappings":"AAAA;;;;;;
|
|
1
|
+
{"version":3,"file":"address.utility.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/address.utility.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,GAAG,MAAM,EAAE;CAgC/D"}
|
|
@@ -1,33 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
export class MailAddressUtility {
|
|
2
|
+
/**
|
|
3
|
+
* Splits one or more RFC 5322 mailbox strings into individual addresses. A caller-supplied `to`
|
|
4
|
+
* is frequently a single comma-separated string (`"a@x.com, b@y.com"`), not an array - treating
|
|
5
|
+
* it as one opaque address turns it into a single malformed recipient. Splitting only at
|
|
6
|
+
* top-level commas (outside a quoted display name) keeps `"Doe, Jane" <jane@x.com>` intact while
|
|
7
|
+
* still separating `"Doe, Jane" <jane@x.com>, bob@y.com` into its two mailboxes.
|
|
8
|
+
*/
|
|
9
|
+
static splitList(opts) {
|
|
10
|
+
const { value } = opts;
|
|
11
|
+
const items = Array.isArray(value) ? value : [value];
|
|
12
|
+
const addresses = [];
|
|
13
|
+
for (const item of items) {
|
|
14
|
+
let current = '';
|
|
15
|
+
let inQuotes = false;
|
|
16
|
+
for (const char of item) {
|
|
17
|
+
if (char === '"') {
|
|
18
|
+
inQuotes = !inQuotes;
|
|
19
|
+
}
|
|
20
|
+
if (char === ',' && !inQuotes) {
|
|
21
|
+
if (current.trim()) {
|
|
22
|
+
addresses.push(current.trim());
|
|
23
|
+
}
|
|
24
|
+
current = '';
|
|
25
|
+
continue;
|
|
21
26
|
}
|
|
22
|
-
current
|
|
23
|
-
|
|
27
|
+
current += char;
|
|
28
|
+
}
|
|
29
|
+
if (current.trim()) {
|
|
30
|
+
addresses.push(current.trim());
|
|
24
31
|
}
|
|
25
|
-
current += char;
|
|
26
|
-
}
|
|
27
|
-
if (current.trim()) {
|
|
28
|
-
addresses.push(current.trim());
|
|
29
32
|
}
|
|
33
|
+
return addresses;
|
|
30
34
|
}
|
|
31
|
-
return addresses;
|
|
32
35
|
}
|
|
33
36
|
//# sourceMappingURL=address.utility.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"address.utility.js","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/address.utility.ts"],"names":[],"mappings":"AAAA;;;;;;
|
|
1
|
+
{"version":3,"file":"address.utility.js","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/address.utility.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAkB;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CAAC,IAAkC;QACjD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QACvB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,SAAS,GAAa,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,OAAO,GAAG,EAAE,CAAC;YACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;YAErB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;gBACxB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACjB,QAAQ,GAAG,CAAC,QAAQ,CAAC;gBACvB,CAAC;gBAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAC9B,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;wBACnB,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;oBACjC,CAAC;oBACD,OAAO,GAAG,EAAE,CAAC;oBACb,SAAS;gBACX,CAAC;gBAED,OAAO,IAAI,IAAI,CAAC;YAClB,CAAC;YAED,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnB,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;CACF","sourcesContent":["export class MailAddressUtility {\n /**\n * Splits one or more RFC 5322 mailbox strings into individual addresses. A caller-supplied `to`\n * is frequently a single comma-separated string (`\"a@x.com, b@y.com\"`), not an array - treating\n * it as one opaque address turns it into a single malformed recipient. Splitting only at\n * top-level commas (outside a quoted display name) keeps `\"Doe, Jane\" <jane@x.com>` intact while\n * still separating `\"Doe, Jane\" <jane@x.com>, bob@y.com` into its two mailboxes.\n */\n static splitList(opts: { value: string | string[] }): string[] {\n const { value } = opts;\n const items = Array.isArray(value) ? value : [value];\n const addresses: string[] = [];\n\n for (const item of items) {\n let current = '';\n let inQuotes = false;\n\n for (const char of item) {\n if (char === '\"') {\n inQuotes = !inQuotes;\n }\n\n if (char === ',' && !inQuotes) {\n if (current.trim()) {\n addresses.push(current.trim());\n }\n current = '';\n continue;\n }\n\n current += char;\n }\n\n if (current.trim()) {\n addresses.push(current.trim());\n }\n }\n\n return addresses;\n }\n}\n"]}
|
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
import { type IMailAttachment } from '../common/index.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
2
|
+
export declare class MailAttachmentUtility {
|
|
3
|
+
/**
|
|
4
|
+
* Reads one attachment's bytes. A string `content` is raw text unless `encoding` says otherwise
|
|
5
|
+
* (nodemailer's convention); `null` counts as absent. A `path` is read only inside
|
|
6
|
+
* `attachmentRoot` and refused without one. `maxBytes` caps the whole message; `usedBytes` is what
|
|
7
|
+
* earlier attachments already took.
|
|
8
|
+
*/
|
|
9
|
+
static readContent(opts: {
|
|
10
|
+
attachment: IMailAttachment;
|
|
11
|
+
attachmentRoot?: string;
|
|
12
|
+
maxBytes?: number;
|
|
13
|
+
usedBytes?: number;
|
|
14
|
+
}): Promise<Buffer>;
|
|
15
|
+
/**
|
|
16
|
+
* Turns every attachment into `content` bytes and drops `path`, so no transport is ever handed a
|
|
17
|
+
* file or URL to read on its own. `maxBytes` is shared by all attachments of the message. An
|
|
18
|
+
* attachment read from `path` keeps the file's name and, when none is given, its content type.
|
|
19
|
+
*/
|
|
20
|
+
static resolve(opts: {
|
|
21
|
+
attachments: IMailAttachment[];
|
|
22
|
+
attachmentRoot?: string;
|
|
23
|
+
maxBytes?: number;
|
|
24
|
+
}): Promise<IMailAttachment[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Releases every attachment stream of a refused send, read or not, so none keeps a descriptor
|
|
27
|
+
* open. A drained stream is already closed; releasing it again is harmless.
|
|
28
|
+
*/
|
|
29
|
+
static release(opts: {
|
|
30
|
+
attachments?: IMailAttachment[];
|
|
31
|
+
}): void;
|
|
32
|
+
}
|
|
31
33
|
//# sourceMappingURL=attachment.utility.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.utility.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/attachment.utility.ts"],"names":[],"mappings":"AAMA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"attachment.utility.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/attachment.utility.ts"],"names":[],"mappings":"AAMA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AA2J7D,qBAAa,qBAAqB;IAChC;;;;;OAKG;WACU,WAAW,CAAC,IAAI,EAAE;QAC7B,UAAU,EAAE,eAAe,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsCnB;;;;OAIG;WACU,OAAO,CAAC,IAAI,EAAE;QACzB,WAAW,EAAE,eAAe,EAAE,CAAC;QAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA4C9B;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,GAAG,IAAI;CA2BhE"}
|