Compare commits

...

13 Commits

Author SHA1 Message Date
AllenTJ7
f62dfdfad2 dev merged 2025-05-19 12:55:57 +05:30
aee28a6050 phonepe (#26)
All checks were successful
Deploy FitLien services to Dev / Deploy to Dev (push) Successful in 3m44s
Co-authored-by: AllenTJ7 <163137620+AllenTJ7@users.noreply.github.com>
Reviewed-on: #26
2025-05-14 13:09:09 +00:00
5f89a5cda4 Email with attachment issue fixed (#25)
All checks were successful
Deploy FitLien services to Dev / Deploy to Dev (push) Successful in 3m43s
Reviewed-on: #25
Co-authored-by: Sharon Dcruz <sharondcruz@cosq.net>
Co-committed-by: Sharon Dcruz <sharondcruz@cosq.net>
2025-05-07 07:20:27 +00:00
1e040212e4 Update deploy-dev.yaml
All checks were successful
Deploy FitLien services to Dev / Deploy to Dev (push) Successful in 3m22s
2025-05-06 18:17:09 +05:30
ccd0ee61bc Update deploy-dev.yaml
Some checks failed
Deploy FitLien services to Dev / Deploy to Dev (push) Has been cancelled
2025-05-06 18:06:46 +05:30
9b42fdcac1 Update deploy-dev.yaml
Some checks failed
Deploy FitLien services to Dev / Deploy to Dev (push) Has been cancelled
2025-05-06 18:04:34 +05:30
4b745d587f Update deploy-dev.yaml
Some checks failed
Deploy FitLien services to Dev / Deploy to Dev (push) Failing after 18s
2025-05-06 17:59:11 +05:30
3adf2a3aac Update deploy-dev.yaml
Some checks failed
Deploy FitLien services to Dev / Deploy to Dev (push) Has been cancelled
2025-05-06 17:56:58 +05:30
868ae3dea4 Update deploy-dev.yaml
All checks were successful
Deploy FitLien services to Dev / Deploy to Dev (push) Successful in 3m19s
2025-05-06 17:53:13 +05:30
b8b518be9c Update deploy-dev.yaml
All checks were successful
Deploy FitLien services to Dev / Deploy to Dev (push) Successful in 1m59s
2025-05-06 17:51:13 +05:30
0f86c468d2 Update deploy-dev.yaml
Some checks failed
Deploy FitLien services to Dev / Deploy to Dev (push) Failing after 19s
2025-05-06 17:47:06 +05:30
bef6b4085b Merge pull request 'phonepe' (#24) from phonepe into dev
Some checks failed
Deploy FitLien services to Dev / Deploy to Dev (push) Failing after 19s
Reviewed-on: #24
2025-05-06 11:40:13 +00:00
9efa31b6cc phonepe (#23)
All checks were successful
Deploy FitLien services to Dev / Deploy to Dev (push) Successful in 4m15s
Co-authored-by: AllenTJ7 <163137620+AllenTJ7@users.noreply.github.com>
Reviewed-on: #23
Co-authored-by: Allen T J <allentj@cosq.net>
Co-committed-by: Allen T J <allentj@cosq.net>
2025-05-05 14:09:08 +00:00
4 changed files with 67 additions and 32 deletions

View File

@ -11,14 +11,14 @@
"@aws-sdk/client-ses": "^3.798.0",
"@types/node-fetch": "^2.6.12",
"aws-sdk": "^2.1692.0",
"axios": "^1.8.4",
"axios": "^1.9.0",
"cors": "^2.8.5",
"firebase-admin": "^12.6.0",
"firebase-functions": "^6.0.1",
"form-data": "^4.0.1",
"functions": "file:",
"html-to-text": "^9.0.5",
"long": "^4.0.0",
"long": "^5.3.2",
"mailgun.js": "^10.4.0",
"node-fetch": "^2.7.0",
"pdfjs-dist": "^5.0.375",
@ -1373,12 +1373,6 @@
"node": ">=6"
}
},
"node_modules/@grpc/proto-loader/node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"optional": true
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@ -2755,6 +2749,7 @@
"integrity": "sha512-eQs9RsucA/LNjnMoJvWG/nXa7Pot/RbBzilF/QRIU/xRl+0ApxrSUFsV5lmf01SvSlqMzJ7Zwxe440wmz2SJGA==",
"deprecated": "This is a stub types definition. long provides its own type definitions, so you do not need this installed.",
"dev": true,
"license": "MIT",
"dependencies": {
"long": "*"
}
@ -3051,6 +3046,7 @@
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
@ -6059,9 +6055,10 @@
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"node_modules/long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"license": "Apache-2.0"
},
"node_modules/lru-cache": {
"version": "5.1.1",
@ -6687,11 +6684,6 @@
"node": ">=12.0.0"
}
},
"node_modules/protobufjs/node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",

View File

@ -18,14 +18,14 @@
"@aws-sdk/client-ses": "^3.798.0",
"@types/node-fetch": "^2.6.12",
"aws-sdk": "^2.1692.0",
"axios": "^1.8.4",
"axios": "^1.9.0",
"cors": "^2.8.5",
"firebase-admin": "^12.6.0",
"firebase-functions": "^6.0.1",
"form-data": "^4.0.1",
"functions": "file:",
"html-to-text": "^9.0.5",
"long": "^4.0.0",
"long": "^5.3.2",
"mailgun.js": "^10.4.0",
"node-fetch": "^2.7.0",
"pdfjs-dist": "^5.0.375",

View File

@ -6,6 +6,7 @@ import { SESClient } from "@aws-sdk/client-ses";
import { SendEmailCommand, SendRawEmailCommand } from "@aws-sdk/client-ses";
import { HttpsError } from "firebase-functions/v2/https";
import * as mime from 'mime-types';
import axios from 'axios';
const logger = getLogger();
const corsHandler = getCorsHandler();
@ -18,6 +19,8 @@ interface EmailRequest {
from: string;
replyTo?: string;
attachments?: Attachment[];
fileUrl?: string;
fileName?: string;
}
interface Attachment {
@ -121,31 +124,71 @@ async function sendEmailWithAttachments(data: EmailRequest, recipients: string[]
return { messageId: result.MessageId };
}
async function downloadFileFromUrl(url: string): Promise<Buffer> {
try {
const response = await axios.get(url, { responseType: 'arraybuffer' });
return Buffer.from(response.data);
} catch (error) {
logger.error(`Error downloading file from URL: ${error}`);
throw new Error(`Failed to download file: ${error}`);
}
}
export const sendEmailSES = onRequest({
region: 'asia-south1'
}, (request: Request, response) => {
return corsHandler(request, response, async () => {
const toAddress = request.body.toAddress;
const subject = request.body.subject;
const message = request.body.message;
const data: EmailRequest = {
to: toAddress,
subject: subject,
html: message,
text: stripHtml(message),
from: process.env.SES_FROM_EMAIL || 'support@fitlien.com',
replyTo: process.env.SES_REPLY_TO_EMAIL || 'support@fitlien.com',
attachments: request.body.attachments as Attachment[] || []
};
try {
const toAddress = request.body.toAddress;
const subject = request.body.subject;
const message = request.body.message;
// Initialize data with basic fields
const data: EmailRequest = {
to: toAddress,
html: message,
subject: subject,
text: stripHtml(message),
from: process.env.SES_FROM_EMAIL || 'support@fitlien.com',
replyTo: process.env.SES_REPLY_TO_EMAIL || 'support@fitlien.com',
attachments: request.body.attachments as Attachment[] || []
};
// Handle file URL if provided
if (request.body.fileUrl && request.body.fileName) {
logger.info(`Downloading attachment from URL: ${request.body.fileUrl}`);
try {
const fileContent = await downloadFileFromUrl(request.body.fileUrl);
// If attachments array doesn't exist, create it
if (!data.attachments) {
data.attachments = [];
}
// Add the downloaded file as an attachment
data.attachments.push({
filename: request.body.fileName,
content: fileContent,
contentType: mime.lookup(request.body.fileName) || 'application/octet-stream'
});
logger.info(`Successfully downloaded attachment: ${request.body.fileName}`);
} catch (downloadError) {
logger.error(`Failed to download attachment: ${downloadError}`);
throw new Error(`Failed to process attachment: ${downloadError}`);
}
}
if (!data.to || !data.subject || !data.html || !data.from) {
throw new HttpsError(
'invalid-argument',
'Missing required email fields'
);
}
logger.info(`Sending Email '${data.subject}' to '${data.to}' from '${data.from}'`);
const recipients = Array.isArray(data.to) ? data.to : [data.to];
if (data.attachments && data.attachments.length > 0) {
const messageResult = await sendEmailWithAttachments(data, recipients);
response.status(200).json(messageResult);

View File

@ -21,7 +21,7 @@ export const phonePeWebhook = onRequest({
body: request.body,
method: request.method
});
const authHeader = request.headers['authorization'] as string;
const username = process.env.PHONEPE_WEBHOOK_USERNAME;
const password = process.env.PHONEPE_WEBHOOK_PASSWORD;
@ -37,7 +37,7 @@ export const phonePeWebhook = onRequest({
.createHash('sha256')
.update(credentialString)
.digest('hex');
const receivedAuth = authHeader.replace(/^SHA256\s+/i, '');
if (receivedAuth.toLowerCase() !== expectedAuth.toLowerCase()) {