import { Injectable, Logger, InternalServerErrorException } from '@nestjs/common'; import * as amqp from 'amqplib'; import { ContactForm, Email, EmailWithoutFrom, FeedbackForm } from './email'; import { ConfigService } from '../configuration/config.service'; import { buildContactAdminEmail, buildContactUserEmail } from '../email-templates/contact'; import { buildFeedbackEmail } from '../email-templates/feedback'; import * as useragent from 'useragent'; import moment = require('moment-timezone'); moment.tz.setDefault('Europe/Paris'); @Injectable() export class EmailService { private logger: Logger; config: any = {}; constructor(private configService: ConfigService) { this.logger = new Logger(EmailService.name); this.config = this.configService.config; } async sendContactEmails(contactForm: ContactForm) { this.logger.log('Entering function', `${EmailService.name} - ${this.sendContactEmails.name}`); const adminEmailBody = buildContactAdminEmail({ subject: contactForm.subject, message: contactForm.text, firstName: contactForm.firstname, lastName: contactForm.lastname, email: contactForm.email, datetime: moment().format('DD/MM/YYYY à HH:mm'), imageHost: this.config.imageHost, }); const userEmailBody = buildContactUserEmail({ subject: contactForm.subject, message: contactForm.text, firstName: contactForm.firstname, datetime: moment().format('DD/MM/YYYY à HH:mm'), imageHost: this.config.imageHost, }); const adminEmail = new EmailWithoutFrom(); adminEmail.to = [this.config.userSupportMailbox]; adminEmail.replyTo = contactForm.email; adminEmail.subject = contactForm.subject; adminEmail.html = adminEmailBody; const userEmail = new EmailWithoutFrom(); userEmail.to = [contactForm.email]; userEmail.replyTo = this.config.userSupportMailbox; userEmail.subject = contactForm.subject; userEmail.html = userEmailBody; await this.send(adminEmail); await this.send(userEmail); return; } async sendFeedback(feedbackForm: FeedbackForm, userAgent) { this.logger.log('Entering function', `${EmailService.name} - ${this.sendFeedback.name}`); const userAgentParsed = useragent.parse(userAgent); let userAgentString = ''; if (userAgentParsed) { userAgentString = `Family: ${userAgentParsed.family},`; userAgentString += `Version:${userAgentParsed.major}.${userAgentParsed.minor}.${userAgentParsed.patch},`; userAgentString += `Source: ${userAgentParsed.source}`; } const feedbackEmailBody = buildFeedbackEmail({ url: feedbackForm.url, userAgent: userAgentString, version: feedbackForm.version, message: feedbackForm.message, datetime: moment().format('DD/MM/YYYY à HH:mm'), imageHost: this.config.imageHost, }); const feedbackEmail = new EmailWithoutFrom(); feedbackEmail.to = [this.config.userSupportMailbox]; if (this.config.additionalFeedbackEmails) { feedbackEmail.to = feedbackEmail.to.concat(this.config.additionalFeedbackEmails.split(',')); } feedbackEmail.subject = 'Feedback'; feedbackEmail.html = feedbackEmailBody; await this.send(feedbackEmail); return; } async send(emailInfo: EmailWithoutFrom) { this.logger.log('Entering function', `${EmailService.name} - ${this.send.name}`); let conn, ch; // tslint:disable-next-line:max-line-length const rabbitmqUrl = `amqp://${this.config.rabbitMQ.user}:${this.config.rabbitMQ.password}@${this.config.rabbitMQ.host}:${this.config.rabbitMQ.port}`; const mailerQueue = this.config.mailerQueue; let email = new Email(); email.from = this.config.noReplyMailAddress; email = Object.assign(email, emailInfo); if (this.config.mailSubjectPrefix) { email.subject = `[${this.config.mailSubjectPrefix}] ${email.subject}`; } // Connect to rabbitmq try { conn = await amqp.connect(rabbitmqUrl); } catch (error) { this.logger.error('Error connecting to RabbitMQ', error, `${EmailService.name} - ${this.send.name}`); throw new InternalServerErrorException('Could not connect to rabbitMQ.'); } try { // Create a communication channel ch = await conn.createChannel(); } catch (error) { this.logger.error('Error creating channel', error, `${EmailService.name} - ${this.send.name}`); throw new InternalServerErrorException('Could not create channel.'); } // Stringify and bufferise message const buffer = Buffer.from(JSON.stringify(email)); try { await ch.assertQueue(mailerQueue, { durable: true }); } catch (error) { this.logger.error('Error asserting queue', error, `${EmailService.name} - ${this.send.name}`); throw new InternalServerErrorException('Could not assert queue.'); } try { await ch.sendToQueue(mailerQueue, buffer, { persistent: true }); } catch (error) { this.logger.error('Error sending to queue', error, `${EmailService.name} - ${this.send.name}`); throw new InternalServerErrorException('Could not send to queue.'); } this.logger.log( `Sent to queue ${mailerQueue},{ from: ${email.from}, to: ${email.to}, subject: ${email.subject}}`, `${EmailService.name} - ${this.send.name}`, ); setTimeout(() => { conn.close(); }, 500); return; } }