I have this error from smtp gmail when i try to send my message.
I use TLS socket on nodejs to connect to smtp, then i have a class which creates me commands which i send.
secure.on('secureConnect', () => {
//secure.setEncoding('base64');
let caretka = `\r\n`;
console.log(secure.authorized);
console.log('IN SECURE');
//secure.write('EHLO hailmail\r\n');
**com**.forEach(command => {
secure.write(command);
});
secure.write('quit\r\n');
secure.on('data', chunk => {
const response = chunk.toString();
console.log(`Response in secure: ${response}`);
})
secure.on('keylog', (line) => {
console.log(`Line in secure: ${line}`);
})
secure.on('close', () => {
console.log('closed');
})
});
My class:
class creatingCommandsForSMTP {
constructor(msg) {
this.helo = `EHLO hailmail\r\n`;
this.mailFrom = `MAIL FROM: <${msg.from}>\r\n`;
this.recipient = `RCPT TO: <${msg.recipient}>\r\n`;
this.commandData = `DATA`;
//this.dataFrom = `FROM: <${msg.from}>\r\n`;
//this.dataTo = `TO: <${msg.recipient}>\r\n`;
//this.dataSubject = `SUBJECT: ${msg.subject}\r\n`;
//this.dataText = `${msg.text}\r\n`;
//this.dot = `.\r\n`;
//this.commandQuit = 'QUIT\r\n';
}
getValue(command) {
return this[command]
}
};
So the problem is when i send Mail from and Rcpt to i always get OK code from server,
but after command 'DATA\r\n' i have this response:
'451 4.5.0 SMTP protocol violation, see RFC 2821 k12-20020adff5cc000000b0021e4c3b2966si4569901wrp.1037 - gsmtp '
I tried to search RFC 2821, but there is no information about rules inside the DATA command
EDIT: The last tries gave me a code 'Go Ahead' which means that server is ready to recieve data, then i send 'FROM: ' and get the same code '451 SMTP protocol violation'
Many mail servers deliberately reject anything that does not follow the RFCs to the letter, in the aim of rejecting bots and spammers. The code snippet is obviously incomplete, but I suspect that the error you are seeing is caused because the commands you are sending do not wait for a response before sending the next. This is classic bot behaviour.
If you change your main command loop to something like the following, you should avoid this problem (psuedocode):
loop_through_commands {
send command
receive response
if error blah
}
Related
I have a working slack app running as an Azure Function using NodeJS. It is posting payloads fine to my channel. I would also like the Function to post a message to the channel via client.chat.postMessage. As far as I can see I have set everything up correctly but whenever I attempt to post the message I get an error:
TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["User-Agent"]
The code to post the message is:
const { WebClient, LogLevel } = require("#slack/web-api");
const client = new WebClient(process.env['BOT_USER_OAUTH_TOKEN'], {
// LogLevel can be imported and used to make debugging simpler
logLevel: LogLevel.DEBUG
});
const channelId = "C0319MTLHB8";
try {
// Call the chat.postMessage method using the WebClient
const result = await client.chat.postMessage({
channel: channelId,
text: "Hello world"
});
console.log(result);
} catch (error) {
context.res = {
// status: 200, /* Defaults to 200 */
body: "error: " + error
};
}
and this piece of code sits within module.exports.
I guess something doesn't like the contents of BOT_USER_OAUTH_TOKEN but this is a direct copy of the xoxb bot user oauth token. And is of the form:
xoxb-999999999999999-9999999999999-aBunchOfUpperAndLowerCaseCharacters
Any suggestions as to what I am doing wrong?
Thank you I'm Joe Too for your valuable discussed resolution. Posting as an answer to help other community members:
You missed an open bracket in const result = await client.chat.postMessage(
Glad #JimBurke, that you have solved yourself by correcting the syntax/transcription.
Isn't it Node.js 16 LTS?
I had a similar problem, But I made Node.js 14 LTS and it worked
Goal: Use Server-Sent Events in my Angular App with Express Backend
Problem: Server-Sent Events do not reach the client
Backend Code
router.get('/options/:a/:b/:c', async (req, res) => {
console.log('options endpoint called..', req.params.a,req.params.b,req.params.c);
// ---- SERVER SENT EVENTS ---- //
// Setting Headers
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Connection', 'keep-alive');
res.flushHeaders(); // flush the headers to establish SSE with client
for(let i=0;i<10;i++){
console.log("should now send this response...banane")
res.write('banane!')
}
});
Client Side Code
export class NetworkingService {
BASE_URL;
OPTIONS = 'options'
searchResultSubject: Subject<SearchResults>;
constructor(private http: HttpClient, private ls: LoggingService, private _zone: NgZone) { // shortened }
getOptions(a: string, b: string, c: string) {
this.ls.log("get options endpoint about to be triggered")
this.getServerSentEvent(this.BASE_URL + this.OPTIONS + "/" + a + "/" + b + "/" + c).subscribe(resp => {
this.ls.log("got from server: ", resp)
});
return this.searchResultSubject;
}
getServerSentEvent(url: string): Observable<any> {
console.log('creating an eventsource...')
return new Observable(observer => {
const eventSource = this.getEventSource(url);
eventSource.onopen = event => {
console.log('opening connection', eventSource.readyState)
};
eventSource.onmessage = event => {
console.log('event from server..')
this._zone.run(() => {
observer.next(event);
});
};
eventSource.onerror = error => {
console.log('error from server..')
this._zone.run(() => {
observer.error(error);
});
};
});
}
private getEventSource(url: string): EventSource {
return new EventSource(url);
}
}
Server Side log output (as expected)
options endpoint called.. A B C
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
should now send this response...banane
Client Side log output (NOT as expected)
get options endpoint about to be triggered
creating an eventsource...
opening connection 1
...and then nothing.
What have I tried?
I fail to see how I differ from these: so-question, tutorial, tutorial
In the Networks Tab in Dev Tools I see a Status 200, type eventsource line entry with the correct headers. But only one!
I think I am making a really obvious mistake, since it is ALMOST working and seems to be straightforward from the examples.
My Angular is 10.1.6 and express is 4.17.1
I am new to interacting directly with ngZone is there a potential error?
The problem persists even when I comment out the compression library or use res.flush(), as suggested here.
I was having the same problem, I was not getting the response on the client.
After a number of changes it seems to be working.
First I set the headers:
response.setHeader('Cache-Control', 'no-cache');
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Connection', 'keep alive');
response.setHeader('X-Accel-Buffering', 'no');
response.flushHeaders(); // flush headers to establish SSE with client
If you are using the compress middleware, it is necessary that when sending the data to the client, you put
response.flush();
example
response.write(`event: ${event}\ndata: ${data}\n\n`);
response.flush();
It seems that the client receives messages from the generated event,
that is, if you send the client the following response
response.write(`event: some_event\ndata: some_data\n\n`);
the client should have a code similar to this:
const eventSource = new EventSource(url);
eventSource.addEventListener('some_event', listener => {
console.log(listener);
...
}, false);
I hope to be helpful
What worked for me was similar to what daacdev said, but not entirely.
Serverside I used:
res.setHeader('Cache-Control', 'no-cache, no-transform'); // Notice the no-transform!
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Connection', 'keep-alive');
res.flushHeaders(); // Flush the headers to establish SSE with client
// Do some stuff...
// Like sending an event with data
res.write('event: fooEvent\n'); // Note the 1 newline after the event name
res.write(`data: ${JSON.stringify({ foo: 'bar' })}\n\n`); // Note the 2 newlines after the data
// And when you're done, end it
res.end();
And clientside, we have eventListeners for event types:
const eventSource = new EventSource('/api/foo');
eventSource.addEventListener('fooEvent', event => {
console.log('Got fooEvent: ', event.data); // event.data has your data
eventSource.close(); // Close the eventSource if the client is done
});
You can leave out the event type altogether and only send 'data' in your res.write(). In which case your client listens for event type-less messages like this:
eventSource.onmessage = event => {
console.log('Got some data: ', event.data); // event.data has your data
eventSource.close(); // Close the eventSource if the client is done
Noteworthy:
The Cache-Control header needed 'no-transform' aside from 'no-cache'. Before I did that, the client would only get the messages after the server ended the whole thing
I did not need to flush after every write
You can't only send an event type. It always needs data to follow it. So if you simply want to send a message, do something like:
res.write('event: doubleProcesses\n');
res.write('data: doubleProcesses\n\n');
You must adhere to the defined structure: the optional 'event' (followed by a colon, a name, and 1 newline) and the required 'data' (followed by a colon, your data as a string, and 2 newlines). You cannot simply put anything in your res.write.
That last point is for sure what you were missing.
Docs here:
https://developer.mozilla.org/en-US/docs/Web/API/EventSource
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
For anyone who landed here after searching similar issues, what our problem turns out to be is that our node.js app is being hosted on Azure windows, and it is using IIS under the hood. The handler iisnode has a default setting of buffering response, which is the reason why response from our server was never received at the client side. All we had to do was to edit the web.config files according to this Microsoft guide
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-nodejs-best-practices-and-troubleshoot-guide
pay attention to the
flushResponse section
I want to use FIXAPI for one of my application.
I am trying connect "LOGON" api. But i am not getting any error or any Response.
While i was tried with "b2bits simulator", it works.
But Using any library, it does not give me any error or reponse.
I am using "fixparser" library (NodeJS npm library) to call the api.
Any help would be appreciated.
Thanks.
calling fixparser with different versions. and also tried different library (node-quickfix)
var fixparser = require("fixparser");
const fixParser = new FIXParser();
fixParser.connect({
host: HOST,
port: PORT,
protocol: 'tcp',
sender: SENDER,
target: TARGET,
fixVersion: VERSION
});
// Sendlogon function
function sendLogon() {
const logon = fixParser.createMessage(
new Field(Fields.MsgType, Messages.Logon),
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
new Field(Fields.SenderCompID, SENDER),
new Field(Fields.SendingTime, fixParser.getTimestamp()),
new Field(Fields.TargetCompID, TARGET),
new Field(Fields.ResetSeqNumFlag, 'Y'),
new Field(Fields.EncryptMethod, EncryptMethod.None),
new Field(Fields.HeartBtInt, 10)
);
const messages = fixParser.parse(logon.encode());
fixParser.send(logon);
}
// Open connection
fixParser.on('open', async (s, se) => {
console.log("Started....");
sendLogon();
});
// Retrive response
fixParser.on('message', (message) => {
// Received FIX message
// console.log("message",message);
console.log('received message', message.description, message.string);
});
// Close connection
fixParser.on('close', () => {
console.log("closed");
});
I want to get response and error(if any)
Looks like you are trying to connect to Stock Exchange api. So according to their docs: first message sent by client have to be a LOGON message, but FixParser after opening sockets sends heartbeat instead, and api closes connection after unexpected message.
I'm writing a application using sockets, but can't seem to get the initial handshake to work. I'm using WebSockets + React on my front-end, running on PORT 8080, and Node.js socket on the backend running on PORT 5000.
The front-end handshake is done through my component like so:
componentDidMount(){
this.socket = new WebSocket('ws://localhost:5000', ['json']);
this.socket.onerror = err => {
console.log(err)
}
this.socket.onmessage = e => {
let res = JSON.parse(e.data);
console.log(e, res);
let copyArr = [...this.state.message]
copyArr.push(res);
this.setState({
message: copyArr
});
}
}
On my Node server, I do:
const server = http.createServer();
server.on('upgrade', (req, socket) => {
if(req.headers['upgrade'] !== "websocket"){
socket.end('HTTP/1.1 400 Bad Request');
return;
}
const acceptKey = req.headers['sec-websocket-key'];
const acceptHash = generateValue(acceptKey);
console.log('accepkey', acceptKey, 'hash', acceptHash);
const resHeaders = [ 'HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', `Sec-WebSocket-Accept: ${acceptHash}` ];
console.log(resHeaders);
let protocols = req.headers['sec-websocket-protocol'];
protocols = !protocols ? [] : protocols.split(',').map(name => name.trim());
if(protocols.includes('json')){
console.log('json here');
resHeaders.push(`Sec-WebSocket-Protocol: json`);
}
socket.write(resHeaders.join('\r\n') + '\r\n\r\n');
})
function generateValue(key){
return crypto
.createHash('sha1')
.update(key + '258EAFA5-E914–47DA-95CA-C5AB0DC85B11', 'binary')
.digest('base64');
}
When my React component mounts, it tries to establish the initial handshake but fails with the error: WebSocket connection to 'ws://localhost:5000/' failed: Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value. I've checked using Chrome developer tool and found this
While on the backend, when logging the request accept-key header, and response headers, I saw this:
So, unless I'm mistaken about these headers, it seems that the request and response accept-key header somehow changes when making it's way from the client to the server, and vice versa. How is this happening? Or have I misunderstood what's going on. Why exactly is the initial handshake not working?
There is a en dash – instead of hyphen - in 258EAFA5-E914–47DA-95CA-C5AB0DC85B11 after E914
So replace it with hyphen -
reference https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-WebSocket-Accept
I believe the generateValue function is wrong, you pass binary as the inputData encoding which is a keyword for latin1 according to the docs. But I believe it is UTF-8 string, not latin1, so the result hash is wrong. So just try to use update(key + '258EAFA5-E914–47DA-95CA-C5AB0DC85B11', 'utf8') or even without the second utf8 argument since it is a default.
I picked up this previous working app (Angular2) and find that it is not working (Angular4) as expected now.
Module was used (it may not matter):
import { HttpModule, JsonpModule } from '#angular/http';
Module being used now:
import { HttpClientModule} from '#angular/common/http';
Trying to get a list of records from the backend (Node.js, Express, and MongoDB) as below.
listResource(resType: string, parameters: string[]) {
console.log("***listResource");
let headers = new HttpHeaders().set("X-CustomHeader", "custom header value");
headers.append('Content-Type', 'application/fhir+json');
headers.append("'Access-Control-Allow-Origin", "*");
headers.append("Accept", "application/fhir+json");
headers.append("USER_KEY", "QIF83Fjoe4sYxdQsah3h"); //TOUCHSTONE KEY
let urlString = this.baseUrl + resType + "/list"; // + queryString;
console.log("List resource URL string: [" + urlString + "]");
return (this.httpClient.get(urlString, { headers })
.map((res: Response) => res.json()))
.catch((error: any) => Observable.throw(error.json().error || 'Server error from Observable http.get call')); //...errors if any
}
when my component is loaded, the above listResource will be called as below.
ngOnInit() {
//Get the initial 25 latest patient
//this.progressBar = true;
this.currentPage = 0;
this.patientList = [];
this.globalSvc.gPatient = [];
console.log("***OnInit");
this.restSvc.listResource("Patient", ["identifier=*", "family=*", "given=*"]).subscribe(
data => {
console.log("Response data: " + JSON.stringify(data));
},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.log('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.log(`Backend returned code ${err.status}, body was: ${err.error}`);
}
});
}
Below is the output from Chrome console. Of course, I don't get any good response. It seems to me the Chrome browser sends CORS option and the server responds correctly, then the browser doesn't send the actual GET.
If I send the REST API request from PostMan directly which doesn't have CORS, I get the expected good response from the server. Hence, it seems to me the server is ok.
Questions:
Any idea how to debug or fix it?
Will this relate to CORS on both Angular client and Node.js server?
The ${err.status} and ${err.error} are "undefined" in Chrome console. How can I find the actual error?
console.log(Backend returned code ${err.status}, body was: ${err.error});
Update 1 based on Grey's suggestion on the immutable header and const.
The GET is returning data now.
headers.append() does not alter the headers, it returns a new Headers (because Headers is immutable).
So, instead of
let headers = new HttpHeaders().set("X-CustomHeader", "custom header value");
headers.append('Content-Type', 'application/fhir+json');
headers.append("'Access-Control-Allow-Origin", "*");
headers.append("Accept", "application/fhir+json");
headers.append("USER_KEY", "QIF83Fjoe4sYxdQsah3h"); //TOUCHSTONE KEY
you need to do something like:
let headers = new HttpHeaders().set("X-CustomHeader", "custom header value")
.append('Content-Type', 'application/fhir+json')
.append("'Access-Control-Allow-Origin", "*")
.append("Accept", "application/fhir+json")
.append("USER_KEY", "QIF83Fjoe4sYxdQsah3h");
Oh, and that should actually be const headers =, rather than let headers =