import { MailerService } from '@nestjs-modules/mailer'; import { BadRequestException, Injectable } from '@nestjs/common'; import { getAuth } from 'firebase-admin/auth'; import { join } from 'path'; import { ZodError } from 'zod'; import { SenderSchema, ShareByEMail, ShareByEMailSchema, User } from '../models/db.model'; import { ErrorResponse, MailInfo, isEmpty } from '../models/main.model'; import { UserService } from '../user/user.service'; // const __filename = fileURLToPath(import.meta.url); // const __dirname = path.dirname(__filename); @Injectable() export class MailService { constructor( private mailerService: MailerService, private userService: UserService, ) {} async sendInquiry(mailInfo: MailInfo): Promise { try { SenderSchema.parse(mailInfo.sender); } catch (error) { if (error instanceof ZodError) { const formattedErrors = error.errors.map(err => ({ field: err.path.join('.'), message: err.message, })); throw new BadRequestException(formattedErrors); } throw error; } const user = await this.userService.getUserByMail(mailInfo.email); if (isEmpty(mailInfo.sender.name)) { return { fields: [{ fieldname: 'name', message: 'Required' }] }; } await this.mailerService.sendMail({ to: user.email, from: '"Bizmatch Team" ', // override default from subject: `Inquiry from ${mailInfo.sender.name}`, //template: './inquiry', // `.hbs` extension is appended automatically template: join(__dirname, '../..', 'mail/templates/inquiry.hbs'), context: { // ✏️ filling curly brackets with content name: user.firstname, inquiry: mailInfo.sender.comments, internalListingNumber: mailInfo.listing.internalListingNumber, title: mailInfo.listing.title, iname: mailInfo.sender.name, phone: mailInfo.sender.phoneNumber, email: mailInfo.sender.email, id: mailInfo.listing.id, url: mailInfo.url, }, }); } async sendVerificationEmail( email: string, redirectConfig: { protocol: string, hostname: string, port?: number } ): Promise { try { // Firebase Auth-Instanz holen const auth = getAuth(); // Baue den Redirect-URL aus den übergebenen Parametern let continueUrl = `${redirectConfig.protocol}://${redirectConfig.hostname}`; if (redirectConfig.port) { continueUrl += `:${redirectConfig.port}`; } continueUrl += '/auth/verify-email-success'; // Beispiel für einen Weiterleitungspfad // Custom Verification Link generieren const firebaseActionLink = await auth.generateEmailVerificationLink(email, { url: continueUrl, handleCodeInApp: false, }); // Extrahiere den oobCode aus dem Firebase Link const actionLinkUrl = new URL(firebaseActionLink); const oobCode = actionLinkUrl.searchParams.get('oobCode'); if (!oobCode) { throw new BadRequestException('Failed to generate verification code'); } // Erstelle die benutzerdefinierte URL mit dem oobCode let customActionLink = `${redirectConfig.protocol}://${redirectConfig.hostname}`; if (redirectConfig.port) { customActionLink += `:${redirectConfig.port}`; } // Ersetze die Platzhalter mit den tatsächlichen Werten customActionLink += `/email-authorized?email=${encodeURIComponent(email)}&mode=verifyEmail&oobCode=${oobCode}`; // Zufallszahl für die E-Mail generieren const randomNumber = Math.floor(Math.random() * 10000); // E-Mail senden await this.mailerService.sendMail({ to: email, from: '"Bizmatch Team" ', subject: 'Verify your email address', template: join(__dirname, '../..', 'mail/templates/email-verification.hbs'), context: { actionLink: customActionLink, randomNumber: randomNumber }, }); return; } catch (error) { console.error('Error sending verification email:', error); throw new BadRequestException('Failed to send verification email'); } } async sendRequest(mailInfo: MailInfo): Promise { try { SenderSchema.parse(mailInfo.sender); } catch (error) { if (error instanceof ZodError) { const formattedErrors = error.errors.map(err => ({ field: err.path.join('.'), message: err.message, })); throw new BadRequestException(formattedErrors); } throw error; } await this.mailerService.sendMail({ to: 'support@bizmatch.net', from: `"Bizmatch Support Team" `, subject: `Support Request from ${mailInfo.sender.name}`, //template: './inquiry', // `.hbs` extension is appended automatically template: join(__dirname, '../..', 'mail/templates/request.hbs'), context: { // ✏️ filling curly brackets with content request: mailInfo.sender.comments, iname: mailInfo.sender.name, phone: mailInfo.sender.phoneNumber, email: mailInfo.sender.email, }, }); } async sendSubscriptionConfirmation(user: User): Promise { await this.mailerService.sendMail({ to: user.email, from: `"Bizmatch Support Team" `, subject: `Subscription Confirmation`, //template: './inquiry', // `.hbs` extension is appended automatically template: join(__dirname, '../..', 'mail/templates/subscriptionConfirmation.hbs'), context: { // ✏️ filling curly brackets with content firstname: user.firstname, lastname: user.lastname, subscriptionPlan: user.subscriptionPlan, }, }); } async send2Friend(shareByEMail: ShareByEMail): Promise { try { ShareByEMailSchema.parse(shareByEMail); } catch (error) { if (error instanceof ZodError) { const formattedErrors = error.errors.map(err => ({ field: err.path.join('.'), message: err.message, })); throw new BadRequestException(formattedErrors); } throw error; } await this.mailerService.sendMail({ to: shareByEMail.recipientEmail, from: `"Bizmatch.net" `, subject: `${shareByEMail.type === 'business' ? 'Business' : 'Commercial Property'} For Sale: ${shareByEMail.listingTitle}`, //template: './inquiry', // `.hbs` extension is appended automatically template: join(__dirname, '../..', 'mail/templates/send2Friend.hbs'), context: { name: shareByEMail.yourName, email: shareByEMail.yourEmail, listingTitle: shareByEMail.listingTitle, url: shareByEMail.url, id: shareByEMail.id, type: shareByEMail.type, }, }); } }