@5minds/node-red-contrib-processcube-tools 1.0.1-feature-3af406-mfdy163c → 1.0.1-feature-2a3502-mfe1ptiw
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/email-receiver/email-receiver.html +187 -0
- package/email-receiver/email-receiver.js +236 -0
- package/package.json +26 -5
- package/test/helpers/email-receiver.mocks.js +379 -0
- package/test/integration/email-receiver.integration.test.js +479 -0
- package/test/unit/email-receiver.unit.test.js +279 -0
- package/email-sender/email-sender.html +0 -138
- package/email-sender/email-sender.js +0 -84
- /package/{processcube-html-to-text/processcube-html-to-text.html → processcube-html-to-text.html} +0 -0
- /package/{processcube-html-to-text/processcube-html-to-text.js → processcube-html-to-text.js} +0 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
const should = require('should');
|
|
2
|
+
const {
|
|
3
|
+
createMockImap,
|
|
4
|
+
createMockMailparser,
|
|
5
|
+
createMockNodeRED,
|
|
6
|
+
setupModuleMocks,
|
|
7
|
+
testConfigs,
|
|
8
|
+
testUtils
|
|
9
|
+
} = require('../helpers/email-receiver.mocks.js');
|
|
10
|
+
|
|
11
|
+
describe('Email Receiver Node - Unit Tests with Helpers', function() {
|
|
12
|
+
this.timeout(10000);
|
|
13
|
+
|
|
14
|
+
let emailReceiverNode;
|
|
15
|
+
let cleanupMocks;
|
|
16
|
+
|
|
17
|
+
before(function() {
|
|
18
|
+
// Set up module mocks using helper
|
|
19
|
+
cleanupMocks = setupModuleMocks();
|
|
20
|
+
|
|
21
|
+
// Load the node with mocked dependencies
|
|
22
|
+
emailReceiverNode = require('../../email-receiver/email-receiver.js');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
after(function() {
|
|
26
|
+
// Clean up mocks
|
|
27
|
+
if (cleanupMocks) {
|
|
28
|
+
cleanupMocks();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('Module Export', function() {
|
|
33
|
+
it('should export a function', function() {
|
|
34
|
+
emailReceiverNode.should.be.type('function');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('Node Registration', function() {
|
|
39
|
+
it('should register node type without errors', function() {
|
|
40
|
+
// ARRANGE: Create mock Node-RED with tracking
|
|
41
|
+
const mockRED = createMockNodeRED();
|
|
42
|
+
|
|
43
|
+
// ACT: Register the node
|
|
44
|
+
emailReceiverNode(mockRED);
|
|
45
|
+
|
|
46
|
+
// ASSERT: Verify registration
|
|
47
|
+
mockRED.nodes.lastRegisteredType.should.equal('email-receiver');
|
|
48
|
+
mockRED.nodes.lastRegisteredConstructor.should.be.type('function');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('Node Instantiation', function() {
|
|
53
|
+
it('should handle node instantiation with valid config', function() {
|
|
54
|
+
// ARRANGE: Track node creation
|
|
55
|
+
let createdNode = null;
|
|
56
|
+
const mockRED = createMockNodeRED({
|
|
57
|
+
onHandler: function(event, callback) {
|
|
58
|
+
createdNode = this;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ACT: Register and create node instance
|
|
63
|
+
emailReceiverNode(mockRED);
|
|
64
|
+
new mockRED.nodes.lastRegisteredConstructor(testConfigs.valid);
|
|
65
|
+
|
|
66
|
+
// ASSERT: Verify node was created with correct properties
|
|
67
|
+
should.exist(createdNode);
|
|
68
|
+
createdNode.should.have.property('name', testConfigs.valid.name);
|
|
69
|
+
createdNode.should.have.property('id', testConfigs.valid.id);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should handle minimal config', function() {
|
|
73
|
+
// ARRANGE: Use minimal test config
|
|
74
|
+
let createdNode = null;
|
|
75
|
+
const mockRED = createMockNodeRED({
|
|
76
|
+
onHandler: function(event, callback) {
|
|
77
|
+
createdNode = this;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ACT: Register and create node with minimal config
|
|
82
|
+
emailReceiverNode(mockRED);
|
|
83
|
+
new mockRED.nodes.lastRegisteredConstructor(testConfigs.minimal);
|
|
84
|
+
|
|
85
|
+
// ASSERT: Verify node creation
|
|
86
|
+
should.exist(createdNode);
|
|
87
|
+
createdNode.should.have.property('id', testConfigs.minimal.id);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('Folder Configuration', function() {
|
|
92
|
+
it('should handle array of folders', async function() {
|
|
93
|
+
// ARRANGE: Set up message tracking
|
|
94
|
+
let sentMessage = null;
|
|
95
|
+
const mockRED = createMockNodeRED({
|
|
96
|
+
sendHandler: function(msg) {
|
|
97
|
+
sentMessage = msg;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// ACT: Register node and create instance with array folders
|
|
102
|
+
emailReceiverNode(mockRED);
|
|
103
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
104
|
+
const nodeInstance = new nodeConstructor(testConfigs.arrayFolders);
|
|
105
|
+
|
|
106
|
+
// Wait for processing
|
|
107
|
+
await testUtils.wait(50);
|
|
108
|
+
|
|
109
|
+
// ASSERT: Should handle array folders without error
|
|
110
|
+
should.exist(nodeInstance);
|
|
111
|
+
nodeInstance.should.have.property('name', testConfigs.arrayFolders.name);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Error Handling', function() {
|
|
116
|
+
it('should call node.error for invalid folder type', function(done) {
|
|
117
|
+
// ARRANGE: Set up error tracking
|
|
118
|
+
const mockRED = createMockNodeRED({
|
|
119
|
+
errorHandler: function(err) {
|
|
120
|
+
// ASSERT: Should receive appropriate error message
|
|
121
|
+
err.should.containEql("The 'folders' property must be an array of strings.");
|
|
122
|
+
done();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// ACT: Register node and create instance with invalid config
|
|
127
|
+
emailReceiverNode(mockRED);
|
|
128
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
129
|
+
new nodeConstructor(testConfigs.invalidConfig);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should call node.error for missing config', function(done) {
|
|
133
|
+
// ARRANGE: Set up error and status tracking
|
|
134
|
+
let statusCalled = false;
|
|
135
|
+
const mockRED = createMockNodeRED({
|
|
136
|
+
statusHandler: function(status) {
|
|
137
|
+
statusCalled = true;
|
|
138
|
+
if (status.fill) {
|
|
139
|
+
status.fill.should.equal('red');
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
errorHandler: function(err) {
|
|
143
|
+
// ASSERT: Should receive config error
|
|
144
|
+
err.should.containEql('Missing required IMAP config');
|
|
145
|
+
statusCalled.should.be.true();
|
|
146
|
+
done();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// ACT: Register node and create instance with invalid config
|
|
151
|
+
emailReceiverNode(mockRED);
|
|
152
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
153
|
+
new nodeConstructor(testConfigs.invalidConfig);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('Message Processing', function() {
|
|
158
|
+
it('should process email message correctly', async function() {
|
|
159
|
+
// ARRANGE: Set up message capture
|
|
160
|
+
let processedMessage = null;
|
|
161
|
+
const mockRED = createMockNodeRED({
|
|
162
|
+
sendHandler: function(msg) {
|
|
163
|
+
processedMessage = msg;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// ACT: Create node and simulate email processing
|
|
168
|
+
emailReceiverNode(mockRED);
|
|
169
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
170
|
+
const nodeInstance = new nodeConstructor(testConfigs.valid);
|
|
171
|
+
|
|
172
|
+
// Simulate input trigger (this would depend on your node's implementation)
|
|
173
|
+
// The actual trigger mechanism would need to match your node's design
|
|
174
|
+
|
|
175
|
+
await testUtils.wait(100);
|
|
176
|
+
|
|
177
|
+
// ASSERT: Message processing behavior would be verified here
|
|
178
|
+
// The specific assertions depend on your node's output format
|
|
179
|
+
should.exist(nodeInstance);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should handle multiple messages', async function() {
|
|
183
|
+
// ARRANGE: Set up message collection
|
|
184
|
+
const messages = [];
|
|
185
|
+
const mockRED = createMockNodeRED({
|
|
186
|
+
sendHandler: function(msg) {
|
|
187
|
+
messages.push(msg);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// ACT: Create node and simulate multiple emails
|
|
192
|
+
emailReceiverNode(mockRED);
|
|
193
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
194
|
+
const nodeInstance = new nodeConstructor(testConfigs.valid);
|
|
195
|
+
|
|
196
|
+
await testUtils.wait(150);
|
|
197
|
+
|
|
198
|
+
// ASSERT: Should handle multiple messages appropriately
|
|
199
|
+
should.exist(nodeInstance);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('IMAP Connection', function() {
|
|
204
|
+
it('should handle connection success', function(done) {
|
|
205
|
+
// ARRANGE: Set up connection tracking
|
|
206
|
+
const mockRED = createMockNodeRED({
|
|
207
|
+
statusHandler: function(status) {
|
|
208
|
+
if (status.fill === 'green') {
|
|
209
|
+
// ASSERT: Should show connected status
|
|
210
|
+
status.text.should.containEql('connected');
|
|
211
|
+
done();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// ACT: Create node which should attempt connection
|
|
217
|
+
emailReceiverNode(mockRED);
|
|
218
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
219
|
+
new nodeConstructor(testConfigs.valid);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('should handle connection errors', function(done) {
|
|
223
|
+
// ARRANGE: Set up error tracking
|
|
224
|
+
const mockRED = createMockNodeRED({
|
|
225
|
+
errorHandler: function(err) {
|
|
226
|
+
// ASSERT: Should handle connection errors gracefully
|
|
227
|
+
should.exist(err);
|
|
228
|
+
done();
|
|
229
|
+
},
|
|
230
|
+
statusHandler: function(status) {
|
|
231
|
+
if (status.fill === 'red') {
|
|
232
|
+
// Connection failed status
|
|
233
|
+
status.text.should.containEql('error');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// ACT: Create node with config that should fail
|
|
239
|
+
emailReceiverNode(mockRED);
|
|
240
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
241
|
+
|
|
242
|
+
// Use invalid config to trigger connection error
|
|
243
|
+
const invalidConfig = { ...testConfigs.valid, host: 'invalid.host.com' };
|
|
244
|
+
new nodeConstructor(invalidConfig);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
describe('Message Verification Utilities', function() {
|
|
249
|
+
it('should verify message properties using testUtils', function() {
|
|
250
|
+
// ARRANGE: Create a test message
|
|
251
|
+
const testMessage = {
|
|
252
|
+
payload: 'test content',
|
|
253
|
+
topic: 'email/received',
|
|
254
|
+
from: 'test@example.com'
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// ACT & ASSERT: Use helper to verify message properties
|
|
258
|
+
testUtils.verifyMessage(testMessage, {
|
|
259
|
+
payload: 'test content',
|
|
260
|
+
topic: 'email/received'
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Should not throw any errors if verification passes
|
|
264
|
+
testMessage.should.have.property('from', 'test@example.com');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should use wait utility for async operations', async function() {
|
|
268
|
+
// ARRANGE: Record start time
|
|
269
|
+
const startTime = Date.now();
|
|
270
|
+
|
|
271
|
+
// ACT: Use the wait utility
|
|
272
|
+
await testUtils.wait(100);
|
|
273
|
+
|
|
274
|
+
// ASSERT: Should have waited approximately the right amount of time
|
|
275
|
+
const elapsed = Date.now() - startTime;
|
|
276
|
+
elapsed.should.be.approximately(100, 50); // Allow 50ms tolerance
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
<script type="text/javascript">
|
|
2
|
-
RED.nodes.registerType('email-sender',{
|
|
3
|
-
category: 'ProcessCube Tools',
|
|
4
|
-
color: '#02AFD6',
|
|
5
|
-
defaults: {
|
|
6
|
-
name: { value: "" },
|
|
7
|
-
// Definition der Felder mit dem Typ 'typedInput'
|
|
8
|
-
fromName: { value: "Stoelting Ticket-System", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
9
|
-
fromAddress: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
10
|
-
to: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
11
|
-
cc: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
12
|
-
bcc: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
13
|
-
subject: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
14
|
-
attachments: { value: "", type: "typedInput", types: ["msg", "flow", "global"] },
|
|
15
|
-
htmlContent: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "json"] },
|
|
16
|
-
|
|
17
|
-
// SMTP-Felder
|
|
18
|
-
smtpHost: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
19
|
-
smtpPort: { value: "", type: "typedInput", types: ["num", "str", "msg", "flow", "global", "env"] },
|
|
20
|
-
smtpUser: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
21
|
-
smtpPassword: { value: "", type: "typedInput", types: ["str", "msg", "flow", "global", "env"] },
|
|
22
|
-
smtpSecure: { value: true, type: "typedInput", types: ["bool", "msg", "flow", "global"] },
|
|
23
|
-
smtpRejectUnauthorized: { value: true, type: "typedInput", types: ["bool", "msg", "flow", "global"] }
|
|
24
|
-
},
|
|
25
|
-
inputs:1,
|
|
26
|
-
outputs:1,
|
|
27
|
-
icon: "font-awesome/fa-paper-plane",
|
|
28
|
-
label: function() {
|
|
29
|
-
return this.name || "Email Sender";
|
|
30
|
-
},
|
|
31
|
-
labelStyle: function() {
|
|
32
|
-
return this.name?"node_label_italic":"";
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
</script>
|
|
36
|
-
<script type="text/html" data-template-name="custom-email-sender">
|
|
37
|
-
<div class="form-row">
|
|
38
|
-
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
39
|
-
<input type="text" id="node-input-name" placeholder="Name">
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
<h3>E-Mail Konfiguration</h3>
|
|
43
|
-
<div class="form-row">
|
|
44
|
-
<label for="node-input-fromName"><i class="fa fa-user"></i> Absendername</label>
|
|
45
|
-
<input type="text" id="node-input-fromName">
|
|
46
|
-
</div>
|
|
47
|
-
<div class="form-row">
|
|
48
|
-
<label for="node-input-fromAddress"><i class="fa fa-envelope"></i> Absenderadresse</label>
|
|
49
|
-
<input type="text" id="node-input-fromAddress">
|
|
50
|
-
</div>
|
|
51
|
-
<div class="form-row">
|
|
52
|
-
<label for="node-input-to"><i class="fa fa-user-plus"></i> Empfänger (To)</label>
|
|
53
|
-
<input type="text" id="node-input-to">
|
|
54
|
-
</div>
|
|
55
|
-
<div class="form-row">
|
|
56
|
-
<label for="node-input-cc"><i class="fa fa-user"></i> CC</label>
|
|
57
|
-
<input type="text" id="node-input-cc">
|
|
58
|
-
</div>
|
|
59
|
-
<div class="form-row">
|
|
60
|
-
<label for="node-input-bcc"><i class="fa fa-user-secret"></i> BCC</label>
|
|
61
|
-
<input type="text" id="node-input-bcc">
|
|
62
|
-
</div>
|
|
63
|
-
<div class="form-row">
|
|
64
|
-
<label for="node-input-subject"><i class="fa fa-info-circle"></i> Betreff</label>
|
|
65
|
-
<input type="text" id="node-input-subject">
|
|
66
|
-
</div>
|
|
67
|
-
<div class="form-row">
|
|
68
|
-
<label for="node-input-attachments"><i class="fa fa-paperclip"></i> Anhänge</label>
|
|
69
|
-
<input type="text" id="node-input-attachments">
|
|
70
|
-
</div>
|
|
71
|
-
<div class="form-row">
|
|
72
|
-
<label for="node-input-htmlContent"><i class="fa fa-file-code-o"></i> HTML Inhalt</label>
|
|
73
|
-
<input type="text" id="node-input-htmlContent">
|
|
74
|
-
</div>
|
|
75
|
-
|
|
76
|
-
<h3>SMTP Konfiguration</h3>
|
|
77
|
-
<div class="form-row">
|
|
78
|
-
<label for="node-input-smtpHost"><i class="fa fa-server"></i> Host</label>
|
|
79
|
-
<input type="text" id="node-input-smtpHost">
|
|
80
|
-
</div>
|
|
81
|
-
<div class="form-row">
|
|
82
|
-
<label for="node-input-smtpPort"><i class="fa fa-plug"></i> Port</label>
|
|
83
|
-
<input type="text" id="node-input-smtpPort">
|
|
84
|
-
</div>
|
|
85
|
-
<div class="form-row">
|
|
86
|
-
<label for="node-input-smtpUser"><i class="fa fa-user"></i> Benutzer</label>
|
|
87
|
-
<input type="text" id="node-input-smtpUser">
|
|
88
|
-
</div>
|
|
89
|
-
<div class="form-row">
|
|
90
|
-
<label for="node-input-smtpPassword"><i class="fa fa-lock"></i> Passwort</label>
|
|
91
|
-
<input type="password" id="node-input-smtpPassword">
|
|
92
|
-
</div>
|
|
93
|
-
<div class="form-row">
|
|
94
|
-
<label for="node-input-smtpSecure"><i class="fa fa-shield"></i> SSL/TLS (Secure)</label>
|
|
95
|
-
<input type="checkbox" id="node-input-smtpSecure">
|
|
96
|
-
</div>
|
|
97
|
-
<div class="form-row">
|
|
98
|
-
<label for="node-input-smtpRejectUnauthorized"><i class="fa fa-ban"></i> Zertifikate ablehnen</label>
|
|
99
|
-
<input type="checkbox" id="node-input-smtpRejectUnauthorized">
|
|
100
|
-
</div>
|
|
101
|
-
</script>
|
|
102
|
-
|
|
103
|
-
<script type="text/html" data-help-name="custom-email-sender">
|
|
104
|
-
<p>Eine benutzerdefinierte Node, um E-Mails über einen SMTP-Server zu versenden. Die Konfiguration kann über die Node-Eigenschaften, die eingehende Nachricht, Flow- oder Global-Kontexte oder Umgebungsvariablen erfolgen.</p>
|
|
105
|
-
<h3>Konfiguration der Felder</h3>
|
|
106
|
-
<p>Jedes Feld kann so konfiguriert werden, dass es einen festen Wert (string, number, boolean) oder einen Wert aus <code>msg</code>, <code>flow</code>, <code>global</code> oder <code>env</code> bezieht. Verwenden Sie das Dropdown-Menü neben dem Eingabefeld, um den Typ auszuwählen.</p>
|
|
107
|
-
</script>
|
|
108
|
-
|
|
109
|
-
<script type="text/javascript">
|
|
110
|
-
(function() {
|
|
111
|
-
// Initialisierung des typedInput-Widgets für die einzelnen Felder
|
|
112
|
-
function initializeTypedInput(id, types) {
|
|
113
|
-
$("#node-input-" + id).typedInput({
|
|
114
|
-
default: types[0],
|
|
115
|
-
types: types
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Initialisierung aller Felder
|
|
120
|
-
RED.events.on('nodes:load', function() {
|
|
121
|
-
initializeTypedInput('fromName', ["str", "msg", "flow", "global", "env"]);
|
|
122
|
-
initializeTypedInput('fromAddress', ["str", "msg", "flow", "global", "env"]);
|
|
123
|
-
initializeTypedInput('to', ["str", "msg", "flow", "global", "env"]);
|
|
124
|
-
initializeTypedInput('cc', ["str", "msg", "flow", "global", "env"]);
|
|
125
|
-
initializeTypedInput('bcc', ["str", "msg", "global", "env"]);
|
|
126
|
-
initializeTypedInput('subject', ["str", "msg", "flow", "global", "env"]);
|
|
127
|
-
initializeTypedInput('attachments', ["msg", "flow", "global"]);
|
|
128
|
-
initializeTypedInput('htmlContent', ["str", "msg", "flow", "global"]);
|
|
129
|
-
|
|
130
|
-
initializeTypedInput('smtpHost', ["str", "msg", "flow", "global", "env"]);
|
|
131
|
-
initializeTypedInput('smtpPort', ["num", "str", "msg", "flow", "global", "env"]);
|
|
132
|
-
initializeTypedInput('smtpUser', ["str", "msg", "flow", "global", "env"]);
|
|
133
|
-
initializeTypedInput('smtpPassword', ["str", "msg", "flow", "global", "env"]);
|
|
134
|
-
initializeTypedInput('smtpSecure', ["bool", "msg", "flow", "global"]);
|
|
135
|
-
initializeTypedInput('smtpRejectUnauthorized', ["bool", "msg", "flow", "global"]);
|
|
136
|
-
});
|
|
137
|
-
})();
|
|
138
|
-
</script>
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
module.exports = function(RED) {
|
|
2
|
-
"use strict";
|
|
3
|
-
const nodemailer = require("nodemailer");
|
|
4
|
-
|
|
5
|
-
function EmailSenderNode(config) {
|
|
6
|
-
RED.nodes.createNode(this, config);
|
|
7
|
-
var node = this;
|
|
8
|
-
|
|
9
|
-
node.on('input', function(msg, send, done) {
|
|
10
|
-
|
|
11
|
-
// Konfiguration und Daten aus der Nachricht extrahieren
|
|
12
|
-
const emailConfig = RED.util.evaluateNodeProperty(config.email, config.emailType, node, msg) || {};
|
|
13
|
-
const smtpConfig = RED.util.evaluateNodeProperty(config.smtp, config.smtpType, node, msg) || {};
|
|
14
|
-
|
|
15
|
-
// Fallback für send und done, falls ältere Node-RED Version
|
|
16
|
-
send = send || function() { node.send.apply(node, arguments); }
|
|
17
|
-
done = done || function(err) { if (err) node.error(err, msg); }
|
|
18
|
-
|
|
19
|
-
// Logik vom Code-Snippet
|
|
20
|
-
const transporter = nodemailer.createTransport({
|
|
21
|
-
host: smtpConfig.host,
|
|
22
|
-
port: smtpConfig.port,
|
|
23
|
-
auth: {
|
|
24
|
-
user: smtpConfig.auth?.user,
|
|
25
|
-
pass: smtpConfig.auth?.pass
|
|
26
|
-
},
|
|
27
|
-
secure: smtpConfig.secure !== undefined ? smtpConfig.secure : true,
|
|
28
|
-
proxy: smtpConfig.proxy || undefined,
|
|
29
|
-
tls: {
|
|
30
|
-
rejectUnauthorized: smtpConfig.tls?.rejectUnauthorized !== undefined
|
|
31
|
-
? smtpConfig.tls.rejectUnauthorized
|
|
32
|
-
: true
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const mail = {
|
|
37
|
-
from: emailConfig.from,
|
|
38
|
-
to: emailConfig.to,
|
|
39
|
-
cc: emailConfig.cc || "",
|
|
40
|
-
bcc: emailConfig.bcc || "",
|
|
41
|
-
subject: emailConfig.subject || msg.topic || "Message from Node-RED",
|
|
42
|
-
attachments: emailConfig.attachments,
|
|
43
|
-
text: emailConfig.text,
|
|
44
|
-
html: emailConfig.html,
|
|
45
|
-
amp: emailConfig.amp,
|
|
46
|
-
priority: emailConfig.priority || "normal"
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// E-Mail senden und den Status überprüfen
|
|
50
|
-
transporter.sendMail(mail, (error, info) => {
|
|
51
|
-
if (error) {
|
|
52
|
-
node.error(error, msg);
|
|
53
|
-
done(error); // Fehler an Node-RED weiterleiten
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
node.log('E-Mail gesendet: ' + info.response);
|
|
58
|
-
msg.payload = info;
|
|
59
|
-
|
|
60
|
-
// Statusprüfung basierend auf dem Code-Auszug
|
|
61
|
-
if (msg.payload.accepted && msg.payload.accepted.length > 0) {
|
|
62
|
-
msg.payload = { result: msg.input };
|
|
63
|
-
send(msg); // Nachricht an den nächsten Knoten senden
|
|
64
|
-
} else if (msg.payload.rejected && msg.payload.rejected.length > 0) {
|
|
65
|
-
msg.error = { result: msg.payload.rejected };
|
|
66
|
-
done('E-Mail abgelehnt: ' + msg.payload.rejected.join(', '));
|
|
67
|
-
node.status({fill:"red", shape:"dot", text:"rejected"});
|
|
68
|
-
return;
|
|
69
|
-
} else if (msg.payload.pending && msg.payload.pending.length > 0) {
|
|
70
|
-
msg.error = { result: msg.payload.pending };
|
|
71
|
-
done('E-Mail ausstehend: ' + msg.payload.pending.join(', '));
|
|
72
|
-
node.status({fill:"yellow", shape:"dot", text:"pending"});
|
|
73
|
-
return;
|
|
74
|
-
} else {
|
|
75
|
-
done('Unbekannter Fehler beim Senden der E-Mail.');
|
|
76
|
-
node.status({fill:"red", shape:"dot", text:"error"});
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
RED.nodes.registerType("email-sender", EmailSenderNode);
|
|
84
|
-
};
|
/package/{processcube-html-to-text/processcube-html-to-text.html → processcube-html-to-text.html}
RENAMED
|
File without changes
|
/package/{processcube-html-to-text/processcube-html-to-text.js → processcube-html-to-text.js}
RENAMED
|
File without changes
|