mirror of
https://github.com/kyantech/Palmr.git
synced 2025-10-23 06:11:58 +00:00
feat: add SMTP connection testing functionality (#103)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { EmailService } from "../email/service";
|
||||
import { LogoService } from "./logo.service";
|
||||
import { AppService } from "./service";
|
||||
import { FastifyReply, FastifyRequest } from "fastify";
|
||||
@@ -26,6 +27,7 @@ if (!fs.existsSync(uploadsDir)) {
|
||||
export class AppController {
|
||||
private appService = new AppService();
|
||||
private logoService = new LogoService();
|
||||
private emailService = new EmailService();
|
||||
|
||||
async getAppInfo(request: FastifyRequest, reply: FastifyReply) {
|
||||
try {
|
||||
@@ -70,6 +72,24 @@ export class AppController {
|
||||
}
|
||||
}
|
||||
|
||||
async testSmtpConnection(request: FastifyRequest, reply: FastifyReply) {
|
||||
try {
|
||||
await request.jwtVerify();
|
||||
|
||||
if (!(request as any).user?.isAdmin) {
|
||||
return reply.status(403).send({ error: "Access restricted to administrators" });
|
||||
}
|
||||
|
||||
const body = request.body as any;
|
||||
const smtpConfig = body.smtpConfig || undefined;
|
||||
|
||||
const result = await this.emailService.testConnection(smtpConfig);
|
||||
return reply.send(result);
|
||||
} catch (error: any) {
|
||||
return reply.status(400).send({ error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async uploadLogo(request: FastifyRequest, reply: FastifyReply) {
|
||||
try {
|
||||
const file = await request.file();
|
||||
|
@@ -126,6 +126,54 @@ export async function appRoutes(app: FastifyInstance) {
|
||||
appController.bulkUpdateConfigs.bind(appController)
|
||||
);
|
||||
|
||||
app.post(
|
||||
"/app/test-smtp",
|
||||
{
|
||||
preValidation: adminPreValidation,
|
||||
schema: {
|
||||
tags: ["App"],
|
||||
operationId: "testSmtpConnection",
|
||||
summary: "Test SMTP connection with provided or saved configuration",
|
||||
description:
|
||||
"Validates SMTP connectivity using either provided configuration parameters or the currently saved settings. This endpoint allows testing SMTP settings before saving them permanently. Requires admin privileges.",
|
||||
body: z
|
||||
.object({
|
||||
smtpConfig: z
|
||||
.object({
|
||||
smtpEnabled: z.string().describe("Whether SMTP is enabled ('true' or 'false')"),
|
||||
smtpHost: z.string().describe("SMTP server hostname or IP address (e.g., 'smtp.gmail.com')"),
|
||||
smtpPort: z
|
||||
.union([z.string(), z.number()])
|
||||
.transform(String)
|
||||
.describe("SMTP server port (typically 587 for TLS, 25 for non-secure)"),
|
||||
smtpUser: z.string().describe("Username for SMTP authentication (e.g., email address)"),
|
||||
smtpPass: z.string().describe("Password for SMTP authentication (for Gmail, use App Password)"),
|
||||
})
|
||||
.optional()
|
||||
.describe("SMTP configuration to test. If not provided, uses currently saved configuration"),
|
||||
})
|
||||
.optional()
|
||||
.describe("Request body containing SMTP configuration to test. Send empty body to test saved configuration"),
|
||||
response: {
|
||||
200: z.object({
|
||||
success: z.boolean().describe("Whether the SMTP connection test was successful"),
|
||||
message: z.string().describe("Descriptive message about the test result"),
|
||||
}),
|
||||
400: z.object({
|
||||
error: z.string().describe("Error message describing what went wrong with the test"),
|
||||
}),
|
||||
401: z.object({
|
||||
error: z.string().describe("Authentication error - invalid or missing JWT token"),
|
||||
}),
|
||||
403: z.object({
|
||||
error: z.string().describe("Authorization error - user does not have admin privileges"),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
appController.testSmtpConnection.bind(appController)
|
||||
);
|
||||
|
||||
app.post(
|
||||
"/app/logo",
|
||||
{
|
||||
|
@@ -1,6 +1,14 @@
|
||||
import { ConfigService } from "../config/service";
|
||||
import nodemailer from "nodemailer";
|
||||
|
||||
interface SmtpConfig {
|
||||
smtpEnabled: string;
|
||||
smtpHost: string;
|
||||
smtpPort: string;
|
||||
smtpUser: string;
|
||||
smtpPass: string;
|
||||
}
|
||||
|
||||
export class EmailService {
|
||||
private configService = new ConfigService();
|
||||
|
||||
@@ -21,6 +29,45 @@ export class EmailService {
|
||||
});
|
||||
}
|
||||
|
||||
async testConnection(config?: SmtpConfig) {
|
||||
let smtpConfig: SmtpConfig;
|
||||
|
||||
if (config) {
|
||||
// Use provided configuration
|
||||
smtpConfig = config;
|
||||
} else {
|
||||
// Fallback to saved configuration
|
||||
smtpConfig = {
|
||||
smtpEnabled: await this.configService.getValue("smtpEnabled"),
|
||||
smtpHost: await this.configService.getValue("smtpHost"),
|
||||
smtpPort: await this.configService.getValue("smtpPort"),
|
||||
smtpUser: await this.configService.getValue("smtpUser"),
|
||||
smtpPass: await this.configService.getValue("smtpPass"),
|
||||
};
|
||||
}
|
||||
|
||||
if (smtpConfig.smtpEnabled !== "true") {
|
||||
throw new Error("SMTP is not enabled");
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: smtpConfig.smtpHost,
|
||||
port: Number(smtpConfig.smtpPort),
|
||||
secure: false,
|
||||
auth: {
|
||||
user: smtpConfig.smtpUser,
|
||||
pass: smtpConfig.smtpPass,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await transporter.verify();
|
||||
return { success: true, message: "SMTP connection successful" };
|
||||
} catch (error: any) {
|
||||
throw new Error(`SMTP connection failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async sendPasswordResetEmail(to: string, resetToken: string, origin: string) {
|
||||
const transporter = await this.createTransporter();
|
||||
if (!transporter) {
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "نطاقات البريد الإلكتروني للمشرف",
|
||||
"description": "نطاقات البريد الإلكتروني التي تحصل على صلاحيات المشرف تلقائياً"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "اختبار اتصال SMTP",
|
||||
"description": "اختبار ما إذا كان تكوين SMTP صالحًا"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "احفظ {group}"
|
||||
"save": "احفظ {group}",
|
||||
"testSmtp": "اختبار الاتصال",
|
||||
"testing": "جاري الاختبار..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "فشل في تحميل الإعدادات",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "لا توجد تغييرات للحفظ",
|
||||
"updateSuccess": "تم تحديث إعدادات {group} بنجاح"
|
||||
"updateSuccess": "تم تحديث إعدادات {group} بنجاح",
|
||||
"smtpTestFailed": "فشل اتصال SMTP: {error}",
|
||||
"smtpTestGenericError": "فشل اختبار اتصال SMTP. يرجى التحقق من إعداداتك والمحاولة مرة أخرى.",
|
||||
"smtpTestSuccess": "تم اتصال SMTP بنجاح! تكوين البريد الإلكتروني الخاص بك يعمل بشكل صحيح."
|
||||
},
|
||||
"title": "الإعدادات",
|
||||
"breadcrumb": "الإعدادات",
|
||||
"pageTitle": "الإعدادات",
|
||||
"tooltips": {
|
||||
"oidcScope": "أدخل نطاقاً واضغط Enter للإضافة",
|
||||
"oidcAdminEmailDomains": "أدخل نطاقاً واضغط Enter للإضافة"
|
||||
"oidcAdminEmailDomains": "أدخل نطاقاً واضغط Enter للإضافة",
|
||||
"testSmtp": "يختبر اتصال SMTP بالقيم المدخلة حاليًا في النموذج. لجعل التغييرات دائمة، تذكر حفظ إعداداتك بعد الاختبار."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mysite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Admin-E-Mail-Domains",
|
||||
"description": "E-Mail-Domains, die automatisch Administratorrechte erhalten"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "SMTP-Verbindung testen",
|
||||
"description": "Testen Sie, ob die SMTP-Konfiguration gültig ist"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "{group} speichern"
|
||||
"save": "{group} speichern",
|
||||
"testSmtp": "Verbindung testen",
|
||||
"testing": "Teste..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Fehler beim Laden der Einstellungen",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Keine Änderungen zum Speichern",
|
||||
"updateSuccess": "{group}-Einstellungen erfolgreich aktualisiert"
|
||||
"updateSuccess": "{group}-Einstellungen erfolgreich aktualisiert",
|
||||
"smtpTestFailed": "SMTP-Verbindung fehlgeschlagen: {error}",
|
||||
"smtpTestGenericError": "SMTP-Verbindungstest fehlgeschlagen. Bitte überprüfen Sie Ihre Einstellungen und versuchen Sie es erneut.",
|
||||
"smtpTestSuccess": "SMTP-Verbindung erfolgreich! Ihre E-Mail-Konfiguration funktioniert korrekt."
|
||||
},
|
||||
"title": "Einstellungen",
|
||||
"breadcrumb": "Einstellungen",
|
||||
"pageTitle": "Einstellungen",
|
||||
"tooltips": {
|
||||
"oidcScope": "Geben Sie einen Scope ein und drücken Sie Enter zum Hinzufügen",
|
||||
"oidcAdminEmailDomains": "Geben Sie eine Domain ein und drücken Sie Enter zum Hinzufügen"
|
||||
"oidcAdminEmailDomains": "Geben Sie eine Domain ein und drücken Sie Enter zum Hinzufügen",
|
||||
"testSmtp": "Testet die SMTP-Verbindung mit den aktuell im Formular eingegebenen Werten. Um die Änderungen dauerhaft zu machen, denken Sie daran, Ihre Einstellungen nach dem Test zu speichern."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://meineseite.com",
|
||||
|
@@ -465,6 +465,10 @@
|
||||
"title": "Sender Email",
|
||||
"description": "Sender email address"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Test SMTP Connection",
|
||||
"description": "Test if the SMTP configuration is valid"
|
||||
},
|
||||
"maxLoginAttempts": {
|
||||
"title": "Maximum Login Attempts",
|
||||
"description": "Maximum number of login attempts before blocking"
|
||||
@@ -531,7 +535,9 @@
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Save {group}"
|
||||
"save": "Save {group}",
|
||||
"testSmtp": "Test Connection",
|
||||
"testing": "Testing..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Failed to load settings",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "No changes to save",
|
||||
"updateSuccess": "{group} settings updated successfully"
|
||||
"updateSuccess": "{group} settings updated successfully",
|
||||
"smtpTestSuccess": "SMTP connection successful! Your email configuration is working correctly.",
|
||||
"smtpTestFailed": "SMTP connection failed: {error}",
|
||||
"smtpTestGenericError": "Failed to test SMTP connection. Please check your settings and try again."
|
||||
},
|
||||
"title": "Settings",
|
||||
"breadcrumb": "Settings",
|
||||
"pageTitle": "Settings",
|
||||
"tooltips": {
|
||||
"oidcScope": "Enter a scope and press Enter to add",
|
||||
"oidcAdminEmailDomains": "Enter a domain and press Enter to add"
|
||||
"oidcAdminEmailDomains": "Enter a domain and press Enter to add",
|
||||
"testSmtp": "Tests the SMTP connection with the values currently entered in the form. To make changes permanent, remember to save your settings after testing."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mysite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Dominios de Correo Admin",
|
||||
"description": "Dominios de correo que reciben privilegios de administrador automáticamente"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Probar Conexión SMTP",
|
||||
"description": "Probar si la configuración SMTP es válida"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Guardar {group}"
|
||||
"save": "Guardar {group}",
|
||||
"testSmtp": "Probar Conexión",
|
||||
"testing": "Probando..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Error al cargar la configuración",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "No hay cambios para guardar",
|
||||
"updateSuccess": "Configuración de {group} actualizada exitosamente"
|
||||
"updateSuccess": "Configuración de {group} actualizada exitosamente",
|
||||
"smtpTestSuccess": "¡Conexión SMTP exitosa! Tu configuración de correo funciona correctamente.",
|
||||
"smtpTestFailed": "Falló la conexión SMTP: {error}",
|
||||
"smtpTestGenericError": "Error al probar la conexión SMTP. Por favor revisa tu configuración e inténtalo de nuevo."
|
||||
},
|
||||
"title": "Configuración",
|
||||
"breadcrumb": "Configuración",
|
||||
"pageTitle": "Configuración",
|
||||
"tooltips": {
|
||||
"oidcScope": "Ingrese un ámbito y presione Enter para agregar",
|
||||
"oidcAdminEmailDomains": "Ingrese un dominio y presione Enter para agregar"
|
||||
"oidcAdminEmailDomains": "Ingrese un dominio y presione Enter para agregar",
|
||||
"testSmtp": "Prueba la conexión SMTP con los valores actualmente ingresados en el formulario. Para hacer los cambios permanentes, recuerda guardar la configuración después de probar."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://misitio.com",
|
||||
|
@@ -531,10 +531,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Domaines Email Admin",
|
||||
"description": "Domaines email qui reçoivent automatiquement les privilèges d'administrateur"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "[TO_TRANSLATE] Test SMTP Connection",
|
||||
"description": "[TO_TRANSLATE] Test if the SMTP configuration is valid"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Enregistrer {group}"
|
||||
"save": "Enregistrer {group}",
|
||||
"testSmtp": "Tester la Connexion",
|
||||
"testing": "Test en cours..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Échec du chargement des paramètres",
|
||||
@@ -542,11 +548,15 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Aucun changement à enregistrer",
|
||||
"updateSuccess": "Paramètres {group} mis à jour avec succès"
|
||||
"updateSuccess": "Paramètres {group} mis à jour avec succès",
|
||||
"smtpTestFailed": "La connexion SMTP a échoué : {error}",
|
||||
"smtpTestGenericError": "Échec du test de connexion SMTP. Veuillez vérifier vos paramètres et réessayer.",
|
||||
"smtpTestSuccess": "Connexion SMTP réussie ! Votre configuration email fonctionne correctement."
|
||||
},
|
||||
"tooltips": {
|
||||
"oidcScope": "Entrez une portée et appuyez sur Entrée pour l'ajouter",
|
||||
"oidcAdminEmailDomains": "Entrez un domaine et appuyez sur Entrée pour l'ajouter"
|
||||
"oidcAdminEmailDomains": "Entrez un domaine et appuyez sur Entrée pour l'ajouter",
|
||||
"testSmtp": "Teste la connexion SMTP avec les valeurs actuellement saisies dans le formulaire. Pour rendre les modifications permanentes, n'oubliez pas d'enregistrer vos paramètres après le test."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://monsite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "एडमिन ईमेल डोमेन",
|
||||
"description": "जिन ईमेल डोमेन को स्वचालित रूप से व्यवस्थापक विशेषाधिकार प्राप्त होंगे"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "SMTP कनेक्शन का परीक्षण करें",
|
||||
"description": "जांचें कि SMTP कॉन्फ़िगरेशन मान्य है"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "{group} सहेजें"
|
||||
"save": "{group} सहेजें",
|
||||
"testSmtp": "कनेक्शन का परीक्षण करें",
|
||||
"testing": "परीक्षण किया जा रहा है..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "सेटिंग्स लोड करने में विफल",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "सहेजने के लिए कोई परिवर्तन नहीं",
|
||||
"updateSuccess": "{group} सेटिंग्स सफलतापूर्वक अपडेट हुईं"
|
||||
"updateSuccess": "{group} सेटिंग्स सफलतापूर्वक अपडेट हुईं",
|
||||
"smtpTestFailed": "SMTP कनेक्शन विफल: {error}",
|
||||
"smtpTestGenericError": "SMTP कनेक्शन का परीक्षण करने में विफल। कृपया अपनी सेटिंग्स जांचें और पुनः प्रयास करें।",
|
||||
"smtpTestSuccess": "SMTP कनेक्शन सफल! आपका ईमेल कॉन्फ़िगरेशन सही ढंग से काम कर रहा है।"
|
||||
},
|
||||
"title": "सेटिंग्स",
|
||||
"breadcrumb": "सेटिंग्स",
|
||||
"pageTitle": "सेटिंग्स",
|
||||
"tooltips": {
|
||||
"oidcScope": "स्कोप जोड़ने के लिए एक स्कोप दर्ज करें और Enter दबाएं",
|
||||
"oidcAdminEmailDomains": "डोमेन जोड़ने के लिए एक डोमेन दर्ज करें और Enter दबाएं"
|
||||
"oidcAdminEmailDomains": "डोमेन जोड़ने के लिए एक डोमेन दर्ज करें और Enter दबाएं",
|
||||
"testSmtp": "फॉर्म में वर्तमान में दर्ज मानों के साथ SMTP कनेक्शन का परीक्षण करता है। परिवर्तनों को स्थायी बनाने के लिए, परीक्षण के बाद अपनी सेटिंग्स को सहेजना याद रखें।"
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mysite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Domini Email Admin",
|
||||
"description": "Domini email che ricevono automaticamente i privilegi di amministratore"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Test Connessione SMTP",
|
||||
"description": "Verifica se la configurazione SMTP è valida"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Salva {group}"
|
||||
"save": "Salva {group}",
|
||||
"testSmtp": "Prova Connessione",
|
||||
"testing": "Verifica in corso..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Errore durante il caricamento delle impostazioni",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Nessuna modifica da salvare",
|
||||
"updateSuccess": "Impostazioni {group} aggiornate con successo"
|
||||
"updateSuccess": "Impostazioni {group} aggiornate con successo",
|
||||
"smtpTestFailed": "Connessione SMTP fallita: {error}",
|
||||
"smtpTestGenericError": "Impossibile testare la connessione SMTP. Controlla le impostazioni e riprova.",
|
||||
"smtpTestSuccess": "Connessione SMTP riuscita! La configurazione email funziona correttamente."
|
||||
},
|
||||
"title": "Impostazioni",
|
||||
"breadcrumb": "Impostazioni",
|
||||
"pageTitle": "Impostazioni",
|
||||
"tooltips": {
|
||||
"oidcScope": "Inserisci uno scope e premi Invio per aggiungerlo",
|
||||
"oidcAdminEmailDomains": "Inserisci un dominio e premi Invio per aggiungerlo"
|
||||
"oidcAdminEmailDomains": "Inserisci un dominio e premi Invio per aggiungerlo",
|
||||
"testSmtp": "Verifica la connessione SMTP con i valori attualmente inseriti nel modulo. Per rendere permanenti le modifiche, ricordati di salvare le impostazioni dopo il test."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://miosito.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "管理者メールドメイン",
|
||||
"description": "自動的に管理者権限が付与されるメールドメイン"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "SMTP接続テスト",
|
||||
"description": "SMTP設定が有効かどうかをテストします"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "{group}を保存"
|
||||
"save": "{group}を保存",
|
||||
"testSmtp": "接続テスト",
|
||||
"testing": "テスト中..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "設定の読み込みに失敗しました",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "保存する変更はありません",
|
||||
"updateSuccess": "{group}の設定が正常に更新されました"
|
||||
"updateSuccess": "{group}の設定が正常に更新されました",
|
||||
"smtpTestFailed": "SMTP接続に失敗しました: {error}",
|
||||
"smtpTestGenericError": "SMTP接続のテストに失敗しました。設定を確認して再度お試しください。",
|
||||
"smtpTestSuccess": "SMTP接続に成功しました!メール設定は正常に動作しています。"
|
||||
},
|
||||
"title": "設定",
|
||||
"breadcrumb": "設定",
|
||||
"pageTitle": "設定",
|
||||
"tooltips": {
|
||||
"oidcScope": "スコープを入力してEnterキーを押して追加",
|
||||
"oidcAdminEmailDomains": "ドメインを入力してEnterキーを押して追加"
|
||||
"oidcAdminEmailDomains": "ドメインを入力してEnterキーを押して追加",
|
||||
"testSmtp": "フォームに現在入力されている値でSMTP接続をテストします。変更を永続化するには、テスト後に設定を保存することを忘れないでください。"
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mysite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "관리자 이메일 도메인",
|
||||
"description": "자동으로 관리자 권한이 부여되는 이메일 도메인"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "SMTP 연결 테스트",
|
||||
"description": "SMTP 구성이 유효한지 테스트합니다"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "{group} 저장"
|
||||
"save": "{group} 저장",
|
||||
"testSmtp": "연결 테스트",
|
||||
"testing": "테스트 중..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "설정을 불러오는데 실패했습니다",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "저장할 변경 사항이 없습니다",
|
||||
"updateSuccess": "{group} 설정이 성공적으로 업데이트되었습니다"
|
||||
"updateSuccess": "{group} 설정이 성공적으로 업데이트되었습니다",
|
||||
"smtpTestFailed": "SMTP 연결 실패: {error}",
|
||||
"smtpTestGenericError": "SMTP 연결 테스트에 실패했습니다. 설정을 확인하고 다시 시도해주세요.",
|
||||
"smtpTestSuccess": "SMTP 연결 성공! 이메일 구성이 올바르게 작동합니다."
|
||||
},
|
||||
"title": "설정",
|
||||
"breadcrumb": "설정",
|
||||
"pageTitle": "설정",
|
||||
"tooltips": {
|
||||
"oidcScope": "스코프를 입력하고 Enter 키를 눌러 추가",
|
||||
"oidcAdminEmailDomains": "도메인을 입력하고 Enter 키를 눌러 추가"
|
||||
"oidcAdminEmailDomains": "도메인을 입력하고 Enter 키를 눌러 추가",
|
||||
"testSmtp": "현재 입력된 값으로 SMTP 연결을 테스트합니다. 변경 사항을 영구적으로 적용하려면 테스트 후 설정을 저장하는 것을 잊지 마세요."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mysite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Admin E-mail Domeinen",
|
||||
"description": "E-mail domeinen die automatisch admin rechten krijgen"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Test SMTP Verbinding",
|
||||
"description": "Test of de SMTP configuratie geldig is"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "{group} Opslaan"
|
||||
"save": "{group} Opslaan",
|
||||
"testSmtp": "Test Verbinding",
|
||||
"testing": "Testen..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Fout bij het laden van instellingen",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Geen wijzigingen om op te slaan",
|
||||
"updateSuccess": "{group} instellingen succesvol bijgewerkt"
|
||||
"updateSuccess": "{group} instellingen succesvol bijgewerkt",
|
||||
"smtpTestFailed": "SMTP verbinding mislukt: {error}",
|
||||
"smtpTestGenericError": "SMTP verbinding testen mislukt. Controleer uw instellingen en probeer het opnieuw.",
|
||||
"smtpTestSuccess": "SMTP verbinding succesvol! Uw e-mailconfiguratie werkt correct."
|
||||
},
|
||||
"title": "Instellingen",
|
||||
"breadcrumb": "Instellingen",
|
||||
"pageTitle": "Instellingen",
|
||||
"tooltips": {
|
||||
"oidcScope": "Voer een scope in en druk op Enter om toe te voegen",
|
||||
"oidcAdminEmailDomains": "Voer een domein in en druk op Enter om toe te voegen"
|
||||
"oidcAdminEmailDomains": "Voer een domein in en druk op Enter om toe te voegen",
|
||||
"testSmtp": "Test de SMTP verbinding met de waarden die momenteel in het formulier zijn ingevoerd. Om wijzigingen permanent te maken, vergeet niet om uw instellingen op te slaan na het testen."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mijnsite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Domeny e-mail administratora",
|
||||
"description": "Domeny e-mail, które automatycznie otrzymują uprawnienia administratora"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Test połączenia SMTP",
|
||||
"description": "Sprawdź, czy konfiguracja SMTP jest prawidłowa"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Zapisz {group}"
|
||||
"save": "Zapisz {group}",
|
||||
"testSmtp": "Testuj połączenie",
|
||||
"testing": "Testowanie..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Nie udało się załadować ustawień",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Brak zmian do zapisania",
|
||||
"updateSuccess": "Ustawienia {group} zaktualizowane pomyślnie"
|
||||
"updateSuccess": "Ustawienia {group} zaktualizowane pomyślnie",
|
||||
"smtpTestFailed": "Połączenie SMTP nie powiodło się: {error}",
|
||||
"smtpTestGenericError": "Nie udało się przetestować połączenia SMTP. Sprawdź ustawienia i spróbuj ponownie.",
|
||||
"smtpTestSuccess": "Połączenie SMTP udane! Twoja konfiguracja poczty e-mail działa poprawnie."
|
||||
},
|
||||
"title": "Ustawienia",
|
||||
"breadcrumb": "Ustawienia",
|
||||
"pageTitle": "Ustawienia",
|
||||
"tooltips": {
|
||||
"oidcScope": "Wprowadź zakres i naciśnij Enter, aby dodać",
|
||||
"oidcAdminEmailDomains": "Wprowadź domenę i naciśnij Enter, aby dodać"
|
||||
"oidcAdminEmailDomains": "Wprowadź domenę i naciśnij Enter, aby dodać",
|
||||
"testSmtp": "Testuje połączenie SMTP z obecnie wprowadzonymi wartościami w formularzu. Aby wprowadzić trwałe zmiany, pamiętaj o zapisaniu ustawień po testowaniu."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://mysite.com",
|
||||
|
@@ -443,7 +443,8 @@
|
||||
},
|
||||
"tooltips": {
|
||||
"oidcScope": "Digite um escopo e pressione Enter para adicionar",
|
||||
"oidcAdminEmailDomains": "Digite um domínio e pressione Enter para adicionar"
|
||||
"oidcAdminEmailDomains": "Digite um domínio e pressione Enter para adicionar",
|
||||
"testSmtp": "Testa a conexão SMTP com os valores atualmente inseridos no formulário. Para tornar as alterações permanentes, lembre-se de salvar suas configurações após o teste."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://meusite.com",
|
||||
@@ -558,10 +559,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Domínios de E-mail Admin",
|
||||
"description": "Domínios de e-mail que recebem privilégios de administrador automaticamente"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Testar Conexão SMTP",
|
||||
"description": "Testa se a configuração SMTP é válida"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Salvar {group}"
|
||||
"save": "Salvar {group}",
|
||||
"testSmtp": "Testar Conexão",
|
||||
"testing": "Testando..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Falha ao carregar configurações",
|
||||
@@ -569,7 +576,10 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Nenhuma alteração para salvar",
|
||||
"updateSuccess": "Configurações de {group} atualizadas com sucesso"
|
||||
"updateSuccess": "Configurações de {group} atualizadas com sucesso",
|
||||
"smtpTestFailed": "Falha na conexão SMTP: {error}",
|
||||
"smtpTestGenericError": "Falha ao testar conexão SMTP. Por favor, verifique suas configurações e tente novamente.",
|
||||
"smtpTestSuccess": "Conexão SMTP bem-sucedida! Sua configuração de e-mail está funcionando corretamente."
|
||||
},
|
||||
"title": "Configurações",
|
||||
"breadcrumb": "Configurações",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Домены Email Администратора",
|
||||
"description": "Домены электронной почты, которые автоматически получают права администратора"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "Проверить SMTP-соединение",
|
||||
"description": "Проверить правильность настройки SMTP"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "Сохранить {group}"
|
||||
"save": "Сохранить {group}",
|
||||
"testSmtp": "Проверить соединение",
|
||||
"testing": "Проверка..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Ошибка загрузки настроек",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Изменений для сохранения нет",
|
||||
"updateSuccess": "Настройки {group} успешно обновлены"
|
||||
"updateSuccess": "Настройки {group} успешно обновлены",
|
||||
"smtpTestFailed": "Ошибка SMTP-соединения: {error}",
|
||||
"smtpTestGenericError": "Не удалось проверить SMTP-соединение. Пожалуйста, проверьте настройки и попробуйте снова.",
|
||||
"smtpTestSuccess": "SMTP-соединение успешно установлено! Ваша конфигурация электронной почты работает корректно."
|
||||
},
|
||||
"title": "Настройки",
|
||||
"breadcrumb": "Настройки",
|
||||
"pageTitle": "Настройки",
|
||||
"tooltips": {
|
||||
"oidcScope": "Digite um escopo e pressione Enter para adicionar",
|
||||
"oidcAdminEmailDomains": "Digite um domínio e pressione Enter para adicionar"
|
||||
"oidcAdminEmailDomains": "Digite um domínio e pressione Enter para adicionar",
|
||||
"testSmtp": "Проверяет SMTP-соединение с текущими значениями в форме. Чтобы сохранить изменения, не забудьте сохранить настройки после тестирования."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://meusite.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "Yönetici E-posta Alanları",
|
||||
"description": "Otomatik olarak yönetici ayrıcalıkları alan e-posta alanları"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "SMTP Bağlantısını Test Et",
|
||||
"description": "SMTP yapılandırmasının geçerli olup olmadığını test et"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "{group} Kaydet"
|
||||
"save": "{group} Kaydet",
|
||||
"testSmtp": "Bağlantıyı Test Et",
|
||||
"testing": "Test Ediliyor..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Ayarlar yüklenemedi",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "Kaydedilecek değişiklik yok",
|
||||
"updateSuccess": "{group} ayarları başarıyla güncellendi"
|
||||
"updateSuccess": "{group} ayarları başarıyla güncellendi",
|
||||
"smtpTestFailed": "SMTP bağlantısı başarısız: {error}",
|
||||
"smtpTestGenericError": "SMTP bağlantısı test edilemedi. Lütfen ayarlarınızı kontrol edin ve tekrar deneyin.",
|
||||
"smtpTestSuccess": "SMTP bağlantısı başarılı! E-posta yapılandırmanız doğru çalışıyor."
|
||||
},
|
||||
"title": "Ayarlar",
|
||||
"breadcrumb": "Ayarlar",
|
||||
"pageTitle": "Ayarlar",
|
||||
"tooltips": {
|
||||
"oidcScope": "Bir kapsam girin ve eklemek için Enter'a basın",
|
||||
"oidcAdminEmailDomains": "Bir alan girin ve eklemek için Enter'a basın"
|
||||
"oidcAdminEmailDomains": "Bir alan girin ve eklemek için Enter'a basın",
|
||||
"testSmtp": "Formda şu anda girilen değerlerle SMTP bağlantısını test eder. Değişiklikleri kalıcı yapmak için test ettikten sonra ayarlarınızı kaydetmeyi unutmayın."
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://sitem.com",
|
||||
|
@@ -528,10 +528,16 @@
|
||||
"oidcAdminEmailDomains": {
|
||||
"title": "管理员电子邮件域名",
|
||||
"description": "自动获得管理员权限的电子邮件域名"
|
||||
},
|
||||
"testSmtp": {
|
||||
"title": "测试SMTP连接",
|
||||
"description": "测试SMTP配置是否有效"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"save": "保存 {group}"
|
||||
"save": "保存 {group}",
|
||||
"testSmtp": "测试连接",
|
||||
"testing": "测试中..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "加载设置失败",
|
||||
@@ -539,14 +545,18 @@
|
||||
},
|
||||
"messages": {
|
||||
"noChanges": "没有需要保存的更改",
|
||||
"updateSuccess": "{group}设置更新成功"
|
||||
"updateSuccess": "{group}设置更新成功",
|
||||
"smtpTestFailed": "SMTP连接失败:{error}",
|
||||
"smtpTestGenericError": "SMTP连接测试失败。请检查您的设置并重试。",
|
||||
"smtpTestSuccess": "SMTP连接成功!您的电子邮件配置工作正常。"
|
||||
},
|
||||
"title": "设置",
|
||||
"breadcrumb": "设置",
|
||||
"pageTitle": "设置",
|
||||
"tooltips": {
|
||||
"oidcScope": "Digite um escopo e pressione Enter para adicionar",
|
||||
"oidcAdminEmailDomains": "Digite um domínio e pressione Enter para adicionar"
|
||||
"oidcAdminEmailDomains": "Digite um domínio e pressione Enter para adicionar",
|
||||
"testSmtp": "使用当前在表单中输入的值测试SMTP连接。要使更改永久生效,请记得在测试后保存您的设置。"
|
||||
},
|
||||
"redirectUri": {
|
||||
"placeholder": "https://meusite.com",
|
||||
|
31
apps/web/src/app/api/(proxy)/app/test-smtp/route.ts
Normal file
31
apps/web/src/app/api/(proxy)/app/test-smtp/route.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const cookieHeader = req.headers.get("cookie");
|
||||
const body = await req.text();
|
||||
|
||||
const apiRes = await fetch(`${process.env.API_BASE_URL}/app/test-smtp`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
cookie: cookieHeader || "",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: body || "{}",
|
||||
redirect: "manual",
|
||||
});
|
||||
|
||||
const resBody = await apiRes.text();
|
||||
const res = new NextResponse(resBody, {
|
||||
status: apiRes.status,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const setCookie = apiRes.headers.getSetCookie?.() || [];
|
||||
if (setCookie.length > 0) {
|
||||
res.headers.set("Set-Cookie", setCookie.join(","));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
@@ -8,6 +8,7 @@ import { Separator } from "@/components/ui/separator";
|
||||
import { createFieldDescriptions, createGroupMetadata } from "../constants";
|
||||
import { SettingsGroupProps } from "../types";
|
||||
import { isFieldHidden, SettingsInput } from "./settings-input";
|
||||
import { SmtpTestButton } from "./smtp-test-button";
|
||||
|
||||
export function SettingsGroup({ group, configs, form, isCollapsed, onToggleCollapse, onSubmit }: SettingsGroupProps) {
|
||||
const t = useTranslations();
|
||||
@@ -19,6 +20,8 @@ export function SettingsGroup({ group, configs, form, isCollapsed, onToggleColla
|
||||
description: t("settings.groups.defaultDescription"),
|
||||
};
|
||||
|
||||
const isEmailGroup = group === "email";
|
||||
|
||||
return (
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<Card className="p-6 gap-0">
|
||||
@@ -70,18 +73,32 @@ export function SettingsGroup({ group, configs, form, isCollapsed, onToggleColla
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-end mt-4">
|
||||
<Button
|
||||
variant="default"
|
||||
disabled={form.formState.isSubmitting}
|
||||
className="flex items-center gap-2"
|
||||
type="submit"
|
||||
>
|
||||
{!form.formState.isSubmitting && <IconDeviceFloppy className="h-4 w-4" />}
|
||||
{t("settings.buttons.save", {
|
||||
group: t(`settings.groups.${group}.title`, { defaultValue: metadata.title }),
|
||||
})}
|
||||
</Button>
|
||||
<div className="flex justify-between items-center mt-4">
|
||||
{isEmailGroup && (
|
||||
<SmtpTestButton
|
||||
smtpEnabled={form.watch("configs.smtpEnabled") || "false"}
|
||||
getFormValues={() => ({
|
||||
smtpEnabled: form.getValues("configs.smtpEnabled") || "false",
|
||||
smtpHost: form.getValues("configs.smtpHost") || "",
|
||||
smtpPort: form.getValues("configs.smtpPort") || "",
|
||||
smtpUser: form.getValues("configs.smtpUser") || "",
|
||||
smtpPass: form.getValues("configs.smtpPass") || "",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<div className={`flex ${isEmailGroup ? "ml-auto" : ""}`}>
|
||||
<Button
|
||||
variant="default"
|
||||
disabled={form.formState.isSubmitting}
|
||||
className="flex items-center gap-2"
|
||||
type="submit"
|
||||
>
|
||||
{!form.formState.isSubmitting && <IconDeviceFloppy className="h-4 w-4" />}
|
||||
{t("settings.buttons.save", {
|
||||
group: t(`settings.groups.${group}.title`, { defaultValue: metadata.title }),
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
86
apps/web/src/app/settings/components/smtp-test-button.tsx
Normal file
86
apps/web/src/app/settings/components/smtp-test-button.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { IconFlask, IconInfoCircle, IconLoader } from "@tabler/icons-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { testSmtpConnection } from "@/http/endpoints/app";
|
||||
|
||||
interface SmtpTestButtonProps {
|
||||
smtpEnabled: string;
|
||||
getFormValues: () => {
|
||||
smtpEnabled: string;
|
||||
smtpHost: string;
|
||||
smtpPort: string;
|
||||
smtpUser: string;
|
||||
smtpPass: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function SmtpTestButton({ smtpEnabled, getFormValues }: SmtpTestButtonProps) {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const t = useTranslations();
|
||||
|
||||
const handleTestConnection = async () => {
|
||||
const formValues = getFormValues();
|
||||
|
||||
if (formValues.smtpEnabled !== "true") {
|
||||
toast.error("SMTP is not enabled. Please enable SMTP first.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if required fields are filled
|
||||
if (!formValues.smtpHost || !formValues.smtpPort || !formValues.smtpUser || !formValues.smtpPass) {
|
||||
toast.error("Please fill in all SMTP configuration fields before testing.");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await testSmtpConnection({
|
||||
smtpConfig: {
|
||||
smtpEnabled: formValues.smtpEnabled,
|
||||
smtpHost: formValues.smtpHost,
|
||||
smtpPort: formValues.smtpPort,
|
||||
smtpUser: formValues.smtpUser,
|
||||
smtpPass: formValues.smtpPass,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
toast.success(t("settings.messages.smtpTestSuccess"));
|
||||
} else {
|
||||
toast.error(t("settings.messages.smtpTestGenericError"));
|
||||
}
|
||||
} catch (error: any) {
|
||||
const errorMessage = error?.response?.data?.error || error?.message || "Unknown error";
|
||||
toast.error(t("settings.messages.smtpTestFailed", { error: errorMessage }));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={handleTestConnection}
|
||||
disabled={isLoading || smtpEnabled !== "true"}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
{isLoading ? <IconLoader className="h-4 w-4 animate-spin" /> : <IconFlask className="h-4 w-4" />}
|
||||
{isLoading ? t("settings.buttons.testing") : t("settings.buttons.testSmtp")}
|
||||
</Button>
|
||||
<div className="relative group">
|
||||
<IconInfoCircle className="h-4 w-4 text-muted-foreground hover:text-foreground cursor-help transition-colors" />
|
||||
<div className="absolute left-1/2 -translate-x-1/2 bottom-full mb-2 px-3 py-2 bg-popover text-popover-foreground text-xs rounded-md border shadow-md opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-50 w-72 text-wrap">
|
||||
{t("settings.tooltips.testSmtp")}
|
||||
<div className="absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-popover"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@@ -80,3 +80,22 @@ export const checkUploadAllowed = <TData = CheckUploadAllowedResult>(
|
||||
params: { ...params, ...options?.params },
|
||||
});
|
||||
};
|
||||
|
||||
export type TestSmtpConnectionResult = { success: boolean; message: string };
|
||||
|
||||
export interface TestSmtpConnectionBody {
|
||||
smtpConfig?: {
|
||||
smtpEnabled: string;
|
||||
smtpHost: string;
|
||||
smtpPort: string;
|
||||
smtpUser: string;
|
||||
smtpPass: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const testSmtpConnection = (
|
||||
body?: TestSmtpConnectionBody,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<{ data: TestSmtpConnectionResult }> => {
|
||||
return apiInstance.post(`/api/app/test-smtp`, body || {}, options);
|
||||
};
|
||||
|
Reference in New Issue
Block a user