Send email from React application - javascript

I have an application, built using React. If I want to send an email to a user after another user successfully completes an action, what are some technologies I need to or can use? To clarify, I have no backend server set up yet.

Check sendgrid! You can do in your backend(nodejs in this case):
const SGmail = require ('#sendgrid/mail')
SGmail.setApiKey(process.env.REACT_APP_SG_API)
app.post('/your/endpoint', (req,res) => {
const data = req.body
const mailOptions = {
from: data.email,
to:'email#example.com',
subject:'Subject',
html:`<p>${data.name}</p>
<p>${data.email}</p>
<p>${data.message}</p>`
}
SGmail.send(mailOptions).then((err,res)=>{res.redirect('/')})
})

Check out SendGrid, they offer a generous free tier.

If you're not expected to do the actual email sending, you could, in JS, build an .eml file and have the user "download" it. They would then send it in their client of choice.
Otherwise you will need, at the very least, access to a mail server, to send this multipart-mime to, or, a little safer, build the message on the server and send it internally.

Related

Fetch POST to send DELETE query to MySQL - is it safe?

Since many web hosting websites (such as infinityfree and 000webhost) block HTTP DELETE requests I found a way how to send DELETE query to MySQL by adding a password to HTTP POST body which triggers PHP to send DELETE query to MySQL.
But is this safe since the password is visible in Front End and so visible to any site visitor? Can someone do harm to my database by using this password like making SQL injection?
In React JS:
async function sendDeleteRequest(i) {
const bodyWithPassword = {
...props.updatedProducts[i],
password: "kfI2KiIMOibKn0X98ufe$#!G^z78FNbbvI!fng0p*vk",
};
await fetch(Links["products"], {
method: "POST",
body: JSON.stringify(bodyWithPassword),
headers: {
"Content-Type": "application/json",
},
});
await props.refreshProductListContent();
}
In PHP:
//If HTTP body has password send DELETE query.
if ($json["password"] = "kfI2KiIMOibKn0X98ufe$#!G^z78FNbbvI!fng0p*vk") {
$deleteProduct = new $json["productType"]($json);
$deleteProduct->deleteProduct($json);
return;
}
//If password isn't added in the body add product to database
$newProduct = new $json["productType"]($json);
$newProduct->addProduct($json, $newProduct);
The short answer is - This is not safe
Having a hard-coded password in ReactJS, which is a client-based Javascript code, means that it's accessible to anyone who visits and loads the Javascript file. Anyone can read it, use it and abuse it.
There is not enough code provided to see if there is a SQL injection vulnerability as such. You should review deleteProduct and addProduct functions and see if you have parameterized all the parameters passed to a SQL query.
In a scenario where your code was vulnerable to a SQL injection, anyone can grab the client-side encoded password and abuse the SQL injection vulnerability.
Regarding the request type, there is no actual difference between a POST and a DELETE request (technically speaking), apart from how your server side code processes it, which is what you write and decide. Obviously the development world has agreed to common sense on which each of the methods does here https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods, which you should oblige by when doing development.

Channel_not_found: authed_user cannot post a message to a channel via Slack API

I'm trying to post a message on a channel a user belongs via the Slack Api as an authed_user.
here is the flow:
User gives permissions with scopes 'chat:write,channels:write,channels:history'
I receive a token along with some more information from Slack that looks like xoxp-122474-a bunch of numbers
I create a Slack Client with the token and sends a request with:
const { WebClient } = require('#slack/web-api');
const client = new WebClient(token.access_token);
await client.chat.postMessage({
channel: channelId, // = Something similar to C02E2K5CCUZ
as_user: true,
text: "here is some text",
});
I get an error from the slack API, 'channel_not_found' but I checked the channel does exists + the user is in the channel.
What should I do to make this work? Am I missing anything?
Thank you !
It's possible that error is a red herring. The as_user parameter might be messing you up. That parameter can only be used for legacy apps. You can still use chat.postMessage but make sure you are also requesting the [chat:write.customize][1] scope. You will then be able to customize the posting user by defining the username and icon_urlparameters in your API call.

How can I debug Stanza.js Authentication?

I'm currently attempting to setup an XMPP client using Stanza.js
https://github.com/legastero/stanza
I have a working server that accepts connections from a Gajim client, however when attempting to connect using Stanza.js client.connect method, the server opens up a websocket connection, but no events for authentication, or session started ever fire.
The server logs do not show any plaintext password authentication attempts.
How can I actually see any of the stanza logs to debug this issue?
import * as XMPP from 'stanza';
const config = { credentials: {jid: '[jid]', password: '[password]'}, transports: {websocket: '[socketurl]', bosh: false} };
const client = XMPP.createClient(config)
client.on('raw:*', (data) => {
console.log('data', data)
})
client.connect();
onconnect event does fire, but this is the only event that fires.
Is there a way to manually trigger authentication that isn't expressed in the documentation?
The raw event handler should be able to give you the logging you want - but in your code sample, you are invoking it incorrectly. Try the following.
client.on('raw:*', (direction, data) => {
console.log(direction, data)
})
For reference, the docs state that the callback for the raw data event handler is
(direction: incoming | outgoing, data: string) => void
So the data that you are looking for is in the second argument, but your callback only has one argument (just the direction string "incoming" or "outgoing", although you have named the argument "data").
Once you fix the logging I expect you will see the stream immediately terminates with a stream error. Your config is incorrect. The jid and password should be top level fields. Review the stanza sample code. For the options to createClient - there is no credentials object. Try the following:
const config = { jid: '[jid]', password: '[password]', transports: {websocket: '[socketurl]', bosh: false} };
Since your username and password are hidden behind an incorrect credentials object, stanza.io does not see them and you are effectively trying to connect with no username and password so no authentication is even attempted.
This issue happened to be caused by a configuration problem.
The jabber server was using plain authentication.
Adding an additional line to the client definition file helped.
Also adding
client.on('*', console.log)
offered more complete server logs.
client.sasl.disable('X-OAUTH2')
How can I actually see any of the stanza logs to debug this issue?
If the connection is not encrypted, you can sniff the XMPP traffic with tools like
sudo tcpflow -i lo -Cg port 5222
You can force ejabberd to not allow encryption, so your clients don't use that, and you can read the network traffic.
Alternatively, in ejabbed.yml you can set this, but probably it will generate a lot of log messages:
loglevel: debug

Emit event for particular user if login functionality in application in Socket.io with Node.js

I have used methods socket.on and io.emit, And i got response to all users. But, i want to get response for particular user.
But my application contains login functionality and i followed this post on stackoverflow, and they are saying we need unique userId and socketId in an object for a particular user to emit an event for a particular user.
But i am getting the userId after login, But we want it when user connect to app.
So can anyone please help me with the same?
In your node.js, create a global array 'aryUser', each element contains the socketid and loginid.
node.js onConnect (new connection), add a new element to the array with the socketid and set loginid = empty.
after the user login, emit an event from client to the server, e.g:
socket.emit('userloginok', loginid)
in node.js, define a function:
socket.on('userloginok', loginid)
and in this function, search the aryUser with the socketid and replace the empty loginid inside the array element with the parm loginid.
in node.js, define the function:
socket.on('disconnect')
and in this function, search the aryUser, use aryUser.splice(i,1) to remove the user just disconnected.
that means, aryUser contains all users connected, some of them logined, some of them not logined. And you can use the socketid of the array to send message to particular user, and/or all users.
Example Source Code:
server.js
http://www.zephan.top/server.js
server.html
http://www.zephan.top/server.html.txt
rename server.html.txt to server.html, put server.html and server.js in the same directory, and run:
node server.js
Yes, you definitely need socketId in order to send and receive messages between two specific users.
UserId is required just to keep track of socketId associated with the particular user or you can manage it with some other way as well that's up to you.
As per your question, you have userId of the user and you need socketId of that user! So, in this case, you can pass userId when that particular connects to a socket server from the client side as shown in below snippet,
const socket = io(this.SOCKET_SERVER_BASE_URL, { query: `userId=${userId}` });
And you can read this user on nodejs server like this,
const userId= socket.request._query['userId'],
const socketId= socket.id
Now store this socketId in somewhere, for example, Redis or some sort of caching mechanism again up to you, just make sure fetching and retrieval should be fast.
Now while sending a message just pull the socketId from your cache and emit the message on that socketId by using below code,
io.to(socket.id).emit(`message-response`, {
message: 'hello'
});
I have written a complete blog post on this topic on both Angular and AngularJs, you can refer those as well.
Edit 1:
Part 1 =>
When your user completes the login request, then make the connection to the socket server.
Assuming you are using React Or Angular After a successful login you will redirect your user to home component(page). On the Home component(page) make the socket server connect by passing the userId just like this,
const socket = io(SOCKET_SERVER_BASE_URL, { query: `userId=${userId}` });
P.S. you can get userID from URL or maybe using a cookie that is up to you.
Once you receive this socket connection request on the server, then you can read the userID query and you can get socketId associated with it and store it in cache like this,
io.use( async (socket, next) => {
try {
await addSocketIdInCache({
userId: socket.request._query['userId'],
socketId: socket.id
});
next();
} catch (error) {
// Error
console.error(error);
}
});
Part 2 =>
Now, let's say you have a list of the users on the client side, and you want to send a message to particular users.
socket.emit(`message`, {
message: 'hello',
userId: userId
});
On the server side, fetch the socketId from the cache using UserId. Once you get the socketId from cache send a specific message like this,
io.to(socketId).emit(`message-response`, {
message: 'hello'
});
Hope this helps.

Verify an email account is active using react on the *client side*

I am making an authentication form and I would like to verify silently an email address is active on the client side. That is if the email address exists, then return true, else return false. This does not involve sending an actualy email to the address. I can do this on the server side using email-verify package in node, ie:
server.post('/api/verify-valid-email-silently', (req, res) => {
if (req.body && req.body.email) {
const email = req.body.email
email_verifier.verify( email, (err : string, info : any) => {
// do something
})
}
}
But I would like to do this on the client side so that I don't have to ping the server and pay for cloud function invocation. Again I'm looking for a free service on the client side. This is important because if I use the current "ping the server" way, someone could conceivably repeatedly enter inactive but well-formed email address and drain my bank account dry completely.
It does require a validation email, but it can be done without maintaining server-side infrastructure. I actually built a platform to do exactly that at https://clicktoverify.net/.
Essentially you just need to add our (small) javascript library to your page. Then you'll be able to send a verification email via our service and execute a client-side callback once the client verifies by clicking the link in their email.

Categories

Resources