@technomoron/mail-magic 1.0.43 → 1.0.44

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/CHANGES CHANGED
@@ -1,6 +1,13 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
+ Version 1.0.44 (2026-03-05)
5
+
6
+ - fix(autoreload): catch unhandled promise rejections from async `reload()` in `enableInitDataAutoReload` `onChange` callback.
7
+ - fix(mailer): validate that parsed `vars` is a non-null, non-array object after `JSON.parse`; return 400 for invalid types.
8
+ - docs(utils): add doc comment to `buildRequestMeta` clarifying it is informational and requires a trusted reverse proxy for reliable IP data.
9
+ - (Changes generated/assisted by Claude Code (profile: anthropic-claude-opus-4-6/high).)
10
+
4
11
  Version 1.0.43 (2026-03-04)
5
12
 
6
13
  - fix(security): add allowlist for custom email headers on `/v1/tx/message` to prevent header injection via arbitrary keys (e.g. `Bcc`, `From`, `Sender`).
@@ -89,6 +89,9 @@ export class MailerAPI extends ApiModule {
89
89
  throw new ApiError({ code: 400, message: 'Invalid JSON provided in "vars"' });
90
90
  }
91
91
  }
92
+ if (!parsedVars || typeof parsedVars !== 'object' || Array.isArray(parsedVars)) {
93
+ throw new ApiError({ code: 400, message: '"vars" must be a JSON object' });
94
+ }
92
95
  const thevars = parsedVars;
93
96
  const { valid, invalid } = this.validateEmails(rcpt);
94
97
  if (invalid.length > 0) {
@@ -18,7 +18,7 @@ type AutoReloadContext = {
18
18
  config_filename: (name: string) => string;
19
19
  print_debug: (msg: string) => void;
20
20
  };
21
- export declare function enableInitDataAutoReload(ctx: AutoReloadContext, reload: () => void): AutoReloadHandle | null;
21
+ export declare function enableInitDataAutoReload(ctx: AutoReloadContext, reload: () => void | Promise<void>): AutoReloadHandle | null;
22
22
  export declare class mailStore {
23
23
  private env;
24
24
  vars: MailStoreVars;
@@ -38,8 +38,12 @@ export function enableInitDataAutoReload(ctx, reload) {
38
38
  debounceTimer = setTimeout(() => {
39
39
  debounceTimer = null;
40
40
  ctx.print_debug('Config file changed, reloading...');
41
+ // reload() may be sync or async — try/catch handles a synchronous
42
+ // throw, while Promise.resolve().catch() handles an async rejection.
41
43
  try {
42
- reload();
44
+ Promise.resolve(reload()).catch((err) => {
45
+ ctx.print_debug(`Failed to reload config: ${err}`);
46
+ });
43
47
  }
44
48
  catch (err) {
45
49
  ctx.print_debug(`Failed to reload config: ${err}`);
@@ -19,6 +19,13 @@ export declare function user_and_domain(domain_id: number): Promise<{
19
19
  user: api_user;
20
20
  domain: api_domain;
21
21
  }>;
22
+ /**
23
+ * Collect informational request metadata (client IP, IP chain, timestamp) for
24
+ * use in template rendering context. The values are **not** used for security
25
+ * decisions such as rate limiting — those rely on `getClientIp()` which is
26
+ * trust-proxy aware. For the IP chain to be meaningful the server must sit
27
+ * behind a trusted reverse proxy that sets the forwarded headers.
28
+ */
22
29
  export declare function buildRequestMeta(rawReq: unknown): RequestMeta;
23
30
  export declare function decodeComponent(value: string | string[] | undefined): string;
24
31
  export declare function getBodyValue(body: Record<string, unknown>, ...keys: string[]): string;
@@ -60,6 +60,13 @@ function resolveHeader(headers, key) {
60
60
  }
61
61
  return undefined;
62
62
  }
63
+ /**
64
+ * Collect informational request metadata (client IP, IP chain, timestamp) for
65
+ * use in template rendering context. The values are **not** used for security
66
+ * decisions such as rate limiting — those rely on `getClientIp()` which is
67
+ * trust-proxy aware. For the IP chain to be meaningful the server must sit
68
+ * behind a trusted reverse proxy that sets the forwarded headers.
69
+ */
63
70
  export function buildRequestMeta(rawReq) {
64
71
  const req = (rawReq ?? {});
65
72
  const headers = req.headers ?? {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/mail-magic",
3
- "version": "1.0.43",
3
+ "version": "1.0.44",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "type": "module",