|
|
|
|
@@ -1,9 +1,10 @@
|
|
|
|
|
"use node";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { action } from "../_generated/server";
|
|
|
|
|
import { v } from "convex/values";
|
|
|
|
|
import { internal } from "../_generated/api";
|
|
|
|
|
import { decryptSMTPPasswordNode } from "./utils/nodeCrypto";
|
|
|
|
|
import nodemailer from "nodemailer";
|
|
|
|
|
|
|
|
|
|
export const enviar = action({
|
|
|
|
|
args: {
|
|
|
|
|
@@ -12,7 +13,6 @@ export const enviar = action({
|
|
|
|
|
returns: v.object({ sucesso: v.boolean(), erro: v.optional(v.string()) }),
|
|
|
|
|
handler: async (ctx, args) => {
|
|
|
|
|
"use node";
|
|
|
|
|
const nodemailer = await import("nodemailer");
|
|
|
|
|
|
|
|
|
|
let email;
|
|
|
|
|
try {
|
|
|
|
|
@@ -26,16 +26,22 @@ export const enviar = action({
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Buscar configuração SMTP ativa
|
|
|
|
|
const configRaw = await ctx.runQuery(internal.email.getActiveEmailConfig, {});
|
|
|
|
|
|
|
|
|
|
const configRaw = await ctx.runQuery(
|
|
|
|
|
internal.email.getActiveEmailConfig,
|
|
|
|
|
{}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!configRaw) {
|
|
|
|
|
console.error("❌ Configuração SMTP não encontrada ou inativa para email:", email.destinatario);
|
|
|
|
|
console.error(
|
|
|
|
|
"❌ Configuração SMTP não encontrada ou inativa para email:",
|
|
|
|
|
email.destinatario
|
|
|
|
|
);
|
|
|
|
|
return {
|
|
|
|
|
sucesso: false,
|
|
|
|
|
erro: "Configuração de email não encontrada ou inativa. Verifique as configurações SMTP no painel de TI.",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log("📧 Tentando enviar email:", {
|
|
|
|
|
para: email.destinatario,
|
|
|
|
|
assunto: email.assunto,
|
|
|
|
|
@@ -46,10 +52,18 @@ export const enviar = action({
|
|
|
|
|
// Descriptografar senha usando função compatível com Node.js
|
|
|
|
|
let senhaDescriptografada: string;
|
|
|
|
|
try {
|
|
|
|
|
senhaDescriptografada = await decryptSMTPPasswordNode(configRaw.senhaHash);
|
|
|
|
|
senhaDescriptografada = await decryptSMTPPasswordNode(
|
|
|
|
|
configRaw.senhaHash
|
|
|
|
|
);
|
|
|
|
|
} catch (decryptError) {
|
|
|
|
|
const decryptErrorMessage = decryptError instanceof Error ? decryptError.message : String(decryptError);
|
|
|
|
|
console.error("Erro ao descriptografar senha SMTP:", decryptErrorMessage);
|
|
|
|
|
const decryptErrorMessage =
|
|
|
|
|
decryptError instanceof Error
|
|
|
|
|
? decryptError.message
|
|
|
|
|
: String(decryptError);
|
|
|
|
|
console.error(
|
|
|
|
|
"Erro ao descriptografar senha SMTP:",
|
|
|
|
|
decryptErrorMessage
|
|
|
|
|
);
|
|
|
|
|
return {
|
|
|
|
|
sucesso: false,
|
|
|
|
|
erro: `Erro ao descriptografar senha SMTP: ${decryptErrorMessage}`,
|
|
|
|
|
@@ -65,7 +79,9 @@ export const enviar = action({
|
|
|
|
|
|
|
|
|
|
// Avisar mas não bloquear se não foi testado
|
|
|
|
|
if (!config.testadoEm) {
|
|
|
|
|
console.warn("⚠️ Configuração SMTP não foi testada. Tentando enviar mesmo assim...");
|
|
|
|
|
console.warn(
|
|
|
|
|
"⚠️ Configuração SMTP não foi testada. Tentando enviar mesmo assim..."
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Marcar como enviando
|
|
|
|
|
@@ -128,8 +144,14 @@ export const enviar = action({
|
|
|
|
|
await transporter.verify();
|
|
|
|
|
console.log("✅ Conexão SMTP verificada com sucesso");
|
|
|
|
|
} catch (verifyError) {
|
|
|
|
|
const verifyErrorMessage = verifyError instanceof Error ? verifyError.message : String(verifyError);
|
|
|
|
|
console.warn("⚠️ Falha na verificação SMTP, mas tentando enviar mesmo assim:", verifyErrorMessage);
|
|
|
|
|
const verifyErrorMessage =
|
|
|
|
|
verifyError instanceof Error
|
|
|
|
|
? verifyError.message
|
|
|
|
|
: String(verifyError);
|
|
|
|
|
console.warn(
|
|
|
|
|
"⚠️ Falha na verificação SMTP, mas tentando enviar mesmo assim:",
|
|
|
|
|
verifyErrorMessage
|
|
|
|
|
);
|
|
|
|
|
// Não bloquear envio por falha na verificação, apenas avisar
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -184,9 +206,10 @@ export const enviar = action({
|
|
|
|
|
|
|
|
|
|
return { sucesso: true };
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
|
|
|
const errorMessage =
|
|
|
|
|
error instanceof Error ? error.message : String(error);
|
|
|
|
|
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.error("❌ Erro ao enviar email:", {
|
|
|
|
|
emailId: args.emailId,
|
|
|
|
|
destinatario: email?.destinatario,
|
|
|
|
|
@@ -195,8 +218,8 @@ export const enviar = action({
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Marcar como falha com detalhes completos
|
|
|
|
|
const erroCompleto = errorStack
|
|
|
|
|
? `${errorMessage}\n\nStack: ${errorStack}`
|
|
|
|
|
const erroCompleto = errorStack
|
|
|
|
|
? `${errorMessage}\n\nStack: ${errorStack}`
|
|
|
|
|
: errorMessage;
|
|
|
|
|
|
|
|
|
|
await ctx.runMutation(internal.email.markEmailFalha, {
|
|
|
|
|
@@ -208,5 +231,3 @@ export const enviar = action({
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|