add mail type and validation

This commit is contained in:
Julian Krauser 2025-04-25 12:13:26 +02:00
parent 2e3d0a755c
commit ce9f621b8b
11 changed files with 193 additions and 19 deletions

View file

@ -60,6 +60,41 @@ export abstract class MsTypeConverter extends TypeConverter<ms.StringValue> {
}
}
export abstract class EmailTypeConverter extends TypeConverter<string> {
fromString(value: string): string {
return value;
}
toString(value: string): string {
return value;
}
validate(value: string): boolean {
var tester =
/^[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~](\.?[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~])*@[a-zA-Z0-9](-*\.?[a-zA-Z0-9])*\.[a-zA-Z](-?[a-zA-Z0-9])+$/;
if (!value) return false;
var emailParts = value.split("@");
if (emailParts.length !== 2) return false;
var account = emailParts[0];
var address = emailParts[1];
if (account.length > 64) return false;
else if (address.length > 255) return false;
var domainParts = address.split(".");
if (
domainParts.some(function (part) {
return part.length > 63;
})
)
return false;
return tester.test(value);
}
}
// Konkrete Implementierungen der Converter
export class StringConverter extends StringTypeConverter {}
export class LongStringConverter extends StringTypeConverter {}
@ -67,3 +102,4 @@ export class UrlConverter extends StringTypeConverter {}
export class NumberConverter extends NumberTypeConverter {}
export class BooleanConverter extends BooleanTypeConverter {}
export class MsConverter extends MsTypeConverter {}
export class EmailConverter extends EmailTypeConverter {}

View file

@ -1,6 +1,7 @@
import { Transporter, createTransport, TransportOptions } from "nodemailer";
import { Attachment } from "nodemailer/lib/mailer";
import SettingHelper from "./settingsHelper";
import emailCheck from "email-check";
export default abstract class MailHelper {
private static transporter: Transporter;
@ -19,6 +20,51 @@ export default abstract class MailHelper {
} as TransportOptions);
}
static async verifyTransport({
host,
port,
secure,
user,
password,
}: {
host: string;
port: number;
secure: boolean;
user: string;
password: string;
}): Promise<boolean> {
let transport = createTransport({
host,
port,
secure,
auth: { user, pass: password },
});
return await transport
.verify()
.then(() => {
return true;
})
.catch(() => {
return false;
})
.finally(() => {
try {
transport?.close();
} catch (error) {}
});
}
static async checkMail(mail: string): Promise<boolean> {
return await emailCheck(mail)
.then((res) => {
return res;
})
.catch((err) => {
return false;
});
}
static initialize() {
SettingHelper.onSettingTopicChanged("mail", () => {
this.createTransport();
@ -42,7 +88,7 @@ export default abstract class MailHelper {
return new Promise((resolve, reject) => {
this.transporter
.sendMail({
from: `"${SettingHelper.getSetting("club.name")}" <${SettingHelper.getSetting("mail.username")}>`,
from: `"${SettingHelper.getSetting("club.name")}" <${SettingHelper.getSetting("mail.email")}>`,
to: target,
subject,
text: content,

View file

@ -5,6 +5,7 @@ import SettingService from "../service/management/settingService";
import { APPLICATION_SECRET } from "../env.defaults";
import {
BooleanConverter,
EmailConverter,
LongStringConverter,
MsConverter,
NumberConverter,
@ -27,6 +28,7 @@ export default abstract class SettingHelper {
number: new NumberConverter(),
boolean: new BooleanConverter(),
ms: new MsConverter(),
email: new EmailConverter(),
};
public static getAllSettings() {
@ -79,7 +81,7 @@ export default abstract class SettingHelper {
finalValue = CodingHelper.encrypt(APPLICATION_SECRET, stringValue);
}
this.settings[key] = finalValue;
this.settings[key] = stringValue;
const [topic, settingKey] = key.split(".") as [SettingTopic, string];
await SettingCommandHandler.create({
@ -144,13 +146,14 @@ export default abstract class SettingHelper {
}
let processedValue = valueToCheck;
if (typeof settingType.type === "string" && settingType.type.includes("/crypt")) {
try {
processedValue = CodingHelper.decrypt(APPLICATION_SECRET, processedValue);
} catch (error) {
throw new Error(`Unable to decrypt value for ${key}: ${error.message}`);
}
}
// do not encypt data here - data is only crypted towards database
// if (typeof settingType.type === "string" && settingType.type.includes("/crypt")) {
// try {
// processedValue = CodingHelper.decrypt(APPLICATION_SECRET, processedValue);
// } catch (error) {
// throw new Error(`Unable to decrypt value for ${key}: ${error.message}`);
// }
// }
const baseType =
typeof settingType.type === "string"