@serve.zone/platformclient 1.1.5 → 2.0.0

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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/platformclient',
6
- version: '1.1.5',
6
+ version: '2.0.0',
7
7
  description: 'a module that makes it really easy to use the serve.zone platform inside your app'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSw0QkFBNEI7SUFDbEMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLG1GQUFtRjtDQUNqRyxDQUFBIn0=
@@ -35,9 +35,10 @@ export declare class SzPlatformClient {
35
35
  private getConfiguredAuthorizationString;
36
36
  private getAuthorizationStringFromBindings;
37
37
  private setAuthorizationTag;
38
+ stop(): Promise<void>;
38
39
  private discoverPlatformBindings;
39
40
  private parsePlatformBindingsEnv;
40
41
  private mergePlatformBindings;
41
- private getConfiguredEnvVar;
42
+ getConfiguredEnvVar(envNameArg: string): Promise<string | undefined>;
42
43
  private getProcessEnvVar;
43
44
  }
@@ -128,6 +128,12 @@ export class SzPlatformClient {
128
128
  }
129
129
  }
130
130
  }
131
+ async stop() {
132
+ await this.emailConnector.stop();
133
+ if (this.typedsocket) {
134
+ await this.typedsocket.stop();
135
+ }
136
+ }
131
137
  async discoverPlatformBindings() {
132
138
  const bindings = [];
133
139
  const envBindings = await this.getConfiguredEnvVar('SERVEZONE_PLATFORM_BINDINGS');
@@ -175,4 +181,4 @@ export class SzPlatformClient {
175
181
  return processEnv?.[envNameArg];
176
182
  }
177
183
  }
178
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wbGF0Zm9ybWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucGxhdGZvcm1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQzNGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZFLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBWXhDLE1BQU0sT0FBTyxnQkFBZ0I7SUFjM0IsWUFBWSxzQkFBMEQ7UUFiL0QsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUdsQixxQkFBZ0IsR0FBNEQsRUFBRSxDQUFDO1FBQy9FLGdCQUFXLEdBQXFDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUV0RixpQkFBWSxHQUFHLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV4QyxtQkFBYyxHQUFHLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUMsaUJBQVksR0FBRyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4Qyw4QkFBeUIsR0FBRyxJQUFJLDJCQUEyQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xFLG9CQUFlLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUduRCxJQUFJLENBQUMsWUFBWSxDQUFDLHNCQUFzQixDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJLENBQUMsc0JBQTBEO1FBQzFFLElBQUksQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsSUFB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
184
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wbGF0Zm9ybWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucGxhdGZvcm1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQzNGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZFLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBWXhDLE1BQU0sT0FBTyxnQkFBZ0I7SUFjM0IsWUFBWSxzQkFBMEQ7UUFiL0QsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUdsQixxQkFBZ0IsR0FBNEQsRUFBRSxDQUFDO1FBQy9FLGdCQUFXLEdBQXFDLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUV0RixpQkFBWSxHQUFHLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV4QyxtQkFBYyxHQUFHLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUMsaUJBQVksR0FBRyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4Qyw4QkFBeUIsR0FBRyxJQUFJLDJCQUEyQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xFLG9CQUFlLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUduRCxJQUFJLENBQUMsWUFBWSxDQUFDLHNCQUFzQixDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJLENBQUMsc0JBQTBEO1FBQzFFLElBQUksQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsSUFB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
@@ -1,9 +1,102 @@
1
1
  import type { SzPlatformClient } from '../classes.platformclient.js';
2
2
  import * as plugins from '../plugins.js';
3
+ export type TServiceMailTlsMode = 'plain' | 'starttls' | 'implicitTls';
4
+ export interface IServiceMailSmtpCredentials {
5
+ from: string;
6
+ host: string;
7
+ port: number;
8
+ tlsMode: TServiceMailTlsMode;
9
+ username: string;
10
+ password: string;
11
+ addressToken?: string;
12
+ }
13
+ export interface IServiceMailTypedCredentials {
14
+ from: string;
15
+ typedUrl: string;
16
+ credentialId: string;
17
+ credentialSecret: string;
18
+ addressToken?: string;
19
+ }
20
+ export interface IServiceMailStatus {
21
+ ready: boolean;
22
+ from?: string;
23
+ host?: string;
24
+ port?: number;
25
+ tlsMode?: TServiceMailTlsMode;
26
+ typedUrl?: string;
27
+ transport?: 'typedsocket' | 'smtp' | 'none';
28
+ usernameConfigured: boolean;
29
+ passwordConfigured: boolean;
30
+ typedCredentialConfigured?: boolean;
31
+ smtpReady?: boolean;
32
+ missing: string[];
33
+ }
34
+ export interface IServiceMailAttachment {
35
+ filename: string;
36
+ contentType?: string;
37
+ content: string | Uint8Array;
38
+ }
39
+ export interface IServiceMailSendOptions {
40
+ from?: string;
41
+ to: string | string[];
42
+ cc?: string | string[];
43
+ bcc?: string | string[];
44
+ subject: string;
45
+ text?: string;
46
+ html?: string;
47
+ headers?: Record<string, string>;
48
+ attachments?: IServiceMailAttachment[];
49
+ }
50
+ export interface IServiceMailSendResult {
51
+ messageId?: string;
52
+ accepted?: string[];
53
+ rejected?: string[];
54
+ response?: string;
55
+ }
56
+ export interface IServiceMailInboundMessage extends plugins.servezoneInterfaces.data.IMailInboundMessagePayload {
57
+ from: string;
58
+ to: string[];
59
+ receivedAtIso: string;
60
+ }
61
+ export interface IServiceMailInboundHandlerResult {
62
+ accepted?: boolean;
63
+ workAppMessageId?: string;
64
+ message?: string;
65
+ }
66
+ export type IServiceMailInboundHandleResult = plugins.servezoneInterfaces.requests.mail.IReq_DeliverInboundMail['response'];
67
+ export type TServiceMailInboundHandler = (messageArg: IServiceMailInboundMessage) => Promise<IServiceMailInboundHandlerResult | void> | IServiceMailInboundHandlerResult | void;
3
68
  export declare class SzEmailConnector {
4
69
  platformClientRef: SzPlatformClient;
70
+ private mailTypedSocket?;
71
+ private mailTypedSocketUrl?;
72
+ private mailTypedSocketPromise?;
73
+ private mailTypedSocketAbortController?;
74
+ private inboundHandler?;
75
+ private inboundTypedHandlerRegistered;
5
76
  constructor(platformClientRefArg: SzPlatformClient);
77
+ /**
78
+ * Legacy platform-service email path. New service-mail code should use sendMail().
79
+ */
6
80
  sendEmail(optionsArg: plugins.servezoneInterfaces.platform.email.IReq_SendEmail['request']): Promise<string | undefined>;
81
+ getServiceMailStatus(addressArg?: string): Promise<IServiceMailStatus>;
82
+ getServiceMailCredentials(addressArg?: string): Promise<IServiceMailSmtpCredentials>;
83
+ sendText(optionsArg: Omit<IServiceMailSendOptions, 'html'> & {
84
+ text: string;
85
+ }): Promise<IServiceMailSendResult>;
86
+ sendHtml(optionsArg: Omit<IServiceMailSendOptions, 'text'> & {
87
+ html: string;
88
+ }): Promise<IServiceMailSendResult>;
89
+ sendMail(optionsArg: IServiceMailSendOptions): Promise<IServiceMailSendResult>;
90
+ registerInboundHandler(handlerArg: TServiceMailInboundHandler, addressArg?: string): Promise<plugins.servezoneInterfaces.requests.mail.IReq_RegisterServiceMailEndpoint['response']>;
91
+ stop(): Promise<void>;
92
+ normalizeInboundMessage(payloadArg: unknown): IServiceMailInboundMessage;
93
+ handleInboundPayload(payloadArg: unknown, handlerArg: TServiceMailInboundHandler): Promise<IServiceMailInboundHandleResult>;
94
+ createInboundHandler(handlerArg: TServiceMailInboundHandler): (payloadArg: unknown) => Promise<{
95
+ accepted: boolean;
96
+ workAppMessageId?: string;
97
+ message?: string;
98
+ }>;
99
+ private ensureInboundTypedHandler;
7
100
  sendNotification(optionsArg: {
8
101
  toArg: string;
9
102
  subject: string;
@@ -14,4 +107,19 @@ export declare class SzEmailConnector {
14
107
  subject: string;
15
108
  text: string;
16
109
  }): Promise<void>;
110
+ private readMailEnv;
111
+ private readMailEnvVar;
112
+ private getCredentialEnvVarFromBindings;
113
+ private hasAnyMailEnvValue;
114
+ private getServiceMailTypedCredentials;
115
+ private getMailTypedSocket;
116
+ private stopMailTypedSocket;
117
+ private normalizeTypedSocketUrl;
118
+ private normalizeTlsMode;
119
+ private getMailEnvToken;
120
+ private listToArray;
121
+ private normalizeAttachmentContent;
122
+ private asRecord;
123
+ private normalizeHeaders;
124
+ private extractHeader;
17
125
  }
@@ -2,8 +2,12 @@ import * as plugins from '../plugins.js';
2
2
  import { logger } from '../logger.js';
3
3
  export class SzEmailConnector {
4
4
  constructor(platformClientRefArg) {
5
+ this.inboundTypedHandlerRegistered = false;
5
6
  this.platformClientRef = platformClientRefArg;
6
7
  }
8
+ /**
9
+ * Legacy platform-service email path. New service-mail code should use sendMail().
10
+ */
7
11
  async sendEmail(optionsArg) {
8
12
  if (this.platformClientRef.debugMode) {
9
13
  logger.log('info', `sent email with subject ${optionsArg.title} to ${optionsArg.to}
@@ -19,7 +23,368 @@ export class SzEmailConnector {
19
23
  const response = await typedRequest.fire(optionsArg);
20
24
  return response.responseId;
21
25
  }
26
+ async getServiceMailStatus(addressArg) {
27
+ const requestedAddress = addressArg?.trim().toLowerCase();
28
+ const token = requestedAddress ? this.getMailEnvToken(requestedAddress) : undefined;
29
+ const scopedEnv = token ? await this.readMailEnv(token) : undefined;
30
+ const defaultEnv = token ? await this.readMailEnv() : undefined;
31
+ const useDefaultEnv = requestedAddress
32
+ && !this.hasAnyMailEnvValue(scopedEnv)
33
+ && defaultEnv?.from?.trim().toLowerCase() === requestedAddress;
34
+ const env = useDefaultEnv ? defaultEnv : scopedEnv || await this.readMailEnv();
35
+ const missingPrefix = useDefaultEnv || !token ? undefined : token;
36
+ const port = env.smtpPort ? Number(env.smtpPort) : undefined;
37
+ const tlsMode = this.normalizeTlsMode(env.smtpTlsMode || 'starttls');
38
+ const typedMissing = [];
39
+ const smtpMissing = [];
40
+ if (!env.typedUrl)
41
+ typedMissing.push(missingPrefix ? `MAIL_${missingPrefix}_TYPED_URL` : 'MAIL_TYPED_URL');
42
+ if (!env.apiCredentialId)
43
+ typedMissing.push(missingPrefix ? `MAIL_${missingPrefix}_API_CREDENTIAL_ID` : 'MAIL_API_CREDENTIAL_ID');
44
+ if (!env.apiCredentialSecret)
45
+ typedMissing.push(missingPrefix ? `MAIL_${missingPrefix}_API_CREDENTIAL_SECRET` : 'MAIL_API_CREDENTIAL_SECRET');
46
+ if (!env.smtpHost)
47
+ smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_HOST` : 'SMTP_HOST');
48
+ if (!env.smtpPort || !Number.isInteger(port) || port < 1 || port > 65535) {
49
+ smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_PORT` : 'SMTP_PORT');
50
+ }
51
+ if (!env.smtpUsername)
52
+ smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_USERNAME` : 'SMTP_USERNAME');
53
+ if (!env.smtpPassword)
54
+ smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_PASSWORD` : 'SMTP_PASSWORD');
55
+ const fromMissing = env.from ? [] : [missingPrefix ? `MAIL_${missingPrefix}_FROM` : 'MAIL_FROM'];
56
+ const typedReady = fromMissing.length === 0 && typedMissing.length === 0;
57
+ const smtpReady = fromMissing.length === 0 && smtpMissing.length === 0;
58
+ return {
59
+ ready: typedReady,
60
+ from: env.from,
61
+ host: env.smtpHost,
62
+ port,
63
+ tlsMode,
64
+ typedUrl: env.typedUrl,
65
+ transport: typedReady ? 'typedsocket' : smtpReady ? 'smtp' : 'none',
66
+ usernameConfigured: Boolean(env.smtpUsername),
67
+ passwordConfigured: Boolean(env.smtpPassword),
68
+ typedCredentialConfigured: Boolean(env.apiCredentialId && env.apiCredentialSecret),
69
+ smtpReady,
70
+ missing: typedReady ? [] : [...fromMissing, ...typedMissing],
71
+ };
72
+ }
73
+ async getServiceMailCredentials(addressArg) {
74
+ const requestedAddress = addressArg?.trim().toLowerCase();
75
+ const requestedToken = requestedAddress ? this.getMailEnvToken(requestedAddress) : undefined;
76
+ const scopedEnv = requestedToken ? await this.readMailEnv(requestedToken) : undefined;
77
+ const hasScopedConfig = scopedEnv && Object.values(scopedEnv).some(Boolean);
78
+ const env = hasScopedConfig ? scopedEnv : await this.readMailEnv();
79
+ const from = env.from?.trim().toLowerCase();
80
+ if (!from)
81
+ throw new Error('MAIL_FROM is required for service mail');
82
+ if (requestedAddress && from !== requestedAddress) {
83
+ throw new Error(`No service mail credentials are configured for ${requestedAddress}`);
84
+ }
85
+ const port = Number(env.smtpPort);
86
+ if (!env.smtpHost)
87
+ throw new Error('SMTP_HOST is required for service mail');
88
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
89
+ throw new Error('SMTP_PORT must be an integer between 1 and 65535');
90
+ }
91
+ if (!env.smtpUsername)
92
+ throw new Error('SMTP_USERNAME is required for service mail');
93
+ if (!env.smtpPassword)
94
+ throw new Error('SMTP_PASSWORD is required for service mail');
95
+ return {
96
+ from,
97
+ host: env.smtpHost,
98
+ port,
99
+ tlsMode: this.normalizeTlsMode(env.smtpTlsMode || 'starttls'),
100
+ username: env.smtpUsername,
101
+ password: env.smtpPassword,
102
+ addressToken: hasScopedConfig ? requestedToken : undefined,
103
+ };
104
+ }
105
+ async sendText(optionsArg) {
106
+ return await this.sendMail(optionsArg);
107
+ }
108
+ async sendHtml(optionsArg) {
109
+ return await this.sendMail(optionsArg);
110
+ }
111
+ async sendMail(optionsArg) {
112
+ if (!optionsArg.text && !optionsArg.html) {
113
+ throw new Error('Either text or html is required for service mail');
114
+ }
115
+ if (this.platformClientRef.debugMode) {
116
+ logger.log('info', `service mail debug send: ${optionsArg.subject} to ${this.listToArray(optionsArg.to).join(', ')}`);
117
+ return { messageId: 'debug' };
118
+ }
119
+ const credentials = await this.getServiceMailTypedCredentials(optionsArg.from);
120
+ const typedSocket = await this.getMailTypedSocket(credentials.typedUrl);
121
+ const request = typedSocket.createTypedRequest('enqueueMail');
122
+ const result = await request.fire({
123
+ auth: {
124
+ credentialId: credentials.credentialId,
125
+ credentialSecret: credentials.credentialSecret,
126
+ },
127
+ outboundIdentityId: credentials.credentialId,
128
+ message: {
129
+ from: credentials.from,
130
+ to: this.listToArray(optionsArg.to),
131
+ cc: optionsArg.cc ? this.listToArray(optionsArg.cc) : undefined,
132
+ bcc: optionsArg.bcc ? this.listToArray(optionsArg.bcc) : undefined,
133
+ subject: optionsArg.subject,
134
+ text: optionsArg.text,
135
+ html: optionsArg.html,
136
+ headers: optionsArg.headers,
137
+ attachments: optionsArg.attachments?.map((attachmentArg) => ({
138
+ filename: attachmentArg.filename,
139
+ contentType: attachmentArg.contentType,
140
+ binaryAttachmentString: this.normalizeAttachmentContent(attachmentArg.content),
141
+ })),
142
+ },
143
+ });
144
+ if (!result.accepted) {
145
+ throw new Error(result.message || 'service mail was not accepted by dcrouter');
146
+ }
147
+ return {
148
+ messageId: result.spoolItemId,
149
+ accepted: this.listToArray(optionsArg.to),
150
+ rejected: [],
151
+ response: result.message,
152
+ };
153
+ }
154
+ async registerInboundHandler(handlerArg, addressArg) {
155
+ this.inboundHandler = handlerArg;
156
+ this.ensureInboundTypedHandler();
157
+ const credentials = await this.getServiceMailTypedCredentials(addressArg);
158
+ const typedSocket = await this.getMailTypedSocket(credentials.typedUrl);
159
+ const request = typedSocket.createTypedRequest('registerServiceMailEndpoint');
160
+ const result = await request.fire({
161
+ auth: {
162
+ credentialId: credentials.credentialId,
163
+ credentialSecret: credentials.credentialSecret,
164
+ },
165
+ addresses: [credentials.from],
166
+ });
167
+ if (!result.success) {
168
+ throw new Error(result.message || 'Could not register service mail endpoint');
169
+ }
170
+ return result;
171
+ }
172
+ async stop() {
173
+ await this.stopMailTypedSocket();
174
+ }
175
+ normalizeInboundMessage(payloadArg) {
176
+ const payload = this.asRecord(payloadArg);
177
+ const deliveryCandidate = this.asRecord(payload.delivery || payload.message || payload);
178
+ const envelope = this.asRecord(deliveryCandidate.envelope);
179
+ const rawMessage = typeof deliveryCandidate.rawMessage === 'string' ? deliveryCandidate.rawMessage : '';
180
+ const rcptTo = Array.isArray(envelope.rcptTo) ? envelope.rcptTo.map(String) : [];
181
+ const receivedAt = typeof deliveryCandidate.receivedAt === 'number' ? deliveryCandidate.receivedAt : Date.now();
182
+ return {
183
+ spoolItemId: String(deliveryCandidate.spoolItemId || deliveryCandidate.id || ''),
184
+ owner: deliveryCandidate.owner,
185
+ envelope: {
186
+ mailFrom: String(envelope.mailFrom || deliveryCandidate.from || ''),
187
+ rcptTo,
188
+ },
189
+ rawMessage,
190
+ sizeBytes: typeof deliveryCandidate.sizeBytes === 'number' ? deliveryCandidate.sizeBytes : rawMessage.length,
191
+ messageId: deliveryCandidate.messageId ? String(deliveryCandidate.messageId) : undefined,
192
+ subject: deliveryCandidate.subject ? String(deliveryCandidate.subject) : this.extractHeader(rawMessage, 'subject'),
193
+ headers: this.normalizeHeaders(deliveryCandidate.headers),
194
+ source: deliveryCandidate.source,
195
+ receivedAt,
196
+ from: String(envelope.mailFrom || deliveryCandidate.from || ''),
197
+ to: rcptTo,
198
+ receivedAtIso: new Date(receivedAt).toISOString(),
199
+ };
200
+ }
201
+ async handleInboundPayload(payloadArg, handlerArg) {
202
+ const message = this.normalizeInboundMessage(payloadArg);
203
+ const result = await handlerArg(message);
204
+ return {
205
+ accepted: result?.accepted !== false,
206
+ workAppMessageId: result?.workAppMessageId,
207
+ message: result?.message,
208
+ };
209
+ }
210
+ createInboundHandler(handlerArg) {
211
+ return async (payloadArg) => await this.handleInboundPayload(payloadArg, handlerArg);
212
+ }
213
+ ensureInboundTypedHandler() {
214
+ if (this.inboundTypedHandlerRegistered)
215
+ return;
216
+ this.inboundTypedHandlerRegistered = true;
217
+ this.platformClientRef.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('deliverInboundMail', async (dataArg) => {
218
+ if (!this.inboundHandler) {
219
+ return { accepted: false, message: 'No service mail inbound handler registered' };
220
+ }
221
+ return await this.handleInboundPayload(dataArg.delivery, this.inboundHandler);
222
+ }));
223
+ }
22
224
  async sendNotification(optionsArg) { }
23
225
  async sendActionLink(optionsArg) { }
226
+ async readMailEnv(tokenArg) {
227
+ const prefix = tokenArg ? `MAIL_${tokenArg}_` : '';
228
+ return {
229
+ from: await this.readMailEnvVar(tokenArg ? `${prefix}FROM` : 'MAIL_FROM'),
230
+ smtpHost: await this.readMailEnvVar(`${prefix}SMTP_HOST`),
231
+ smtpPort: await this.readMailEnvVar(`${prefix}SMTP_PORT`),
232
+ smtpTlsMode: await this.readMailEnvVar(`${prefix}SMTP_TLS_MODE`),
233
+ smtpUsername: await this.readMailEnvVar(`${prefix}SMTP_USERNAME`),
234
+ smtpPassword: await this.readMailEnvVar(`${prefix}SMTP_PASSWORD`),
235
+ typedUrl: await this.readMailEnvVar(tokenArg ? `${prefix}TYPED_URL` : 'MAIL_TYPED_URL'),
236
+ apiCredentialId: await this.readMailEnvVar(tokenArg ? `${prefix}API_CREDENTIAL_ID` : 'MAIL_API_CREDENTIAL_ID'),
237
+ apiCredentialSecret: await this.readMailEnvVar(tokenArg ? `${prefix}API_CREDENTIAL_SECRET` : 'MAIL_API_CREDENTIAL_SECRET'),
238
+ };
239
+ }
240
+ async readMailEnvVar(envNameArg) {
241
+ return await this.platformClientRef.getConfiguredEnvVar(envNameArg)
242
+ || this.getCredentialEnvVarFromBindings(envNameArg);
243
+ }
244
+ getCredentialEnvVarFromBindings(envNameArg) {
245
+ for (const binding of this.platformClientRef.platformBindings || []) {
246
+ if (binding.desiredState === 'disabled' || binding.status === 'failed')
247
+ continue;
248
+ if (binding.capability !== 'email')
249
+ continue;
250
+ for (const credential of binding.credentials || []) {
251
+ const value = credential.env?.[envNameArg];
252
+ if (value)
253
+ return value;
254
+ }
255
+ }
256
+ }
257
+ hasAnyMailEnvValue(envArg) {
258
+ return Boolean(envArg && Object.values(envArg).some(Boolean));
259
+ }
260
+ async getServiceMailTypedCredentials(addressArg) {
261
+ const requestedAddress = addressArg?.trim().toLowerCase();
262
+ const requestedToken = requestedAddress ? this.getMailEnvToken(requestedAddress) : undefined;
263
+ const scopedEnv = requestedToken ? await this.readMailEnv(requestedToken) : undefined;
264
+ const hasScopedConfig = scopedEnv && Object.values(scopedEnv).some(Boolean);
265
+ const env = hasScopedConfig ? scopedEnv : await this.readMailEnv();
266
+ const from = env.from?.trim().toLowerCase();
267
+ if (!from)
268
+ throw new Error('MAIL_FROM is required for typed service mail');
269
+ if (requestedAddress && from !== requestedAddress) {
270
+ throw new Error(`No typed service mail credentials are configured for ${requestedAddress}`);
271
+ }
272
+ if (!env.typedUrl)
273
+ throw new Error('MAIL_TYPED_URL is required for typed service mail');
274
+ if (!env.apiCredentialId)
275
+ throw new Error('MAIL_API_CREDENTIAL_ID is required for typed service mail');
276
+ if (!env.apiCredentialSecret)
277
+ throw new Error('MAIL_API_CREDENTIAL_SECRET is required for typed service mail');
278
+ return {
279
+ from,
280
+ typedUrl: this.normalizeTypedSocketUrl(env.typedUrl),
281
+ credentialId: env.apiCredentialId,
282
+ credentialSecret: env.apiCredentialSecret,
283
+ addressToken: hasScopedConfig ? requestedToken : undefined,
284
+ };
285
+ }
286
+ async getMailTypedSocket(urlArg) {
287
+ const normalizedUrl = this.normalizeTypedSocketUrl(urlArg);
288
+ if (this.mailTypedSocket && this.mailTypedSocketUrl === normalizedUrl) {
289
+ return this.mailTypedSocket;
290
+ }
291
+ if (this.mailTypedSocketPromise && this.mailTypedSocketUrl === normalizedUrl) {
292
+ return await this.mailTypedSocketPromise;
293
+ }
294
+ if (this.mailTypedSocket || this.mailTypedSocketPromise) {
295
+ await this.stopMailTypedSocket();
296
+ }
297
+ this.mailTypedSocketUrl = normalizedUrl;
298
+ const abortController = new AbortController();
299
+ this.mailTypedSocketAbortController = abortController;
300
+ const socketPromise = plugins.typedsocket.TypedSocket.createClient(this.platformClientRef.typedrouter, normalizedUrl, { autoReconnect: true, abortSignal: abortController.signal });
301
+ this.mailTypedSocketPromise = socketPromise;
302
+ try {
303
+ const socket = await socketPromise;
304
+ if (this.mailTypedSocketPromise === socketPromise && this.mailTypedSocketUrl === normalizedUrl) {
305
+ this.mailTypedSocket = socket;
306
+ }
307
+ else {
308
+ await socket.stop();
309
+ }
310
+ return socket;
311
+ }
312
+ catch (error) {
313
+ if (this.mailTypedSocketPromise === socketPromise) {
314
+ this.mailTypedSocketPromise = undefined;
315
+ this.mailTypedSocketUrl = undefined;
316
+ this.mailTypedSocketAbortController = undefined;
317
+ }
318
+ throw error;
319
+ }
320
+ }
321
+ async stopMailTypedSocket() {
322
+ const socket = this.mailTypedSocket;
323
+ const socketPromise = this.mailTypedSocketPromise;
324
+ const abortController = this.mailTypedSocketAbortController;
325
+ this.mailTypedSocket = undefined;
326
+ this.mailTypedSocketPromise = undefined;
327
+ this.mailTypedSocketUrl = undefined;
328
+ this.mailTypedSocketAbortController = undefined;
329
+ abortController?.abort();
330
+ if (socket) {
331
+ await socket.stop();
332
+ return;
333
+ }
334
+ if (socketPromise) {
335
+ try {
336
+ const pendingSocket = await socketPromise;
337
+ await pendingSocket.stop();
338
+ }
339
+ catch {
340
+ // The pending connection already failed; there is no socket to stop.
341
+ }
342
+ }
343
+ }
344
+ normalizeTypedSocketUrl(urlArg) {
345
+ return urlArg.trim().replace(/\/typedrequest\/?$/, '').replace(/\/+$/, '');
346
+ }
347
+ normalizeTlsMode(valueArg) {
348
+ if (valueArg === 'plain' || valueArg === 'starttls' || valueArg === 'implicitTls')
349
+ return valueArg;
350
+ throw new Error(`Invalid SMTP_TLS_MODE: ${valueArg}`);
351
+ }
352
+ getMailEnvToken(addressArg) {
353
+ const token = addressArg.trim().toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '').toUpperCase();
354
+ return /^\d/.test(token) ? `ADDR_${token}` : token;
355
+ }
356
+ listToArray(valueArg) {
357
+ return Array.isArray(valueArg) ? valueArg : [valueArg];
358
+ }
359
+ normalizeAttachmentContent(contentArg) {
360
+ return Buffer.from(contentArg).toString('base64');
361
+ }
362
+ asRecord(valueArg) {
363
+ return valueArg && typeof valueArg === 'object' ? valueArg : {};
364
+ }
365
+ normalizeHeaders(headersArg) {
366
+ if (!headersArg || typeof headersArg !== 'object')
367
+ return undefined;
368
+ const result = {};
369
+ for (const [key, value] of Object.entries(headersArg)) {
370
+ if (Array.isArray(value)) {
371
+ result[key] = value.map(String);
372
+ }
373
+ else if (value !== undefined && value !== null) {
374
+ result[key] = String(value);
375
+ }
376
+ }
377
+ return result;
378
+ }
379
+ extractHeader(rawMessageArg, headerNameArg) {
380
+ const lowerName = `${headerNameArg.toLowerCase()}:`;
381
+ for (const line of rawMessageArg.split(/\r?\n/)) {
382
+ if (!line)
383
+ return undefined;
384
+ if (line.toLowerCase().startsWith(lowerName)) {
385
+ return line.slice(lowerName.length).trim();
386
+ }
387
+ }
388
+ }
24
389
  }
25
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbGNvbm5lY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2VtYWlsL2NsYXNzZXMuZW1haWxjb25uZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFFekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0QyxNQUFNLE9BQU8sZ0JBQWdCO0lBRzNCLFlBQVksb0JBQXNDO1FBQ2hELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxvQkFBb0IsQ0FBQztJQUNoRCxDQUFDO0lBRU0sS0FBSyxDQUFDLFNBQVMsQ0FDcEIsVUFBZ0Y7UUFFaEYsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDckMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsMkJBQTJCLFVBQVUsQ0FBQyxLQUFLLE9BQU8sVUFBVSxDQUFDLEVBQUU7O1VBRTlFLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDOztTQUVyRSxDQUFDLENBQUM7UUFDUCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDckMsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLFlBQVksR0FDaEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FDbkQsV0FBVyxDQUNaLENBQUM7UUFDSixNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDckQsT0FBTyxRQUFRLENBQUMsVUFBVSxDQUFDO0lBQzdCLENBQUM7SUFFTSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsVUFBNEQsSUFBRyxDQUFDO0lBRXZGLEtBQUssQ0FBQyxjQUFjLENBQUMsVUFBNEQsSUFBRyxDQUFDO0NBQzdGIn0=
390
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbGNvbm5lY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2VtYWlsL2NsYXNzZXMuZW1haWxjb25uZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFFekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQWlGdEMsTUFBTSxPQUFPLGdCQUFnQjtJQVMzQixZQUFZLG9CQUFzQztRQUYxQyxrQ0FBNkIsR0FBRyxLQUFLLENBQUM7UUFHNUMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLG9CQUFvQixDQUFDO0lBQ2hELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxTQUFTLENBQ3BCLFVBQWdGO1FBRWhGLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLDJCQUEyQixVQUFVLENBQUMsS0FBSyxPQUFPLFVBQVUsQ0FBQyxFQUFFOztVQUU5RSxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzs7U0FFckUsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3JDLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxZQUFZLEdBQ2hCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQ25ELFdBQVcsQ0FDWixDQUFDO1FBQ0osTUFBTSxRQUFRLEdBQUcsTUFBTSxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JELE9BQU8sUUFBUSxDQUFDLFVBQVUsQ0FB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
@@ -1 +1,2 @@
1
1
  export * from './classes.platformclient.js';
2
+ export * from './email/classes.emailconnector.js';
package/dist_ts/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './classes.platformclient.js';
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDIn0=
2
+ export * from './email/classes.emailconnector.js';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsbUNBQW1DLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/platformclient",
3
- "version": "1.1.5",
3
+ "version": "2.0.0",
4
4
  "private": false,
5
5
  "description": "a module that makes it really easy to use the serve.zone platform inside your app",
6
6
  "main": "dist_ts/index.js",
@@ -10,10 +10,10 @@
10
10
  "license": "MIT",
11
11
  "devDependencies": {
12
12
  "@git.zone/tsbuild": "^4.4.2",
13
- "@git.zone/tsbundle": "^2.10.4",
13
+ "@git.zone/tsbundle": "^2.11.0",
14
14
  "@git.zone/tsrun": "^2.0.4",
15
15
  "@git.zone/tstest": "^3.6.6",
16
- "@types/node": "^25.9.1"
16
+ "@types/node": "^25.9.3"
17
17
  },
18
18
  "dependencies": {
19
19
  "@api.global/typedrequest": "^3.3.0",
@@ -22,7 +22,7 @@
22
22
  "@push.rocks/qenv": "^6.1.4",
23
23
  "@push.rocks/smartlog": "^3.2.2",
24
24
  "@push.rocks/smartntml": "^2.0.9",
25
- "@serve.zone/interfaces": "^5.5.0"
25
+ "@serve.zone/interfaces": "^7.28.0"
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
package/readme.md CHANGED
@@ -38,7 +38,7 @@ await platformClient.emailConnector.sendEmail({
38
38
 
39
39
  | Connector | Main methods | Platform capability |
40
40
  | --- | --- | --- |
41
- | `emailConnector` | `sendEmail()` | `email` |
41
+ | `emailConnector` | `getServiceMailStatus()`, `getServiceMailCredentials()`, `sendMail()`, `sendText()`, `sendHtml()`, `registerInboundHandler()`, `normalizeInboundMessage()`, `handleInboundPayload()`, `createInboundHandler()`, `sendEmail()` | `email` |
42
42
  | `smsConnector` | `sendSms()`, `sendSmsVerifcation()` | `sms` |
43
43
  | `pushNotificationConnector` | `sendPushNotification()` | `pushnotification` |
44
44
  | `letterConnector` | `sendLetter()` | `letter` |
@@ -57,6 +57,10 @@ The client needs an authorization string and a platform endpoint. You can provid
57
57
 
58
58
  Binding environment variables must contain JSON encoded `IPlatformBinding` objects from `@serve.zone/interfaces`.
59
59
 
60
+ Service mail credentials can be provided directly as environment variables or through `email` platform binding credentials. Standard platformclient mail uses dcrouter TypedSocket/TypedRequest service credentials. The default sender uses `MAIL_FROM`, `MAIL_TYPED_URL`, `MAIL_API_CREDENTIAL_ID`, and `MAIL_API_CREDENTIAL_SECRET`. Additional configured sender addresses use scoped variables such as `MAIL_TEST_SERVICE_GATED_ONE_FROM`, `MAIL_TEST_SERVICE_GATED_ONE_TYPED_URL`, `MAIL_TEST_SERVICE_GATED_ONE_API_CREDENTIAL_ID`, and `MAIL_TEST_SERVICE_GATED_ONE_API_CREDENTIAL_SECRET`.
61
+
62
+ SMTP compatibility credentials are still discoverable with `getServiceMailCredentials()` for applications that explicitly implement SMTP themselves. Those compatibility variables are `SMTP_HOST`, `SMTP_PORT`, `SMTP_TLS_MODE`, `SMTP_USERNAME`, and `SMTP_PASSWORD`, plus scoped `MAIL_<TOKEN>_SMTP_*` variants. They are not used by `sendMail()`, `sendText()`, `sendHtml()`, or `registerInboundHandler()`.
63
+
60
64
  ```typescript
61
65
  import { SzPlatformClient } from '@serve.zone/platformclient';
62
66
 
@@ -100,9 +104,79 @@ console.log(verificationCode); // 123456
100
104
 
101
105
  The current SMS verification method is spelled `sendSmsVerifcation()` in code. Use that exact method name until the public API changes.
102
106
 
107
+ ## Lifecycle
108
+
109
+ `SzPlatformClient` keeps TypedSocket connections open for platform requests and typed service-mail delivery. Call `stop()` when a short-lived process, worker, or test is done with the client.
110
+
111
+ ```typescript
112
+ const client = new SzPlatformClient({
113
+ token: process.env.SERVEZONE_PLATFORM_TOKEN,
114
+ platformUrl: process.env.SERVEZONE_PLATFORM_URL,
115
+ });
116
+
117
+ await client.init();
118
+
119
+ try {
120
+ await client.emailConnector.sendText({
121
+ to: 'user@example.com',
122
+ subject: 'Done',
123
+ text: 'The job has finished.',
124
+ });
125
+ } finally {
126
+ await client.stop();
127
+ }
128
+ ```
129
+
103
130
  ## Connector Examples
104
131
 
105
- Email:
132
+ Service mail over managed TypedSocket credentials:
133
+
134
+ ```typescript
135
+ const status = await client.emailConnector.getServiceMailStatus();
136
+
137
+ if (status.ready) {
138
+ await client.emailConnector.sendText({
139
+ to: 'user@example.com',
140
+ subject: 'Service mail ready',
141
+ text: 'This message was sent through the managed service mail identity.',
142
+ });
143
+ }
144
+ ```
145
+
146
+ `getServiceMailStatus().ready` means the typed service-mail path is configured. The status also exposes `transport`, `typedUrl`, `typedCredentialConfigured`, and `smtpReady` so applications can distinguish standard TypedSocket mail from explicit SMTP compatibility configuration.
147
+
148
+ Specific sender address:
149
+
150
+ ```typescript
151
+ await client.emailConnector.sendHtml({
152
+ from: 'test-service@gated.one',
153
+ to: 'user@example.com',
154
+ subject: 'Platform capability test',
155
+ html: '<p>The service mail identity is working.</p>',
156
+ });
157
+ ```
158
+
159
+ Typed inbound mail registration:
160
+
161
+ ```typescript
162
+ await client.emailConnector.registerInboundHandler(async (message) => {
163
+ console.log(message.from, message.to, message.subject);
164
+ return { accepted: true, workAppMessageId: message.messageId };
165
+ });
166
+ ```
167
+
168
+ `registerInboundHandler()` registers this client connection as the typed endpoint for the configured service mail address. dcrouter then delivers inbound messages through the shared `deliverInboundMail` TypedRequest contract.
169
+
170
+ Inbound message normalization for webhook or direct TypedRequest-style delivery:
171
+
172
+ ```typescript
173
+ const inboundHandler = client.emailConnector.createInboundHandler(async (message) => {
174
+ console.log(message.from, message.to, message.subject);
175
+ return { accepted: true };
176
+ });
177
+ ```
178
+
179
+ Legacy platform-service email request:
106
180
 
107
181
  ```typescript
108
182
  await client.emailConnector.sendEmail({
@@ -144,7 +218,7 @@ await client.letterConnector.sendLetter({
144
218
  });
145
219
  ```
146
220
 
147
- Exact fields are defined in `@serve.zone/interfaces` under `platform.email`, `platform.sms`, `platform.pushnotification`, and `platform.letter`.
221
+ Service-mail helper option and result types are exported from `@serve.zone/platformclient`. The legacy platform-service request fields are defined in `@serve.zone/interfaces` under `platform.email`, `platform.sms`, `platform.pushnotification`, and `platform.letter`.
148
222
 
149
223
  ## Platform Bindings
150
224
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/platformclient',
6
- version: '1.1.5',
6
+ version: '2.0.0',
7
7
  description: 'a module that makes it really easy to use the serve.zone platform inside your app'
8
8
  }
@@ -174,6 +174,13 @@ export class SzPlatformClient {
174
174
  }
175
175
  }
176
176
 
177
+ public async stop(): Promise<void> {
178
+ await this.emailConnector.stop();
179
+ if (this.typedsocket) {
180
+ await this.typedsocket.stop();
181
+ }
182
+ }
183
+
177
184
  private async discoverPlatformBindings() {
178
185
  const bindings: plugins.servezoneInterfaces.platform.IPlatformBinding[] = [];
179
186
  const envBindings = await this.getConfiguredEnvVar('SERVEZONE_PLATFORM_BINDINGS');
@@ -217,7 +224,7 @@ export class SzPlatformClient {
217
224
  return Array.from(bindingMap.values());
218
225
  }
219
226
 
220
- private async getConfiguredEnvVar(envNameArg: string) {
227
+ public async getConfiguredEnvVar(envNameArg: string) {
221
228
  const processValue = this.getProcessEnvVar(envNameArg);
222
229
  if (processValue) {
223
230
  return processValue;
@@ -3,13 +3,101 @@ import * as plugins from '../plugins.js';
3
3
 
4
4
  import { logger } from '../logger.js';
5
5
 
6
+ export type TServiceMailTlsMode = 'plain' | 'starttls' | 'implicitTls';
7
+
8
+ export interface IServiceMailSmtpCredentials {
9
+ from: string;
10
+ host: string;
11
+ port: number;
12
+ tlsMode: TServiceMailTlsMode;
13
+ username: string;
14
+ password: string;
15
+ addressToken?: string;
16
+ }
17
+
18
+ export interface IServiceMailTypedCredentials {
19
+ from: string;
20
+ typedUrl: string;
21
+ credentialId: string;
22
+ credentialSecret: string;
23
+ addressToken?: string;
24
+ }
25
+
26
+ export interface IServiceMailStatus {
27
+ ready: boolean;
28
+ from?: string;
29
+ host?: string;
30
+ port?: number;
31
+ tlsMode?: TServiceMailTlsMode;
32
+ typedUrl?: string;
33
+ transport?: 'typedsocket' | 'smtp' | 'none';
34
+ usernameConfigured: boolean;
35
+ passwordConfigured: boolean;
36
+ typedCredentialConfigured?: boolean;
37
+ smtpReady?: boolean;
38
+ missing: string[];
39
+ }
40
+
41
+ export interface IServiceMailAttachment {
42
+ filename: string;
43
+ contentType?: string;
44
+ content: string | Uint8Array;
45
+ }
46
+
47
+ export interface IServiceMailSendOptions {
48
+ from?: string;
49
+ to: string | string[];
50
+ cc?: string | string[];
51
+ bcc?: string | string[];
52
+ subject: string;
53
+ text?: string;
54
+ html?: string;
55
+ headers?: Record<string, string>;
56
+ attachments?: IServiceMailAttachment[];
57
+ }
58
+
59
+ export interface IServiceMailSendResult {
60
+ messageId?: string;
61
+ accepted?: string[];
62
+ rejected?: string[];
63
+ response?: string;
64
+ }
65
+
66
+ export interface IServiceMailInboundMessage extends plugins.servezoneInterfaces.data.IMailInboundMessagePayload {
67
+ from: string;
68
+ to: string[];
69
+ receivedAtIso: string;
70
+ }
71
+
72
+ export interface IServiceMailInboundHandlerResult {
73
+ accepted?: boolean;
74
+ workAppMessageId?: string;
75
+ message?: string;
76
+ }
77
+
78
+ export type IServiceMailInboundHandleResult =
79
+ plugins.servezoneInterfaces.requests.mail.IReq_DeliverInboundMail['response'];
80
+
81
+ export type TServiceMailInboundHandler = (
82
+ messageArg: IServiceMailInboundMessage,
83
+ ) => Promise<IServiceMailInboundHandlerResult | void> | IServiceMailInboundHandlerResult | void;
84
+
6
85
  export class SzEmailConnector {
7
86
  public platformClientRef: SzPlatformClient;
87
+ private mailTypedSocket?: plugins.typedsocket.TypedSocket;
88
+ private mailTypedSocketUrl?: string;
89
+ private mailTypedSocketPromise?: Promise<plugins.typedsocket.TypedSocket>;
90
+ private mailTypedSocketAbortController?: AbortController;
91
+ private inboundHandler?: TServiceMailInboundHandler;
92
+ private inboundTypedHandlerRegistered = false;
8
93
 
9
94
  constructor(platformClientRefArg: SzPlatformClient) {
10
95
  this.platformClientRef = platformClientRefArg;
11
96
  }
12
97
 
98
+ /**
99
+ * Legacy platform-service email path. New service-mail code should use sendMail().
100
+ */
13
101
  public async sendEmail(
14
102
  optionsArg: plugins.servezoneInterfaces.platform.email.IReq_SendEmail['request']
15
103
  ) {
@@ -33,7 +121,405 @@ export class SzEmailConnector {
33
121
  return response.responseId;
34
122
  }
35
123
 
124
+ public async getServiceMailStatus(addressArg?: string): Promise<IServiceMailStatus> {
125
+ const requestedAddress = addressArg?.trim().toLowerCase();
126
+ const token = requestedAddress ? this.getMailEnvToken(requestedAddress) : undefined;
127
+ const scopedEnv = token ? await this.readMailEnv(token) : undefined;
128
+ const defaultEnv = token ? await this.readMailEnv() : undefined;
129
+ const useDefaultEnv = requestedAddress
130
+ && !this.hasAnyMailEnvValue(scopedEnv)
131
+ && defaultEnv?.from?.trim().toLowerCase() === requestedAddress;
132
+ const env = useDefaultEnv ? defaultEnv! : scopedEnv || await this.readMailEnv();
133
+ const missingPrefix = useDefaultEnv || !token ? undefined : token;
134
+ const port = env.smtpPort ? Number(env.smtpPort) : undefined;
135
+ const tlsMode = this.normalizeTlsMode(env.smtpTlsMode || 'starttls');
136
+ const typedMissing: string[] = [];
137
+ const smtpMissing: string[] = [];
138
+ if (!env.typedUrl) typedMissing.push(missingPrefix ? `MAIL_${missingPrefix}_TYPED_URL` : 'MAIL_TYPED_URL');
139
+ if (!env.apiCredentialId) typedMissing.push(missingPrefix ? `MAIL_${missingPrefix}_API_CREDENTIAL_ID` : 'MAIL_API_CREDENTIAL_ID');
140
+ if (!env.apiCredentialSecret) typedMissing.push(missingPrefix ? `MAIL_${missingPrefix}_API_CREDENTIAL_SECRET` : 'MAIL_API_CREDENTIAL_SECRET');
141
+ if (!env.smtpHost) smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_HOST` : 'SMTP_HOST');
142
+ if (!env.smtpPort || !Number.isInteger(port) || port! < 1 || port! > 65535) {
143
+ smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_PORT` : 'SMTP_PORT');
144
+ }
145
+ if (!env.smtpUsername) smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_USERNAME` : 'SMTP_USERNAME');
146
+ if (!env.smtpPassword) smtpMissing.push(missingPrefix ? `MAIL_${missingPrefix}_SMTP_PASSWORD` : 'SMTP_PASSWORD');
147
+ const fromMissing = env.from ? [] : [missingPrefix ? `MAIL_${missingPrefix}_FROM` : 'MAIL_FROM'];
148
+ const typedReady = fromMissing.length === 0 && typedMissing.length === 0;
149
+ const smtpReady = fromMissing.length === 0 && smtpMissing.length === 0;
150
+ return {
151
+ ready: typedReady,
152
+ from: env.from,
153
+ host: env.smtpHost,
154
+ port,
155
+ tlsMode,
156
+ typedUrl: env.typedUrl,
157
+ transport: typedReady ? 'typedsocket' : smtpReady ? 'smtp' : 'none',
158
+ usernameConfigured: Boolean(env.smtpUsername),
159
+ passwordConfigured: Boolean(env.smtpPassword),
160
+ typedCredentialConfigured: Boolean(env.apiCredentialId && env.apiCredentialSecret),
161
+ smtpReady,
162
+ missing: typedReady ? [] : [...fromMissing, ...typedMissing],
163
+ };
164
+ }
165
+
166
+ public async getServiceMailCredentials(addressArg?: string): Promise<IServiceMailSmtpCredentials> {
167
+ const requestedAddress = addressArg?.trim().toLowerCase();
168
+ const requestedToken = requestedAddress ? this.getMailEnvToken(requestedAddress) : undefined;
169
+ const scopedEnv = requestedToken ? await this.readMailEnv(requestedToken) : undefined;
170
+ const hasScopedConfig = scopedEnv && Object.values(scopedEnv).some(Boolean);
171
+ const env = hasScopedConfig ? scopedEnv! : await this.readMailEnv();
172
+ const from = env.from?.trim().toLowerCase();
173
+ if (!from) throw new Error('MAIL_FROM is required for service mail');
174
+ if (requestedAddress && from !== requestedAddress) {
175
+ throw new Error(`No service mail credentials are configured for ${requestedAddress}`);
176
+ }
177
+ const port = Number(env.smtpPort);
178
+ if (!env.smtpHost) throw new Error('SMTP_HOST is required for service mail');
179
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
180
+ throw new Error('SMTP_PORT must be an integer between 1 and 65535');
181
+ }
182
+ if (!env.smtpUsername) throw new Error('SMTP_USERNAME is required for service mail');
183
+ if (!env.smtpPassword) throw new Error('SMTP_PASSWORD is required for service mail');
184
+ return {
185
+ from,
186
+ host: env.smtpHost,
187
+ port,
188
+ tlsMode: this.normalizeTlsMode(env.smtpTlsMode || 'starttls'),
189
+ username: env.smtpUsername,
190
+ password: env.smtpPassword,
191
+ addressToken: hasScopedConfig ? requestedToken : undefined,
192
+ };
193
+ }
194
+
195
+ public async sendText(optionsArg: Omit<IServiceMailSendOptions, 'html'> & { text: string }) {
196
+ return await this.sendMail(optionsArg);
197
+ }
198
+
199
+ public async sendHtml(optionsArg: Omit<IServiceMailSendOptions, 'text'> & { html: string }) {
200
+ return await this.sendMail(optionsArg);
201
+ }
202
+
203
+ public async sendMail(optionsArg: IServiceMailSendOptions): Promise<IServiceMailSendResult> {
204
+ if (!optionsArg.text && !optionsArg.html) {
205
+ throw new Error('Either text or html is required for service mail');
206
+ }
207
+ if (this.platformClientRef.debugMode) {
208
+ logger.log('info', `service mail debug send: ${optionsArg.subject} to ${this.listToArray(optionsArg.to).join(', ')}`);
209
+ return { messageId: 'debug' };
210
+ }
211
+
212
+ const credentials = await this.getServiceMailTypedCredentials(optionsArg.from);
213
+ const typedSocket = await this.getMailTypedSocket(credentials.typedUrl);
214
+ const request = typedSocket.createTypedRequest<plugins.servezoneInterfaces.requests.mail.IReq_EnqueueMail>('enqueueMail');
215
+ const result = await request.fire({
216
+ auth: {
217
+ credentialId: credentials.credentialId,
218
+ credentialSecret: credentials.credentialSecret,
219
+ },
220
+ outboundIdentityId: credentials.credentialId,
221
+ message: {
222
+ from: credentials.from,
223
+ to: this.listToArray(optionsArg.to),
224
+ cc: optionsArg.cc ? this.listToArray(optionsArg.cc) : undefined,
225
+ bcc: optionsArg.bcc ? this.listToArray(optionsArg.bcc) : undefined,
226
+ subject: optionsArg.subject,
227
+ text: optionsArg.text,
228
+ html: optionsArg.html,
229
+ headers: optionsArg.headers,
230
+ attachments: optionsArg.attachments?.map((attachmentArg) => ({
231
+ filename: attachmentArg.filename,
232
+ contentType: attachmentArg.contentType,
233
+ binaryAttachmentString: this.normalizeAttachmentContent(attachmentArg.content),
234
+ })),
235
+ },
236
+ });
237
+ if (!result.accepted) {
238
+ throw new Error(result.message || 'service mail was not accepted by dcrouter');
239
+ }
240
+ return {
241
+ messageId: result.spoolItemId,
242
+ accepted: this.listToArray(optionsArg.to),
243
+ rejected: [],
244
+ response: result.message,
245
+ };
246
+ }
247
+
248
+ public async registerInboundHandler(
249
+ handlerArg: TServiceMailInboundHandler,
250
+ addressArg?: string,
251
+ ): Promise<plugins.servezoneInterfaces.requests.mail.IReq_RegisterServiceMailEndpoint['response']> {
252
+ this.inboundHandler = handlerArg;
253
+ this.ensureInboundTypedHandler();
254
+ const credentials = await this.getServiceMailTypedCredentials(addressArg);
255
+ const typedSocket = await this.getMailTypedSocket(credentials.typedUrl);
256
+ const request = typedSocket.createTypedRequest<plugins.servezoneInterfaces.requests.mail.IReq_RegisterServiceMailEndpoint>('registerServiceMailEndpoint');
257
+ const result = await request.fire({
258
+ auth: {
259
+ credentialId: credentials.credentialId,
260
+ credentialSecret: credentials.credentialSecret,
261
+ },
262
+ addresses: [credentials.from],
263
+ });
264
+ if (!result.success) {
265
+ throw new Error(result.message || 'Could not register service mail endpoint');
266
+ }
267
+ return result;
268
+ }
269
+
270
+ public async stop(): Promise<void> {
271
+ await this.stopMailTypedSocket();
272
+ }
273
+
274
+ public normalizeInboundMessage(payloadArg: unknown): IServiceMailInboundMessage {
275
+ const payload = this.asRecord(payloadArg);
276
+ const deliveryCandidate = this.asRecord(payload.delivery || payload.message || payload);
277
+ const envelope = this.asRecord(deliveryCandidate.envelope);
278
+ const rawMessage = typeof deliveryCandidate.rawMessage === 'string' ? deliveryCandidate.rawMessage : '';
279
+ const rcptTo = Array.isArray(envelope.rcptTo) ? envelope.rcptTo.map(String) : [];
280
+ const receivedAt = typeof deliveryCandidate.receivedAt === 'number' ? deliveryCandidate.receivedAt : Date.now();
281
+ return {
282
+ spoolItemId: String(deliveryCandidate.spoolItemId || deliveryCandidate.id || ''),
283
+ owner: deliveryCandidate.owner as plugins.servezoneInterfaces.data.IMailResourceOwner | undefined,
284
+ envelope: {
285
+ mailFrom: String(envelope.mailFrom || deliveryCandidate.from || ''),
286
+ rcptTo,
287
+ },
288
+ rawMessage,
289
+ sizeBytes: typeof deliveryCandidate.sizeBytes === 'number' ? deliveryCandidate.sizeBytes : rawMessage.length,
290
+ messageId: deliveryCandidate.messageId ? String(deliveryCandidate.messageId) : undefined,
291
+ subject: deliveryCandidate.subject ? String(deliveryCandidate.subject) : this.extractHeader(rawMessage, 'subject'),
292
+ headers: this.normalizeHeaders(deliveryCandidate.headers),
293
+ source: deliveryCandidate.source as plugins.servezoneInterfaces.data.IMailConnectionInfo | undefined,
294
+ receivedAt,
295
+ from: String(envelope.mailFrom || deliveryCandidate.from || ''),
296
+ to: rcptTo,
297
+ receivedAtIso: new Date(receivedAt).toISOString(),
298
+ };
299
+ }
300
+
301
+ public async handleInboundPayload(
302
+ payloadArg: unknown,
303
+ handlerArg: TServiceMailInboundHandler,
304
+ ): Promise<IServiceMailInboundHandleResult> {
305
+ const message = this.normalizeInboundMessage(payloadArg);
306
+ const result = await handlerArg(message);
307
+ return {
308
+ accepted: result?.accepted !== false,
309
+ workAppMessageId: result?.workAppMessageId,
310
+ message: result?.message,
311
+ };
312
+ }
313
+
314
+ public createInboundHandler(handlerArg: TServiceMailInboundHandler) {
315
+ return async (payloadArg: unknown) => await this.handleInboundPayload(payloadArg, handlerArg);
316
+ }
317
+
318
+ private ensureInboundTypedHandler(): void {
319
+ if (this.inboundTypedHandlerRegistered) return;
320
+ this.inboundTypedHandlerRegistered = true;
321
+ this.platformClientRef.typedrouter.addTypedHandler(
322
+ new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.mail.IReq_DeliverInboundMail>(
323
+ 'deliverInboundMail',
324
+ async (dataArg) => {
325
+ if (!this.inboundHandler) {
326
+ return { accepted: false, message: 'No service mail inbound handler registered' };
327
+ }
328
+ return await this.handleInboundPayload(dataArg.delivery, this.inboundHandler);
329
+ },
330
+ ),
331
+ );
332
+ }
333
+
36
334
  public async sendNotification(optionsArg: { toArg: string; subject: string; text: string }) {}
37
335
 
38
336
  public async sendActionLink(optionsArg: { toArg: string; subject: string; text: string }) {}
337
+
338
+ private async readMailEnv(tokenArg?: string): Promise<{
339
+ from?: string;
340
+ smtpHost?: string;
341
+ smtpPort?: string;
342
+ smtpTlsMode?: string;
343
+ smtpUsername?: string;
344
+ smtpPassword?: string;
345
+ typedUrl?: string;
346
+ apiCredentialId?: string;
347
+ apiCredentialSecret?: string;
348
+ }> {
349
+ const prefix = tokenArg ? `MAIL_${tokenArg}_` : '';
350
+ return {
351
+ from: await this.readMailEnvVar(tokenArg ? `${prefix}FROM` : 'MAIL_FROM'),
352
+ smtpHost: await this.readMailEnvVar(`${prefix}SMTP_HOST`),
353
+ smtpPort: await this.readMailEnvVar(`${prefix}SMTP_PORT`),
354
+ smtpTlsMode: await this.readMailEnvVar(`${prefix}SMTP_TLS_MODE`),
355
+ smtpUsername: await this.readMailEnvVar(`${prefix}SMTP_USERNAME`),
356
+ smtpPassword: await this.readMailEnvVar(`${prefix}SMTP_PASSWORD`),
357
+ typedUrl: await this.readMailEnvVar(tokenArg ? `${prefix}TYPED_URL` : 'MAIL_TYPED_URL'),
358
+ apiCredentialId: await this.readMailEnvVar(tokenArg ? `${prefix}API_CREDENTIAL_ID` : 'MAIL_API_CREDENTIAL_ID'),
359
+ apiCredentialSecret: await this.readMailEnvVar(tokenArg ? `${prefix}API_CREDENTIAL_SECRET` : 'MAIL_API_CREDENTIAL_SECRET'),
360
+ };
361
+ }
362
+
363
+ private async readMailEnvVar(envNameArg: string): Promise<string | undefined> {
364
+ return await this.platformClientRef.getConfiguredEnvVar(envNameArg)
365
+ || this.getCredentialEnvVarFromBindings(envNameArg);
366
+ }
367
+
368
+ private getCredentialEnvVarFromBindings(envNameArg: string): string | undefined {
369
+ for (const binding of this.platformClientRef.platformBindings || []) {
370
+ if (binding.desiredState === 'disabled' || binding.status === 'failed') continue;
371
+ if (binding.capability !== 'email') continue;
372
+ for (const credential of binding.credentials || []) {
373
+ const value = credential.env?.[envNameArg];
374
+ if (value) return value;
375
+ }
376
+ }
377
+ }
378
+
379
+ private hasAnyMailEnvValue(envArg?: {
380
+ from?: string;
381
+ smtpHost?: string;
382
+ smtpPort?: string;
383
+ smtpTlsMode?: string;
384
+ smtpUsername?: string;
385
+ smtpPassword?: string;
386
+ typedUrl?: string;
387
+ apiCredentialId?: string;
388
+ apiCredentialSecret?: string;
389
+ }): boolean {
390
+ return Boolean(envArg && Object.values(envArg).some(Boolean));
391
+ }
392
+
393
+ private async getServiceMailTypedCredentials(addressArg?: string): Promise<IServiceMailTypedCredentials> {
394
+ const requestedAddress = addressArg?.trim().toLowerCase();
395
+ const requestedToken = requestedAddress ? this.getMailEnvToken(requestedAddress) : undefined;
396
+ const scopedEnv = requestedToken ? await this.readMailEnv(requestedToken) : undefined;
397
+ const hasScopedConfig = scopedEnv && Object.values(scopedEnv).some(Boolean);
398
+ const env = hasScopedConfig ? scopedEnv! : await this.readMailEnv();
399
+ const from = env.from?.trim().toLowerCase();
400
+ if (!from) throw new Error('MAIL_FROM is required for typed service mail');
401
+ if (requestedAddress && from !== requestedAddress) {
402
+ throw new Error(`No typed service mail credentials are configured for ${requestedAddress}`);
403
+ }
404
+ if (!env.typedUrl) throw new Error('MAIL_TYPED_URL is required for typed service mail');
405
+ if (!env.apiCredentialId) throw new Error('MAIL_API_CREDENTIAL_ID is required for typed service mail');
406
+ if (!env.apiCredentialSecret) throw new Error('MAIL_API_CREDENTIAL_SECRET is required for typed service mail');
407
+ return {
408
+ from,
409
+ typedUrl: this.normalizeTypedSocketUrl(env.typedUrl),
410
+ credentialId: env.apiCredentialId,
411
+ credentialSecret: env.apiCredentialSecret,
412
+ addressToken: hasScopedConfig ? requestedToken : undefined,
413
+ };
414
+ }
415
+
416
+ private async getMailTypedSocket(urlArg: string): Promise<plugins.typedsocket.TypedSocket> {
417
+ const normalizedUrl = this.normalizeTypedSocketUrl(urlArg);
418
+ if (this.mailTypedSocket && this.mailTypedSocketUrl === normalizedUrl) {
419
+ return this.mailTypedSocket;
420
+ }
421
+ if (this.mailTypedSocketPromise && this.mailTypedSocketUrl === normalizedUrl) {
422
+ return await this.mailTypedSocketPromise;
423
+ }
424
+ if (this.mailTypedSocket || this.mailTypedSocketPromise) {
425
+ await this.stopMailTypedSocket();
426
+ }
427
+ this.mailTypedSocketUrl = normalizedUrl;
428
+ const abortController = new AbortController();
429
+ this.mailTypedSocketAbortController = abortController;
430
+ const socketPromise = plugins.typedsocket.TypedSocket.createClient(
431
+ this.platformClientRef.typedrouter,
432
+ normalizedUrl,
433
+ { autoReconnect: true, abortSignal: abortController.signal },
434
+ );
435
+ this.mailTypedSocketPromise = socketPromise;
436
+ try {
437
+ const socket = await socketPromise;
438
+ if (this.mailTypedSocketPromise === socketPromise && this.mailTypedSocketUrl === normalizedUrl) {
439
+ this.mailTypedSocket = socket;
440
+ } else {
441
+ await socket.stop();
442
+ }
443
+ return socket;
444
+ } catch (error) {
445
+ if (this.mailTypedSocketPromise === socketPromise) {
446
+ this.mailTypedSocketPromise = undefined;
447
+ this.mailTypedSocketUrl = undefined;
448
+ this.mailTypedSocketAbortController = undefined;
449
+ }
450
+ throw error;
451
+ }
452
+ }
453
+
454
+ private async stopMailTypedSocket(): Promise<void> {
455
+ const socket = this.mailTypedSocket;
456
+ const socketPromise = this.mailTypedSocketPromise;
457
+ const abortController = this.mailTypedSocketAbortController;
458
+ this.mailTypedSocket = undefined;
459
+ this.mailTypedSocketPromise = undefined;
460
+ this.mailTypedSocketUrl = undefined;
461
+ this.mailTypedSocketAbortController = undefined;
462
+ abortController?.abort();
463
+ if (socket) {
464
+ await socket.stop();
465
+ return;
466
+ }
467
+ if (socketPromise) {
468
+ try {
469
+ const pendingSocket = await socketPromise;
470
+ await pendingSocket.stop();
471
+ } catch {
472
+ // The pending connection already failed; there is no socket to stop.
473
+ }
474
+ }
475
+ }
476
+
477
+ private normalizeTypedSocketUrl(urlArg: string): string {
478
+ return urlArg.trim().replace(/\/typedrequest\/?$/, '').replace(/\/+$/, '');
479
+ }
480
+
481
+ private normalizeTlsMode(valueArg: string): TServiceMailTlsMode {
482
+ if (valueArg === 'plain' || valueArg === 'starttls' || valueArg === 'implicitTls') return valueArg;
483
+ throw new Error(`Invalid SMTP_TLS_MODE: ${valueArg}`);
484
+ }
485
+
486
+ private getMailEnvToken(addressArg: string): string {
487
+ const token = addressArg.trim().toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '').toUpperCase();
488
+ return /^\d/.test(token) ? `ADDR_${token}` : token;
489
+ }
490
+
491
+ private listToArray(valueArg: string | string[]): string[] {
492
+ return Array.isArray(valueArg) ? valueArg : [valueArg];
493
+ }
494
+
495
+ private normalizeAttachmentContent(contentArg: string | Uint8Array): string {
496
+ return Buffer.from(contentArg).toString('base64');
497
+ }
498
+
499
+ private asRecord(valueArg: unknown): Record<string, unknown> {
500
+ return valueArg && typeof valueArg === 'object' ? valueArg as Record<string, unknown> : {};
501
+ }
502
+
503
+ private normalizeHeaders(headersArg: unknown): Record<string, string | string[]> | undefined {
504
+ if (!headersArg || typeof headersArg !== 'object') return undefined;
505
+ const result: Record<string, string | string[]> = {};
506
+ for (const [key, value] of Object.entries(headersArg as Record<string, unknown>)) {
507
+ if (Array.isArray(value)) {
508
+ result[key] = value.map(String);
509
+ } else if (value !== undefined && value !== null) {
510
+ result[key] = String(value);
511
+ }
512
+ }
513
+ return result;
514
+ }
515
+
516
+ private extractHeader(rawMessageArg: string, headerNameArg: string): string | undefined {
517
+ const lowerName = `${headerNameArg.toLowerCase()}:`;
518
+ for (const line of rawMessageArg.split(/\r?\n/)) {
519
+ if (!line) return undefined;
520
+ if (line.toLowerCase().startsWith(lowerName)) {
521
+ return line.slice(lowerName.length).trim();
522
+ }
523
+ }
524
+ }
39
525
  }
package/ts/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './classes.platformclient.js';
2
+ export * from './email/classes.emailconnector.js';