Skip to content

Commit 2443d6d

Browse files
committed
Integrated email to users
1 parent 7d82220 commit 2443d6d

File tree

8 files changed

+202
-53
lines changed

8 files changed

+202
-53
lines changed

package-lock.json

Lines changed: 93 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@mui/material": "^5.11.15",
1818
"@mui/x-data-grid": "^6.0.4",
1919
"@mui/x-date-pickers": "^6.0.4",
20+
"@sendgrid/mail": "^7.7.0",
2021
"aos": "^2.3.4",
2122
"axios": "^1.3.5",
2223
"cheerio": "^1.0.0-rc.12",

server/models/EmailSchema.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const mongoose = require("mongoose");
2+
3+
const emailSchema = new mongoose.Schema({
4+
emails: String,
5+
stringMsg: String,
6+
});
7+
8+
const Email = mongoose.model("Email", emailSchema);
9+
10+
module.exports = Email;

server/routes/sms.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
const express = require('express');
1+
const express = require("express");
22
const router = express.Router();
33

4-
const { sendOTP, verifyOTP } = require("../services/smsAPI");
4+
const { sendOTP, verifyOTP, sendMail } = require("../services/smsAPI");
5+
const Email = require("../models/EmailSchema");
56

67
// OTP routes
78
router.post("/apis/sendOTP", (req, res) => {
@@ -16,11 +17,11 @@ router.post("/apis/sendOTP", (req, res) => {
1617
data,
1718
});
1819

19-
sendOTP(phone)
20+
sendOTP(phone)
2021
.then(() => {
21-
res.status(200).send({
22-
message: `OTP sent to ${phone}`
23-
})
22+
res.status(200).send({
23+
message: `OTP sent to ${phone}`,
24+
});
2425
})
2526
.catch((err) => {
2627
console.log(err);
@@ -33,6 +34,9 @@ router.post("/apis/sendOTP", (req, res) => {
3334
});
3435
});
3536

37+
// sendGrid router
38+
router.post("/apis/sendEmail", sendMail);
39+
3640
// Verify Endpoint
3741
router.post("/apis/verifyOTP", (req, res) => {
3842
const phone = `+91${req.body.phone}`;
@@ -75,5 +79,4 @@ router.post("/apis/verifyOTP", (req, res) => {
7579
});
7680
});
7781

78-
79-
module.exports = router;
82+
module.exports = router;

server/services/sendEmail.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const sgMail = require("@sendgrid/mail");
2+
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
3+
4+
const msg = {
5+
to: "[email protected]", // Change to your recipient
6+
from: "[email protected]", // Change to your verified sender
7+
subject: "Sending with SendGrid is Fun",
8+
text: "and easy to do anywhere, even with Node.js",
9+
html: "<strong>and easy to do anywhere, even with Node.js</strong>",
10+
};
11+
12+
sgMail
13+
.send(msg)
14+
.then(() => {
15+
console.log("Email sent");
16+
})
17+
.catch((error) => {
18+
console.error(error);
19+
});

server/services/smsAPI.js

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,64 @@
11
const TWILIO_ACCOUNT_SID = process.env.TWILIO_ACCOUNT_SID;
22
const AUTH_TOKEN = process.env.AUTH_TOKEN;
33
const SERVICE_ID = process.env.SERVICE_ID;
4-
const sgMail = require('@sendgrid/mail')
5-
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
4+
const sgMail = require("@sendgrid/mail");
5+
const Email = require("../models/EmailSchema");
66

7+
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
78

89
console.log("Twilio params", {
9-
TWILIO_ACCOUNT_SID,
10-
AUTH_TOKEN,
11-
SERVICE_ID
10+
TWILIO_ACCOUNT_SID,
11+
AUTH_TOKEN,
12+
SERVICE_ID,
1213
});
1314

14-
const twilioClient = require('twilio')(TWILIO_ACCOUNT_SID, AUTH_TOKEN);
15+
const twilioClient = require("twilio")(TWILIO_ACCOUNT_SID, AUTH_TOKEN);
1516

1617
exports.sendOTP = (phone) => {
17-
return new Promise((resolve, reject) => {
18-
twilioClient.verify.v2.services(SERVICE_ID)
19-
.verifications
20-
.create({to: phone, channel: 'sms'})
21-
.then(resolve)
22-
.catch(reject)
23-
})
24-
}
18+
return new Promise((resolve, reject) => {
19+
twilioClient.verify.v2
20+
.services(SERVICE_ID)
21+
.verifications.create({ to: phone, channel: "sms" })
22+
.then(resolve)
23+
.catch(reject);
24+
});
25+
};
2526

2627
exports.verifyOTP = (phone, code) => {
27-
return new Promise((resolve, reject) => {
28-
twilioClient.verify.v2.services(SERVICE_ID)
29-
.verificationChecks
30-
.create({to: phone, code: code})
31-
.then(resolve)
32-
.catch(reject);
33-
})
34-
}
35-
36-
exports.sendMail = () => {
28+
return new Promise((resolve, reject) => {
29+
twilioClient.verify.v2
30+
.services(SERVICE_ID)
31+
.verificationChecks.create({ to: phone, code: code })
32+
.then(resolve)
33+
.catch(reject);
34+
});
35+
};
36+
37+
// Email through sendGrid
38+
exports.sendMail = async (req, res) => {
39+
const ownerEmails = await Email.create({ emails: req.body.emails , stringMsg : req.body.stringMsg});
40+
41+
try {
3742
const msg = {
38-
to: '[email protected]', // Change to your recipient
39-
from: '[email protected]', // Change to your verified sender
40-
subject: 'Sending with SendGrid is Fun',
41-
text: 'and easy to do anywhere, even with Node.js',
42-
html: '<strong>and easy to do anywhere, even with Node.js</strong>',
43-
}
44-
sgMail
45-
.send(msg)
46-
.then(() => {
47-
console.log('Email sent')
48-
})
49-
.catch((error) => {
50-
console.error(error)
51-
})
52-
}
43+
personalizations: [
44+
{
45+
"to": [
46+
{
47+
"email": ownerEmails.emails
48+
}
49+
]}],
50+
from: "[email protected]", // Change to your verified sender
51+
subject: "Message from user to owners",
52+
text: ownerEmails.stringMsg,
53+
};
54+
55+
await sgMail.send(msg).then(() => {
56+
console.log("Email sent");
57+
return res
58+
.status(200)
59+
.json({ statusMessage: "Message sent!!", emails: ownerEmails.emails , text: ownerEmails.stringMsg });
60+
});
61+
} catch {
62+
return res.json({ statusMessage: "Message not sent!!", emails: ownerEmails.emails });
63+
}
64+
};

src/components/TagList.jsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Button } from 'flowbite-react';
22
import { useState } from 'react';
3+
import axios from 'axios'
34

4-
const TagList = () => {
5+
const TagList = ({emailMsg}) => {
56
const [tags, setTags] = useState([]);
67
const [inputValue, setInputValue] = useState('');
78

@@ -13,6 +14,7 @@ const TagList = () => {
1314
if (e.key === 'Enter' && inputValue !== '') {
1415
setTags([...tags, inputValue]);
1516
setInputValue('');
17+
console.log(tags);
1618
} else if (e.key === 'Backspace' && inputValue === '') {
1719
setTags(tags.slice(0, -1));
1820
}
@@ -22,9 +24,16 @@ const TagList = () => {
2224
setTags(tags.filter((_, index) => index !== tagIndex));
2325
};
2426

27+
const sendUrl = () => {
28+
for (let i = 0; i < tags.length; i++){
29+
axios.post('http://localhost:5001/apis/sendEmail', {emails: tags[i] , stringMsg: emailMsg }).then((resp) => {
30+
console.log(resp.data);
31+
})
32+
}
33+
}
34+
2535
return (
2636
<div className="flex flex-col gap-2 w-[100%] px-[30px]">
27-
2837
<div className='flex flex-row gap-x-[10px] items-center py-[10px]'>
2938
<input
3039
type="text"
@@ -34,7 +43,7 @@ const TagList = () => {
3443
placeholder='Enter the input tag'
3544
className="block rounded-md text-gray-900 border-[1px] border-[#DCE3EE] dark:border-[#232830] flex-grow"
3645
/>
37-
<Button className='ml-auto'>Share</Button>
46+
<Button className='ml-auto' onClick={() => sendUrl()}>Share</Button>
3847
</div>
3948

4049
<div className='w-full h-auto flex flex-col flex-grow gap-y-[10px] pb-[20px]'>

src/pages/byLink.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import React from 'react'
55

66
const ByLink = () => {
77
const { profile } = useAuth()
8-
console.log(profile)
8+
const gstinNum = profile !== null && profile.gstin;
9+
const emailMsg = `https://localhost:3000/verifyByLink/${gstinNum}`;
10+
911
return (
1012
<div className='w-[70%] dark:text-white dark:bg-dark2 text-dark3'>
1113
<div className='flex flex-col justify-center text-[26px] font-medium h-[80px] pl-[40px] border-b-[1px] dark:border-[#232830] border-[#DCE3EE]'>
@@ -20,7 +22,7 @@ const ByLink = () => {
2022
</svg>
2123
</div>
2224
<div className='flex flex-row items-center text-[16px] font-medium px-[20px] text-[#090D11] dark:text-[#D9D9D9]'>
23-
https://localhost:3000/verifyByLink/{profile.gstin}
25+
https://localhost:3000/verifyByLink/{gstinNum}
2426
</div>
2527
<Button className='ml-auto mr-[25px]'>
2628
Copy Link
@@ -33,7 +35,7 @@ const ByLink = () => {
3335
<div className='text-[12px]'>enter your friends' email address to send them link</div>
3436
</div>
3537
<div className='overflow-scroll'>
36-
<TagList/>
38+
<TagList emailMsg={emailMsg}/>
3739
</div>
3840
</div>
3941
</div>

0 commit comments

Comments
 (0)