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