@apocaliss92/nodelink-js 0.4.28 → 0.4.30

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 @@ import {
3
3
  BaichuanRtspServer,
4
4
  ReolinkBaichuanApi,
5
5
  autoDetectDeviceType
6
- } from "../chunk-NQ7D5TLR.js";
6
+ } from "../chunk-AZZKLRJV.js";
7
7
  import "../chunk-AHY4L7JI.js";
8
8
  import {
9
9
  __require
package/dist/index.cjs CHANGED
@@ -21585,6 +21585,7 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
21585
21585
  */
21586
21586
  subscribeEmailPushEvents(params) {
21587
21587
  const channel = params.channel ?? 0;
21588
+ const onEvent = params.onEvent;
21588
21589
  const matches = "match" in params ? params.match : (event) => event.cameraId === params.cameraId;
21589
21590
  const off = onEmailPushEvent((event) => {
21590
21591
  if (!matches(event)) return;
@@ -21600,6 +21601,15 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
21600
21601
  timestamp: event.receivedAtMs
21601
21602
  });
21602
21603
  }
21604
+ if (onEvent) {
21605
+ try {
21606
+ onEvent(event);
21607
+ } catch (err) {
21608
+ this.logger.warn?.(
21609
+ `[ReolinkBaichuanApi] subscribeEmailPushEvents onEvent threw: ${err instanceof Error ? err.message : err}`
21610
+ );
21611
+ }
21612
+ }
21603
21613
  });
21604
21614
  return off;
21605
21615
  }
@@ -41065,6 +41075,7 @@ function base64DecodeToBytes(b64) {
41065
41075
  }
41066
41076
 
41067
41077
  // src/emailPush/server.ts
41078
+ var import_node_util2 = require("util");
41068
41079
  var import_smtp_server = require("smtp-server");
41069
41080
  var import_mailparser = require("mailparser");
41070
41081
 
@@ -41144,6 +41155,9 @@ function createEmailPushServer(params) {
41144
41155
  return;
41145
41156
  }
41146
41157
  const receivedAtMs = Date.now();
41158
+ const imageAttachment = (parsed.attachments ?? []).find(
41159
+ (a) => a && typeof a.contentType === "string" && a.contentType.toLowerCase().startsWith("image/") && Buffer.isBuffer(a.content)
41160
+ );
41147
41161
  const event = {
41148
41162
  cameraId,
41149
41163
  recipient,
@@ -41151,11 +41165,18 @@ function createEmailPushServer(params) {
41151
41165
  receivedAtMs,
41152
41166
  subject: parsed.subject ?? "",
41153
41167
  from: typeof parsed.from === "object" && parsed.from !== null && "text" in parsed.from ? String(parsed.from.text) : "",
41154
- bodyExcerpt: (parsed.text ?? "").slice(0, 500)
41168
+ bodyExcerpt: (parsed.text ?? "").slice(0, 500),
41169
+ ...imageAttachment ? {
41170
+ attachment: {
41171
+ contentType: imageAttachment.contentType,
41172
+ data: imageAttachment.content,
41173
+ ...imageAttachment.filename ? { filename: imageAttachment.filename } : {}
41174
+ }
41175
+ } : {}
41155
41176
  };
41156
41177
  status.messagesAccepted++;
41157
41178
  log.info(
41158
- `Email push for camera=${cameraId} type=${event.inferredType} subject="${event.subject.slice(0, 80)}"`
41179
+ `Email push for camera=${cameraId} type=${event.inferredType} attachment=${event.attachment ? `${event.attachment.contentType} ${event.attachment.data.length}B` : "none"} subject="${event.subject.slice(0, 80)}"`
41159
41180
  );
41160
41181
  emitEmailPushEvent(event);
41161
41182
  }
@@ -41174,10 +41195,19 @@ function createEmailPushServer(params) {
41174
41195
  disabledCommands: config.requireAuth ? [] : ["AUTH"],
41175
41196
  allowInsecureAuth: !config.tls,
41176
41197
  size: config.maxMessageBytes,
41198
+ // smtp-server invokes its internal logger as
41199
+ // logger.info(metadata, formatString, ...args)
41200
+ // where `metadata` is an opaque session/connection object and
41201
+ // `formatString` may contain printf-style placeholders.
41202
+ // Naive `.map(String).join(" ")` would surface `[object Object]`
41203
+ // and leave `%s` unresolved (which is what the user was seeing).
41204
+ // Here we strip the metadata (keeping a compact `tnx`/`cid` tag
41205
+ // when present), then apply `util.format` so placeholders are
41206
+ // expanded by Node exactly like the smtp-server defaults do.
41177
41207
  logger: {
41178
- info: (...args) => log.debug(`[smtp] ${args.map((a) => String(a)).join(" ")}`),
41179
- debug: (...args) => log.debug(`[smtp] ${args.map((a) => String(a)).join(" ")}`),
41180
- error: (...args) => log.warn(`[smtp] ${args.map((a) => String(a)).join(" ")}`)
41208
+ info: (...args) => log.info(formatSmtpLogArgs(args)),
41209
+ debug: (...args) => log.debug(formatSmtpLogArgs(args)),
41210
+ error: (...args) => log.warn(formatSmtpLogArgs(args))
41181
41211
  },
41182
41212
  ...tlsOptions ? { secure: false, ...tlsOptions } : {},
41183
41213
  onConnect(session, callback) {
@@ -41226,24 +41256,37 @@ function createEmailPushServer(params) {
41226
41256
  );
41227
41257
  return callback(new Error("Invalid username or password"));
41228
41258
  },
41229
- onRcptTo(address, _session, callback) {
41259
+ onRcptTo(address, session, callback) {
41230
41260
  const cameraId = resolveCameraIdFromRecipient(address.address);
41231
41261
  if (!cameraId) {
41232
41262
  status.messagesRejected++;
41263
+ log.warn(
41264
+ `SMTP RCPT TO rejected ${address.address} \u2014 unknown recipient (sessionId=${session.id})`
41265
+ );
41233
41266
  return callback(
41234
41267
  new Error(
41235
41268
  `Unknown recipient ${address.address} (not registered)`
41236
41269
  )
41237
41270
  );
41238
41271
  }
41272
+ log.info(
41273
+ `SMTP RCPT TO ${address.address} \u2192 camera=${cameraId} (sessionId=${session.id})`
41274
+ );
41239
41275
  callback();
41240
41276
  },
41241
41277
  onData(stream, session, callback) {
41278
+ const startedAt = Date.now();
41279
+ log.debug(
41280
+ `SMTP DATA start (sessionId=${session.id} from=${session.envelope.mailFrom ? session.envelope.mailFrom.address : "?"})`
41281
+ );
41242
41282
  const chunks = [];
41243
41283
  stream.on("data", (chunk) => chunks.push(chunk));
41244
41284
  stream.on("end", () => {
41245
41285
  const recipients = session.envelope.rcptTo?.map((r) => r.address) ?? [];
41246
41286
  const buffer = Buffer.concat(chunks);
41287
+ log.info(
41288
+ `SMTP DATA received ${buffer.length}B in ${Date.now() - startedAt}ms for ${recipients.length} recipient(s) (sessionId=${session.id})`
41289
+ );
41247
41290
  const matched = recipients.map((r) => ({
41248
41291
  recipient: r,
41249
41292
  cameraId: resolveCameraIdFromRecipient(r)
@@ -41252,6 +41295,9 @@ function createEmailPushServer(params) {
41252
41295
  );
41253
41296
  if (matched.length === 0) {
41254
41297
  status.messagesRejected++;
41298
+ log.warn(
41299
+ `SMTP DATA dropped \u2014 no recognised recipients in [${recipients.join(", ")}] (sessionId=${session.id})`
41300
+ );
41255
41301
  return callback(new Error("No recognised recipients"));
41256
41302
  }
41257
41303
  Promise.all(
@@ -41260,13 +41306,15 @@ function createEmailPushServer(params) {
41260
41306
  )
41261
41307
  ).then(() => callback()).catch((err) => {
41262
41308
  const msg = err instanceof Error ? err.message : String(err);
41263
- log.error(`Email push pipeline error: ${msg}`);
41309
+ log.error(
41310
+ `Email push pipeline error (sessionId=${session.id}): ${msg}`
41311
+ );
41264
41312
  status.lastErrorMessage = msg;
41265
41313
  callback(new Error(msg));
41266
41314
  });
41267
41315
  });
41268
41316
  stream.on("error", (err) => {
41269
- log.warn(`SMTP stream error: ${err.message}`);
41317
+ log.warn(`SMTP stream error (sessionId=${session.id}): ${err.message}`);
41270
41318
  callback(err);
41271
41319
  });
41272
41320
  }
@@ -41314,6 +41362,25 @@ function createEmailPushServer(params) {
41314
41362
  }
41315
41363
  };
41316
41364
  }
41365
+ function formatSmtpLogArgs(args) {
41366
+ if (args.length === 0) return "[smtp]";
41367
+ const [first, ...rest] = args;
41368
+ let tag = "";
41369
+ let formatArgs = args;
41370
+ if (first && typeof first === "object" && !Array.isArray(first)) {
41371
+ const meta = first;
41372
+ const tnx = typeof meta.tnx === "string" ? meta.tnx : void 0;
41373
+ const cid = typeof meta.cid === "string" ? meta.cid : void 0;
41374
+ const sid = typeof meta.sid === "string" ? meta.sid : void 0;
41375
+ const bits = [];
41376
+ if (tnx) bits.push(tnx);
41377
+ if (cid) bits.push(`cid=${cid}`);
41378
+ if (sid) bits.push(`sid=${sid}`);
41379
+ if (bits.length > 0) tag = ` [${bits.join(" ")}]`;
41380
+ formatArgs = rest;
41381
+ }
41382
+ return `[smtp]${tag} ${(0, import_node_util2.format)(...formatArgs)}`;
41383
+ }
41317
41384
  function buildInitialStatus(config) {
41318
41385
  return {
41319
41386
  enabled: true,