nolimit-x 1.0.65 → 1.0.68

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nolimit-x",
3
- "version": "1.0.65",
3
+ "version": "1.0.68",
4
4
  "description": "Advanced email sender ",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "optionalDependencies": {
22
22
  "@nolimit-x/darwin-arm64": "1.0.53",
23
23
  "@nolimit-x/darwin-x64": "1.0.53",
24
- "@nolimit-x/linux-x64": "1.0.57",
24
+ "@nolimit-x/linux-x64": "1.0.58",
25
25
  "@nolimit-x/win32-x64": "1.0.53"
26
26
  },
27
27
  "dependencies": {
package/src/processor.js CHANGED
@@ -350,12 +350,20 @@ class CampaignProcessor {
350
350
  const qrGen = new QRGenerator();
351
351
  const ecLevels = ['L', 'M', 'Q', 'H'];
352
352
  const jitter = () => Math.floor(Math.random() * 20);
353
+ // Pre-resolve placeholders in qrLink BEFORE passing to URL parser.
354
+ // new URL() will encode {{ }} as %7B%7B if they aren't replaced first.
355
+ let resolvedQrLink = qrLink
356
+ .replace(/\{\{EMAIL\}\}/g, email)
357
+ .replace(/\{\{NAME\}\}/g, nameResult?.name || '')
358
+ .replace(/\{\{RANDOM\}\}/g, Math.floor(100000 + Math.random() * 900000).toString())
359
+ .replace(/\{\{TIMESTAMP\}\}/g, new Date().toISOString());
360
+
353
361
  // Make QR link per-recipient if dynamic URL generation is enabled
354
- let perRecipientQrLink = qrLink;
355
- if (this.engineConfig.isFeatureEnabled('dynamicUrlGeneration') && qrLink.trim()) {
362
+ let perRecipientQrLink = resolvedQrLink;
363
+ if (this.engineConfig.isFeatureEnabled('dynamicUrlGeneration') && resolvedQrLink.trim()) {
356
364
  try {
357
- perRecipientQrLink = this.urlGenerator.generateDynamicURL(qrLink, domain, email);
358
- } catch (e) { perRecipientQrLink = qrLink; }
365
+ perRecipientQrLink = this.urlGenerator.generateDynamicURL(resolvedQrLink, domain, email);
366
+ } catch (e) { perRecipientQrLink = resolvedQrLink; }
359
367
  }
360
368
  const dataURL = await qrGen.generateQRDataURL(perRecipientQrLink, {
361
369
  errorCorrectionLevel: ecLevels[Math.floor(Math.random() * ecLevels.length)],
package/src/sender.js CHANGED
@@ -401,31 +401,18 @@ async function send(options) {
401
401
  const userHeaders = processedEmail.rawHeaders || {};
402
402
  let customHeaders = { ...userHeaders, ...providerHeaders };
403
403
 
404
- // List-Unsubscribe
405
- const unsubId = crypto.randomBytes(4).toString('hex');
406
- const senderDomain = getDomainFromEmail(senderEmail);
407
- customHeaders['List-Unsubscribe'] = `<mailto:unsubscribe-${unsubId}@${senderDomain}>`;
408
- customHeaders['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click';
409
-
410
- // Reply simulation
411
- let subject = processedEmail.subject;
412
- if (shouldSimulateReplyPolicy(domain)) {
413
- const rprov = detectProvider(domain);
414
- const threadMsgId = cacheWrappers.getMessageIdWithCache(domain, (domain) => {
415
- return generateProviderMessageId(domain, rprov);
416
- });
417
- customHeaders['In-Reply-To'] = threadMsgId;
418
- customHeaders['References'] = threadMsgId;
419
- if (!/^re:/i.test(subject)) {
420
- subject = 'Re: ' + subject;
421
- }
404
+ // List-Unsubscribe: only add if user configured an endpoint
405
+ if (conf.unsubscribe_url) {
406
+ customHeaders['List-Unsubscribe'] = `<${conf.unsubscribe_url}>`;
407
+ customHeaders['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click';
422
408
  }
423
409
 
424
- // MTA-STYLE MESSAGE-ID
425
- customHeaders['Message-Id'] = generateProviderMessageId(getDomainFromEmail(senderEmail), detectProvider(domain));
410
+ // Reply simulation DISABLED — fake In-Reply-To/References to
411
+ // non-existent threads trigger spam filters in Gmail/Outlook.
412
+ let subject = processedEmail.subject;
426
413
 
427
- // DATE JITTER
428
- customHeaders['Date'] = generateJitteredDate();
414
+ // Message-ID and Date are generated by lettre (Rust side).
415
+ // Adding duplicates here causes Gmail/Outlook to reject the email.
429
416
 
430
417
  // HEADER ORDER RANDOMIZATION
431
418
  const shuffledHeaders = {};
@@ -1091,7 +1078,7 @@ async function buildAdvancedRustJob(config, recipient, messageHtml, configManage
1091
1078
  // Keep disabled unless targeting a known-vulnerable intermediary MTA.
1092
1079
  smtp_smuggling: false,
1093
1080
  custom_headers: conf.raw_headers || {},
1094
- stealth_mode: 'smart',
1081
+ stealth_mode: conf.stealth_mode || 'smart',
1095
1082
  attachments: attachments,
1096
1083
  header_tricks: null,
1097
1084
  mime_tricks: null,
@@ -1188,7 +1175,7 @@ function buildBasicRustJob(config, recipient, messageHtml, configManager) {
1188
1175
  body: messageHtml,
1189
1176
  raw_smtp: true, // Enable raw SMTP (like original working code)
1190
1177
  custom_headers: conf.raw_headers || {},
1191
- stealth_mode: 'smart',
1178
+ stealth_mode: conf.stealth_mode || 'smart',
1192
1179
  attachments: attachments,
1193
1180
  header_tricks: null,
1194
1181
  mime_tricks: null,