"use strict";
/*
 * server component for the TimeLimit App
 * Copyright (C) 2019 - 2023 Jonas Lochmann
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendAccountDeletedMail = exports.sendPasswordRecoveryUsedMail = exports.sendDeviceLinkedMail = exports.sendTaskDoneMail = exports.sendUninstallWarningMail = exports.sendManipulationWarningMail = exports.sendAuthenticationMail = void 0;
exports.isMailServerBlacklisted = isMailServerBlacklisted;
exports.isMailAddressCoveredByWhitelist = isMailAddressCoveredByWhitelist;
exports.sanitizeMailAddress = sanitizeMailAddress;
const ejs_1 = require("ejs");
const email_addresses_1 = require("email-addresses");
const fs_1 = require("fs");
const nodemailer_1 = require("nodemailer");
const path_1 = require("path");
const config_1 = require("../config");
const exception_1 = require("../exception");
const mailimprint = process.env.MAIL_IMPRINT || 'not defined';
const mailServerBlacklist = (process.env.MAIL_SERVER_BLACKLIST || '').split(',').filter((item) => !!item);
const mailSender = process.env.MAIL_SENDER || '';
const mailTransportConfig = JSON.parse(process.env.MAIL_TRANSPORT || 'null') || undefined;
const isDevMode = process.env.NODE_ENV === 'development';
const mailTransport = isDevMode || mailTransportConfig !== undefined ?
    (0, nodemailer_1.createTransport)(isDevMode ? {
        jsonTransport: true
    } : mailTransportConfig) :
    null;
function createMailTemplateSender(templateName) {
    const compileTemplate = (filename) => (0, ejs_1.compile)((0, fs_1.readFileSync)((0, path_1.resolve)(__dirname, '../../other/mail', templateName, filename)).toString('utf8'));
    const subjectTemplate = compileTemplate('subject.ejs');
    const textTemplate = compileTemplate('text.ejs');
    const htmlTemplate = compileTemplate('html.ejs');
    const sendMail = async ({ receiver, params }) => {
        if (!mailTransport) {
            throw new Error('can not send mails without mail config and without NODE_ENV=development');
        }
        const subject = subjectTemplate(params).replace(/\n/g, ' ');
        const text = textTemplate(params);
        const html = htmlTemplate(params);
        await new Promise((resolve, reject) => {
            mailTransport.sendMail({
                from: mailSender,
                to: receiver,
                subject,
                text,
                html
            }, (err, info) => {
                if (err) {
                    reject(err);
                }
                else {
                    if (isDevMode) {
                        // eslint-disable-next-line @typescript-eslint/no-explicit-any
                        const data = info.message;
                        console.log(JSON.stringify(Object.assign(Object.assign({}, JSON.parse(data)), { params }), null, 2));
                    }
                    resolve();
                }
            });
        });
    };
    return { sendMail };
}
const loginMailSender = createMailTemplateSender('login');
const sendAuthenticationMail = async ({ receiver, code, locale, deviceName }) => {
    await loginMailSender.sendMail({
        receiver,
        params: {
            subject: locale === 'de' ? 'Anmeldung bei TimeLimit' : 'Sign in at TimeLimit',
            introtext: locale === 'de' ? 'Geben Sie zum Authentifizieren folgenden Code in TimeLimit ein' : 'To authenticate, enter the following code in TimeLimit',
            code,
            outrotext: locale === 'de' ? 'Geben Sie diesen Code nicht an Dritte weiter.' : 'Do not share this code with third parties.',
            mailimprint,
            deviceName,
            deviceNameIntro: locale === 'de' ? 'Die Anmeldung wurde am Gerät' : 'The login was attempted at the device',
            deviceNameOutro: locale === 'de' ? 'versucht.' : '.'
        }
    });
};
exports.sendAuthenticationMail = sendAuthenticationMail;
const manipulationMailSender = createMailTemplateSender('manipulation');
const sendManipulationWarningMail = async ({ receiver, deviceName }) => {
    await manipulationMailSender.sendMail({
        receiver,
        params: {
            subject: 'TimeLimit@' + deviceName + ' - Manipulation',
            deviceName,
            mailimprint
        }
    });
};
exports.sendManipulationWarningMail = sendManipulationWarningMail;
const uninstallMailSender = createMailTemplateSender('uninstall');
const sendUninstallWarningMail = async ({ receiver, deviceName }) => {
    await uninstallMailSender.sendMail({
        receiver,
        params: {
            subject: 'TimeLimit removed from ' + deviceName,
            deviceName,
            mailimprint
        }
    });
};
exports.sendUninstallWarningMail = sendUninstallWarningMail;
const taskDoneSender = createMailTemplateSender('taskdone');
const sendTaskDoneMail = async ({ receiver, child, task }) => {
    await taskDoneSender.sendMail({
        receiver,
        params: { child, task, mailimprint }
    });
};
exports.sendTaskDoneMail = sendTaskDoneMail;
const deviceLinkedSender = createMailTemplateSender('device-linked-by-mail');
const sendDeviceLinkedMail = async ({ receiver, deviceName, locale }) => {
    await deviceLinkedSender.sendMail({
        receiver,
        params: {
            subject: locale === 'de' ? 'Gerät hinzugefügt' : 'Device added',
            preText: locale === 'de' ? 'Soeben wurde das Gerät' : 'The device',
            deviceName,
            postText: locale === 'de' ? 'über Ihre E-Mail-Adresse hinzugefügt.' : 'was added using your mail address.',
            securityText: getMailSecurityText(locale),
            mailimprint
        }
    });
};
exports.sendDeviceLinkedMail = sendDeviceLinkedMail;
const passwordRecoveryUsedMailSender = createMailTemplateSender('password-recovery-used');
const sendPasswordRecoveryUsedMail = async ({ receiver, locale }) => {
    await passwordRecoveryUsedMailSender.sendMail({
        receiver,
        params: {
            subject: locale === 'de' ? 'Passwort-Vergessen-Funktion verwendet' : 'Password reset',
            text: locale === 'de' ?
                'Soeben wurde Ihr TimeLimit-Passwort mit der Passwort-Vergessen-Funktion geändert.' :
                'Your password was changed using the password reset feature.',
            securityText: getMailSecurityText(locale),
            mailimprint
        }
    });
};
exports.sendPasswordRecoveryUsedMail = sendPasswordRecoveryUsedMail;
const accountDeletedMailSender = createMailTemplateSender('account-deleted');
const sendAccountDeletedMail = async ({ receiver }) => {
    await accountDeletedMailSender.sendMail({
        receiver,
        params: {
            mailimprint
        }
    });
};
exports.sendAccountDeletedMail = sendAccountDeletedMail;
function getMailSecurityText(locale) {
    if (locale === 'de') {
        return 'Achten Sie darauf, dass Ihr Kind/Ihre Kinder keinen Zugang zu der E-Mail-Adresse hat/haben, die Sie bei TimeLimit angegeben haben.';
    }
    else {
        return 'Make sure that your child/children can not access the mail addresss that you use for TimeLimit.';
    }
}
function isMailServerBlacklisted(mail) {
    const parts = mail.split('@');
    const domain = parts[parts.length - 1];
    return mailServerBlacklist.indexOf(domain.toLowerCase()) !== -1;
}
function isMailAddressCoveredByWhitelist(mail) {
    if (config_1.config.mailWhitelist.length === 0) {
        return true;
    }
    const mailParts = mail.split('@');
    const mailDomain = mailParts[mailParts.length - 1];
    for (let i = 0; i < config_1.config.mailWhitelist.length; i++) {
        const whtielistItem = config_1.config.mailWhitelist[i];
        const isDomain = whtielistItem.indexOf('@') === -1;
        if (isDomain) {
            if (mailDomain === whtielistItem) {
                return true;
            }
        }
        else {
            if (mail === whtielistItem) {
                return true;
            }
        }
    }
    return false;
}
function sanitizeMailAddress(input) {
    const parsed = (0, email_addresses_1.parseOneAddress)(input);
    if ((!parsed) || (parsed.type !== 'mailbox')) {
        return null;
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const address = parsed.address;
    if (typeof address !== 'string') {
        throw new exception_1.IllegalStateException({ staticMessage: 'mail address is not a string' });
    }
    return address;
}
//# sourceMappingURL=mail.js.map