feat: add debug logging for SMTP configuration and detailed mail delivery status
Build and Push Multi-Platform Images / build-and-push (push) Failing after 34s

This commit is contained in:
2026-05-06 19:48:29 +02:00
parent 443ab765c9
commit a000e0f5c6
16 changed files with 431 additions and 5 deletions
@@ -0,0 +1,107 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as nodemailer from 'nodemailer';
import { UserSettings } from '../database/entities/user-settings.entity';
export interface UserSettingsDto {
smtpHost: string | null;
smtpPort: number | null;
smtpSecure: boolean;
smtpUser: string | null;
smtpPassSet: boolean;
smtpFrom: string | null;
mailSignatureHtml: string | null;
}
@Injectable()
export class UserSettingsService {
constructor(
@InjectRepository(UserSettings)
private readonly repo: Repository<UserSettings>,
) {}
async getSettings(userId: string): Promise<UserSettingsDto> {
const entity = await this.repo.findOne({ where: { UserId: userId } });
return this.toDto(entity);
}
async updateSettings(
userId: string,
data: {
smtpHost?: string | null;
smtpPort?: number | null;
smtpSecure?: boolean;
smtpUser?: string | null;
smtpPass?: string | null;
smtpFrom?: string | null;
mailSignatureHtml?: string | null;
},
): Promise<UserSettingsDto> {
let entity = await this.repo.findOne({ where: { UserId: userId } });
if (!entity) {
entity = this.repo.create({ UserId: userId });
}
if (data.smtpHost !== undefined) entity.SmtpHost = data.smtpHost;
if (data.smtpPort !== undefined) entity.SmtpPort = data.smtpPort;
if (data.smtpSecure !== undefined) entity.SmtpSecure = data.smtpSecure;
if (data.smtpUser !== undefined) entity.SmtpUser = data.smtpUser;
if (data.smtpPass !== undefined && data.smtpPass !== null && data.smtpPass !== '') {
entity.SmtpPass = data.smtpPass;
}
if (data.smtpFrom !== undefined) entity.SmtpFrom = data.smtpFrom;
if (data.mailSignatureHtml !== undefined) entity.MailSignatureHtml = data.mailSignatureHtml;
await this.repo.save(entity);
return this.toDto(entity);
}
async testSmtp(config: {
host: string;
port: number;
secure: boolean;
user: string;
pass: string;
}): Promise<{ ok: boolean; error?: string }> {
const transporter = nodemailer.createTransport({
host: config.host,
port: config.port,
secure: config.secure,
auth: { user: config.user, pass: config.pass },
});
try {
await transporter.verify();
return { ok: true };
} catch (err: any) {
return { ok: false, error: err.message };
}
}
async getSmtpConfig(userId: string): Promise<{
host: string; port: number; secure: boolean; user: string; pass: string; from: string;
} | null> {
const entity = await this.repo.findOne({ where: { UserId: userId } });
if (!entity?.SmtpHost || !entity?.SmtpPass) return null;
return {
host: entity.SmtpHost,
port: entity.SmtpPort ?? 587,
secure: entity.SmtpSecure,
user: entity.SmtpUser ?? '',
pass: entity.SmtpPass,
from: entity.SmtpFrom ?? entity.SmtpUser ?? '',
};
}
private toDto(entity: UserSettings | null): UserSettingsDto {
return {
smtpHost: entity?.SmtpHost ?? null,
smtpPort: entity?.SmtpPort ?? null,
smtpSecure: entity?.SmtpSecure ?? false,
smtpUser: entity?.SmtpUser ?? null,
smtpPassSet: !!(entity?.SmtpPass),
smtpFrom: entity?.SmtpFrom ?? null,
mailSignatureHtml: entity?.MailSignatureHtml ?? null,
};
}
}