diff --git a/_reference/localEmailViewer/index.js b/_reference/localEmailViewer/index.js
index 2b4c21444..1dd17f779 100644
--- a/_reference/localEmailViewer/index.js
+++ b/_reference/localEmailViewer/index.js
@@ -1,116 +1,96 @@
// index.js
-import express from 'express';
-import fetch from 'node-fetch';
-import {simpleParser} from 'mailparser';
+import express from "express";
+import fetch from "node-fetch";
+import { simpleParser } from "mailparser";
const app = express();
const PORT = 3334;
-app.get('/', async (req, res) => {
- try {
- const response = await fetch('http://localhost:4566/_aws/ses');
- if (!response.ok) {
- throw new Error('Network response was not ok');
- }
- const data = await response.json();
- const messagesHtml = await parseMessages(data.messages);
- res.send(renderHtml(messagesHtml));
- } catch (error) {
- console.error('Error fetching messages:', error);
- res.status(500).send('Error fetching messages');
+app.get("/", async (req, res) => {
+ try {
+ const response = await fetch("http://localhost:4566/_aws/ses");
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
}
+ const data = await response.json();
+ const messagesHtml = await parseMessages(data.messages);
+ res.send(renderHtml(messagesHtml));
+ } catch (error) {
+ console.error("Error fetching messages:", error);
+ res.status(500).send("Error fetching messages");
+ }
});
async function parseMessages(messages) {
- const parsedMessages = await Promise.all(
- messages.map(async (message, index) => {
- try {
- const parsed = await simpleParser(message.RawData);
- return `
-
-
-
- Message ${index + 1}
-
-
- From: ${message.Source}
-
-
- Region: ${message.Region}
-
-
- Timestamp: ${message.Timestamp}
-
-
-
- ${parsed.html || parsed.textAsHtml || 'No HTML content available'}
-
-
- `;
- } catch (error) {
- console.error('Error parsing email:', error);
- return `
-
-
- Message ${index + 1}
-
-
- From: ${message.Source}
-
-
- Region: ${message.Region}
-
-
- Timestamp: ${message.Timestamp}
-
-
- Error parsing email content
-
-
- `;
- }
- })
- );
- return parsedMessages.join('');
+ const parsedMessages = await Promise.all(
+ messages.map(async (message, index) => {
+ try {
+ const parsed = await simpleParser(message.RawData);
+ return `
+
+
+
Message ${index + 1}
+
From: ${message.Source}
+
To: ${parsed.to.text || "No To Address"}
+
Subject: ${parsed.subject || "No Subject"}
+
Region: ${message.Region}
+
Timestamp: ${message.Timestamp}
+
+
${parsed.html || parsed.textAsHtml || "No HTML content available"}
+
+ `;
+ } catch (error) {
+ console.error("Error parsing email:", error);
+ return `
+
+
Message ${index + 1}
+
From: ${message.Source}
+
Region: ${message.Region}
+
Timestamp: ${message.Timestamp}
+
Error parsing email content
+
+ `;
+ }
+ })
+ );
+ return parsedMessages.join("");
}
function renderHtml(messagesHtml) {
- return `
-
-
-
-
-
- Email Messages Viewer
-
-
-
-
-
-
Email Messages Viewer
-
- ${messagesHtml}
-
-
-
-
- `;
+ return `
+
+
+
+
+
+ Email Messages Viewer
+
+
+
+
+
+
Email Messages Viewer
+
${messagesHtml}
+
+
+
+ `;
}
app.listen(PORT, () => {
- console.log(`Server is running on http://localhost:${PORT}`);
-});
\ No newline at end of file
+ console.log(`Server is running on http://localhost:${PORT}`);
+});
diff --git a/_reference/localEmailViewer/package-lock.json b/_reference/localEmailViewer/package-lock.json
index ae14abb19..2c7ecad93 100644
--- a/_reference/localEmailViewer/package-lock.json
+++ b/_reference/localEmailViewer/package-lock.json
@@ -10,7 +10,7 @@
"license": "ISC",
"dependencies": {
"express": "^5.1.0",
- "mailparser": "^3.7.2",
+ "mailparser": "^3.7.4",
"node-fetch": "^3.3.2"
}
},
@@ -634,9 +634,9 @@
"license": "MIT"
},
"node_modules/libmime": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.6.tgz",
- "integrity": "sha512-j9mBC7eiqi6fgBPAGvKCXJKJSIASanYF4EeA4iBzSG0HxQxmXnR3KbyWqTn4CwsKSebqCv2f5XZfAO6sKzgvwA==",
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.7.tgz",
+ "integrity": "sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw==",
"license": "MIT",
"dependencies": {
"encoding-japanese": "2.2.0",
@@ -661,31 +661,31 @@
}
},
"node_modules/mailparser": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.7.2.tgz",
- "integrity": "sha512-iI0p2TCcIodR1qGiRoDBBwboSSff50vQAWytM5JRggLfABa4hHYCf3YVujtuzV454xrOP352VsAPIzviqMTo4Q==",
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.7.4.tgz",
+ "integrity": "sha512-Beh4yyR4jLq3CZZ32asajByrXnW8dLyKCAQD3WvtTiBnMtFWhxO+wa93F6sJNjDmfjxXs4NRNjw3XAGLqZR3Vg==",
"license": "MIT",
"dependencies": {
"encoding-japanese": "2.2.0",
"he": "1.2.0",
"html-to-text": "9.0.5",
"iconv-lite": "0.6.3",
- "libmime": "5.3.6",
+ "libmime": "5.3.7",
"linkify-it": "5.0.0",
- "mailsplit": "5.4.2",
- "nodemailer": "6.9.16",
+ "mailsplit": "5.4.5",
+ "nodemailer": "7.0.4",
"punycode.js": "2.3.1",
- "tlds": "1.255.0"
+ "tlds": "1.259.0"
}
},
"node_modules/mailsplit": {
- "version": "5.4.2",
- "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-5.4.2.tgz",
- "integrity": "sha512-4cczG/3Iu3pyl8JgQ76dKkisurZTmxMrA4dj/e8d2jKYcFTZ7MxOzg1gTioTDMPuFXwTrVuN/gxhkrO7wLg7qA==",
+ "version": "5.4.5",
+ "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-5.4.5.tgz",
+ "integrity": "sha512-oMfhmvclR689IIaQmIcR5nODnZRRVwAKtqFT407TIvmhX2OLUBnshUTcxzQBt3+96sZVDud9NfSe1NxAkUNXEQ==",
"license": "(MIT OR EUPL-1.1+)",
"dependencies": {
"libbase64": "1.3.0",
- "libmime": "5.3.6",
+ "libmime": "5.3.7",
"libqp": "2.1.1"
}
},
@@ -793,9 +793,9 @@
}
},
"node_modules/nodemailer": {
- "version": "6.9.16",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz",
- "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.4.tgz",
+ "integrity": "sha512-9O00Vh89/Ld2EcVCqJ/etd7u20UhME0f/NToPfArwPEe1Don1zy4mAIz6ariRr7mJ2RDxtaDzN0WJVdVXPtZaw==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
@@ -1114,9 +1114,9 @@
}
},
"node_modules/tlds": {
- "version": "1.255.0",
- "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.255.0.tgz",
- "integrity": "sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw==",
+ "version": "1.259.0",
+ "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.259.0.tgz",
+ "integrity": "sha512-AldGGlDP0PNgwppe2quAvuBl18UcjuNtOnDuUkqhd6ipPqrYYBt3aTxK1QTsBVknk97lS2JcafWMghjGWFtunw==",
"license": "MIT",
"bin": {
"tlds": "bin.js"
diff --git a/_reference/localEmailViewer/package.json b/_reference/localEmailViewer/package.json
index 74cef99ff..5f553cf17 100644
--- a/_reference/localEmailViewer/package.json
+++ b/_reference/localEmailViewer/package.json
@@ -12,7 +12,7 @@
"description": "",
"dependencies": {
"express": "^5.1.0",
- "mailparser": "^3.7.2",
+ "mailparser": "^3.7.4",
"node-fetch": "^3.3.2"
}
}
diff --git a/docker-compose.yml b/docker-compose.yml
index ae8b35048..ad805e272 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -119,6 +119,7 @@ services:
aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-large-log --create-bucket-configuration LocationConstraint=ca-central-1
aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-job-totals --create-bucket-configuration LocationConstraint=ca-central-1
aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket parts-estimates --create-bucket-configuration LocationConstraint=ca-central-1
+ aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-carfax-uploads --create-bucket-configuration LocationConstraint=ca-central-1
"
# Node App: The Main IMEX API
node-app:
diff --git a/hasura/metadata/cron_triggers.yaml b/hasura/metadata/cron_triggers.yaml
index 534560869..cc1baa225 100644
--- a/hasura/metadata/cron_triggers.yaml
+++ b/hasura/metadata/cron_triggers.yaml
@@ -6,6 +6,15 @@
headers:
- name: x-imex-auth
value_from_env: DATAPUMP_AUTH
+- name: CARFAX Data Pump
+ webhook: '{{HASURA_API_URL}}/data/carfax'
+ schedule: 0 7 * * 6
+ include_in_metadata: true
+ payload: {}
+ headers:
+ - name: x-imex-auth
+ value_from_env: DATAPUMP_AUTH
+ comment: Project Mexico
- name: Chatter Data Pump
webhook: '{{HASURA_API_URL}}/data/chatter'
schedule: 45 5 * * *
diff --git a/server/data/carfax.js b/server/data/carfax.js
index b25e371a8..c1db22193 100644
--- a/server/data/carfax.js
+++ b/server/data/carfax.js
@@ -6,7 +6,7 @@ const InstanceManager = require("../utils/instanceMgr").default;
const { isString, isEmpty } = require("lodash");
const fs = require("fs");
const client = require("../graphql-client/graphql-client").client;
-const { sendServerEmail } = require("../email/sendemail");
+const { sendServerEmail, sendMexicoBillingEmail } = require("../email/sendemail");
const { uploadFileToS3 } = require("../utils/s3");
const crypto = require("crypto");
@@ -168,6 +168,29 @@ async function processShopData(shopsToProcess, start, end, skipUpload, ignoreDat
await uploadViaSFTP(jsonObj);
}
+ await sendMexicoBillingEmail({
+ subject: `${shopid.toUpperCase()}_Mexico_${moment().format("MM-DD-YY")} ROs ${jsonObj.count} Error ${errorCode(jsonObj)}`,
+ text: `Errors:\n${JSON.stringify(
+ erroredJobs.map((ej) => ({
+ ro_number: ej.job?.ro_number,
+ jobid: ej.job?.id,
+ error: ej.error
+ })),
+ null,
+ 2
+ )}\n\nUploaded:\n${JSON.stringify(
+ {
+ bodyshopid: bodyshop.id,
+ imexshopid: shopid,
+ count: jsonObj.count,
+ filename: jsonObj.filename,
+ result: jsonObj.result
+ },
+ null,
+ 2
+ )}`
+ });
+
allXMLResults.push({
bodyshopid: bodyshop.id,
imexshopid: shopid,
@@ -402,3 +425,14 @@ const generatePartType = (type) => {
return partTypeMap[type?.toLowerCase()] || null;
};
+
+const errorCode = ({ count, filename, results }) => {
+ if (count === 0) return 1;
+ if (!filename) return 3;
+ const sftpErrorCode = results?.sftpError?.code;
+ if (sftpErrorCode && ["ECONNREFUSED", "ENOTFOUND", "ETIMEDOUT", "ECONNRESET"].includes(sftpErrorCode)) {
+ return 4;
+ }
+ if (sftpErrorCode) return 7;
+ return 0;
+};
diff --git a/server/email/sendemail.js b/server/email/sendemail.js
index 6622cb6ce..c9a72c17f 100644
--- a/server/email/sendemail.js
+++ b/server/email/sendemail.js
@@ -79,6 +79,41 @@ const sendServerEmail = async ({ subject, text }) => {
}
};
+const sendMexicoBillingEmail = async ({ subject, text }) => {
+ if (process.env.NODE_ENV === undefined) return;
+ try {
+ mailer.sendMail(
+ {
+ from: InstanceManager({
+ imex: `ImEX Online API - ${process.env.NODE_ENV} `,
+ rome: `Rome Online API - ${process.env.NODE_ENV} `
+ }),
+ to: ["mexico@rometech.zohodesk.com"],
+ subject: subject,
+ text: text,
+ ses: {
+ // optional extra arguments for SendRawEmail
+ Tags: [
+ {
+ Name: "tag_name",
+ Value: "tag_value"
+ }
+ ]
+ }
+ },
+ // eslint-disable-next-line no-unused-vars
+ (err, info) => {
+ logger.log("server-email-failure", err ? "error" : "debug", null, null, {
+ message: err?.message,
+ stack: err?.stack
+ });
+ }
+ );
+ } catch (error) {
+ logger.log("server-email-failure", "error", null, null, { message: error?.message, stack: error?.stack });
+ }
+};
+
const sendWelcomeEmail = async ({ to, resetLink, dateLine, features, bcc }) => {
try {
await mailer.sendMail({
@@ -420,6 +455,7 @@ ${body.bounce?.bouncedRecipients.map(
module.exports = {
sendEmail,
sendServerEmail,
+ sendMexicoBillingEmail,
sendTaskEmail,
emailBounce,
sendWelcomeEmail