112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
import nodemailer from 'nodemailer'
|
|
import { prisma } from './db'
|
|
|
|
export interface SmtpConfig {
|
|
host: string
|
|
port: number
|
|
secure: boolean
|
|
user: string
|
|
pass: string
|
|
fromName: string
|
|
fromEmail: string
|
|
}
|
|
|
|
// Get SMTP settings from DB (SystemSetting table)
|
|
export async function getSmtpConfig(): Promise<SmtpConfig | null> {
|
|
try {
|
|
const settings = await (prisma as any).systemSetting.findMany({
|
|
where: { category: 'smtp' },
|
|
})
|
|
if (!settings || settings.length === 0) return null
|
|
|
|
const map: Record<string, string> = {}
|
|
for (const s of settings) {
|
|
map[s.key] = s.value
|
|
}
|
|
|
|
if (!map['smtp_host'] || !map['smtp_user']) return null
|
|
|
|
return {
|
|
host: map['smtp_host'],
|
|
port: parseInt(map['smtp_port'] || '587'),
|
|
secure: map['smtp_secure'] === 'true',
|
|
user: map['smtp_user'],
|
|
pass: map['smtp_pass'] || '',
|
|
fromName: map['smtp_from_name'] || 'Lageplan',
|
|
fromEmail: map['smtp_from_email'] || map['smtp_user'],
|
|
}
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
// Save SMTP settings to DB
|
|
export async function saveSmtpConfig(config: Partial<SmtpConfig>): Promise<void> {
|
|
const entries: { key: string; value: string; isSecret: boolean }[] = []
|
|
if (config.host !== undefined) entries.push({ key: 'smtp_host', value: config.host, isSecret: false })
|
|
if (config.port !== undefined) entries.push({ key: 'smtp_port', value: String(config.port), isSecret: false })
|
|
if (config.secure !== undefined) entries.push({ key: 'smtp_secure', value: String(config.secure), isSecret: false })
|
|
if (config.user !== undefined) entries.push({ key: 'smtp_user', value: config.user, isSecret: false })
|
|
if (config.pass !== undefined) entries.push({ key: 'smtp_pass', value: config.pass, isSecret: true })
|
|
if (config.fromName !== undefined) entries.push({ key: 'smtp_from_name', value: config.fromName, isSecret: false })
|
|
if (config.fromEmail !== undefined) entries.push({ key: 'smtp_from_email', value: config.fromEmail, isSecret: false })
|
|
|
|
for (const entry of entries) {
|
|
await (prisma as any).systemSetting.upsert({
|
|
where: { key: entry.key },
|
|
update: { value: entry.value, isSecret: entry.isSecret },
|
|
create: { key: entry.key, value: entry.value, isSecret: entry.isSecret, category: 'smtp' },
|
|
})
|
|
}
|
|
}
|
|
|
|
// Create nodemailer transport from DB settings
|
|
async function createTransport() {
|
|
const config = await getSmtpConfig()
|
|
if (!config) throw new Error('SMTP nicht konfiguriert')
|
|
|
|
return nodemailer.createTransport({
|
|
host: config.host,
|
|
port: config.port,
|
|
secure: config.secure,
|
|
auth: {
|
|
user: config.user,
|
|
pass: config.pass,
|
|
},
|
|
tls: {
|
|
rejectUnauthorized: false,
|
|
},
|
|
})
|
|
}
|
|
|
|
// Send email
|
|
export async function sendEmail(to: string, subject: string, html: string): Promise<boolean> {
|
|
try {
|
|
const config = await getSmtpConfig()
|
|
if (!config) throw new Error('SMTP nicht konfiguriert')
|
|
const transport = await createTransport()
|
|
|
|
await transport.sendMail({
|
|
from: `"${config.fromName}" <${config.fromEmail}>`,
|
|
to,
|
|
subject,
|
|
html,
|
|
})
|
|
return true
|
|
} catch (error) {
|
|
console.error('Email send error:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// Test SMTP connection
|
|
export async function testSmtpConnection(): Promise<{ success: boolean; error?: string }> {
|
|
try {
|
|
const transport = await createTransport()
|
|
await transport.verify()
|
|
return { success: true }
|
|
} catch (error) {
|
|
return { success: false, error: error instanceof Error ? error.message : 'Verbindung fehlgeschlagen' }
|
|
}
|
|
}
|