import { arch } from "os"; import nodemailer from "nodemailer"; import _ from "lodash"; import { getHostname } from "./os"; const host = process.env.EMAIL_HOST; const port = process.env.EMAIL_PORT; const fromEmail = process.env.FROM_EMAIL || "taskbar-client@example.com"; const toEmail = process.env.ADMIN_EMAIL; const retryTimeout = 30 * 60 * 1000; // 30min const sendedErrors = []; const transporter = nodemailer.createTransport({ host, port, secure: false, // true for 465, false for other ports name: getHostname(), // required usage to prevent nodemailer internal call _getHostname() that leads to exception [A system error occurred: uv_os_gethostname returned ENOSYS (function not implemented)] on win7 with electron=^19 }); export async function sendAdmin({ error, versions }) { const id = error?.stack?.substring(0, 60); const ignoredErrors = [ "TypeError: Object has been destroyed", "Error: spawn C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe ENOENT", ]; if ( !!error && !sendedErrors.includes(id) && !ignoredErrors.includes(error?.toString()) ) { const subject = error?.name || "unknown error"; const date = new Date(Date.now()).toLocaleDateString("uk"); const time = new Date(Date.now()).toLocaleTimeString("uk"); const v = JSON.stringify(versions); const text = `Versions: ${v}\nLocal DT: ${date} ${time}\nError: ${error}\n\nStack trace: ${error?.stack}`; try { const result = await transporter.sendMail({ from: fromEmail, to: toEmail, subject: `${getHostname()}(${arch()}): ${subject}`, text, }); sendedErrors.push(id); setTimeout(() => { _.remove(sendedErrors, (i) => i === id); }, retryTimeout); return result; } catch (e) { setTimeout(() => sendAdmin({ error, versions }), retryTimeout); return 0; } } return 0; } export default transporter;