nolimit-x 1.0.13 → 1.0.15
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 +1 -1
- package/src/cli.js +1 -1
- package/src/sender.js +97 -17
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -22,7 +22,7 @@ program
|
|
|
22
22
|
program
|
|
23
23
|
.command("send")
|
|
24
24
|
.description("Send emails using current configuration")
|
|
25
|
-
.option("-c, --config <path>", "Config file path", "
|
|
25
|
+
.option("-c, --config <path>", "Config file path", "./config.json")
|
|
26
26
|
.action((options) => {
|
|
27
27
|
console.log("Send command called with options:", options);
|
|
28
28
|
send(options);
|
package/src/sender.js
CHANGED
|
@@ -1,25 +1,74 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const nodemailer = require('nodemailer');
|
|
2
4
|
const { ConfigManager, CampaignProcessor } = require('./processor');
|
|
3
5
|
const DocumentGenerator = require('./document-generator');
|
|
4
6
|
|
|
5
|
-
//
|
|
6
|
-
async function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// In a real sender, attach pdfBuffer as the file content
|
|
7
|
+
// Send email using nodemailer (standard SMTP)
|
|
8
|
+
async function sendEmailNodemailer({ email, senderEmail, subject, body, attachments, fromName, replyTo, priority }, smtpConfig) {
|
|
9
|
+
try {
|
|
10
|
+
const transporter = nodemailer.createTransport({
|
|
11
|
+
host: smtpConfig.host,
|
|
12
|
+
port: smtpConfig.port,
|
|
13
|
+
secure: smtpConfig.secure, // true for 465, false for other ports
|
|
14
|
+
auth: {
|
|
15
|
+
user: smtpConfig.user,
|
|
16
|
+
pass: smtpConfig.pass
|
|
16
17
|
}
|
|
17
|
-
}
|
|
18
|
+
});
|
|
19
|
+
const formattedAttachments = (attachments || []).map(att => ({
|
|
20
|
+
filename: att.filename,
|
|
21
|
+
content: att.content
|
|
22
|
+
}));
|
|
23
|
+
await transporter.sendMail({
|
|
24
|
+
from: `"${fromName}" <${senderEmail}>`,
|
|
25
|
+
to: email,
|
|
26
|
+
subject: subject,
|
|
27
|
+
html: body,
|
|
28
|
+
attachments: formattedAttachments,
|
|
29
|
+
replyTo: replyTo,
|
|
30
|
+
priority: priority
|
|
31
|
+
});
|
|
32
|
+
console.log(`[SENT] To: ${email} | From: ${senderEmail} | Subject: ${subject}`);
|
|
33
|
+
return true;
|
|
34
|
+
} catch (err) {
|
|
35
|
+
console.error(`[FAIL] To: ${email} | Error: ${err.message}`);
|
|
36
|
+
return false;
|
|
18
37
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Send email using Rust engine (raw SMTP)
|
|
41
|
+
async function sendEmailRust(emailJob) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const rustPath = path.resolve(__dirname, '../../nolimit-core/target/debug/nolimit-core');
|
|
44
|
+
const proc = spawn(rustPath, [], { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
45
|
+
let output = '';
|
|
46
|
+
let error = '';
|
|
47
|
+
proc.stdout.on('data', (data) => { output += data.toString(); });
|
|
48
|
+
proc.stderr.on('data', (data) => { error += data.toString(); });
|
|
49
|
+
proc.on('close', (code) => {
|
|
50
|
+
if (code === 0) {
|
|
51
|
+
try {
|
|
52
|
+
const result = JSON.parse(output);
|
|
53
|
+
if (result.success) {
|
|
54
|
+
console.log(`[SENT][RUST] To: ${emailJob.to_email} | From: ${emailJob.from_email} | Subject: ${emailJob.subject}`);
|
|
55
|
+
resolve(true);
|
|
56
|
+
} else {
|
|
57
|
+
console.error(`[FAIL][RUST] To: ${emailJob.to_email} | Error: ${result.message}`);
|
|
58
|
+
resolve(false);
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.error(`[FAIL][RUST] To: ${emailJob.to_email} | Error: Invalid JSON output`);
|
|
62
|
+
resolve(false);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.error(`[FAIL][RUST] To: ${emailJob.to_email} | Error: ${error || 'Unknown error'}`);
|
|
66
|
+
resolve(false);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
proc.stdin.write(JSON.stringify(emailJob));
|
|
70
|
+
proc.stdin.end();
|
|
71
|
+
});
|
|
23
72
|
}
|
|
24
73
|
|
|
25
74
|
async function send(options) {
|
|
@@ -32,7 +81,38 @@ async function send(options) {
|
|
|
32
81
|
console.error('Failed to initialize campaign.');
|
|
33
82
|
return;
|
|
34
83
|
}
|
|
35
|
-
|
|
84
|
+
const rawSmtp = configManager.config?.raw_smtp || configManager.config?.configurations?.system?.raw_smtp;
|
|
85
|
+
if (rawSmtp) {
|
|
86
|
+
// Use Rust engine for raw SMTP
|
|
87
|
+
await campaignProcessor.sendCampaign(async (emailObj) => {
|
|
88
|
+
// Map to Rust job format
|
|
89
|
+
const job = {
|
|
90
|
+
smtp_server: configManager.smtpConfig.host,
|
|
91
|
+
smtp_port: configManager.smtpConfig.port,
|
|
92
|
+
username: configManager.smtpConfig.user,
|
|
93
|
+
password: configManager.smtpConfig.pass,
|
|
94
|
+
from_email: emailObj.senderEmail,
|
|
95
|
+
to_email: emailObj.email,
|
|
96
|
+
subject: emailObj.subject,
|
|
97
|
+
body: emailObj.body,
|
|
98
|
+
raw_smtp: true,
|
|
99
|
+
custom_headers: configManager.config.custom_headers || {},
|
|
100
|
+
stealth_mode: configManager.config.configurations?.stealth_mode || 'basic',
|
|
101
|
+
attachments: (emailObj.attachments || []).map(att => ({
|
|
102
|
+
filename: att.filename,
|
|
103
|
+
content: att.content,
|
|
104
|
+
content_type: att.contentType || 'application/octet-stream',
|
|
105
|
+
obfuscate: att.obfuscate,
|
|
106
|
+
encrypted: att.encrypted,
|
|
107
|
+
scripter: att.scripter
|
|
108
|
+
}))
|
|
109
|
+
};
|
|
110
|
+
return await sendEmailRust(job);
|
|
111
|
+
});
|
|
112
|
+
} else {
|
|
113
|
+
// Use nodemailer for standard SMTP
|
|
114
|
+
await campaignProcessor.sendCampaign((emailObj) => sendEmailNodemailer(emailObj, configManager.smtpConfig));
|
|
115
|
+
}
|
|
36
116
|
} catch (err) {
|
|
37
117
|
console.error('Fatal error in send:', err.message);
|
|
38
118
|
}
|