Skip to content
Snippets Groups Projects
Commit 2b68810c authored by Hugo SUBTIL's avatar Hugo SUBTIL
Browse files

feat(mailer): add ejs template handling

parent 13e5b816
No related branches found
No related tags found
2 merge requests!4Dev,!2feat(mailer): add ejs template handling
...@@ -4,6 +4,7 @@ import { AppController } from './app.controller'; ...@@ -4,6 +4,7 @@ import { AppController } from './app.controller';
import { StructuresModule } from './structures/structures.module'; import { StructuresModule } from './structures/structures.module';
import { ConfigurationModule } from './configuration/configuration.module'; import { ConfigurationModule } from './configuration/configuration.module';
import { CategoriesModule } from './categories/categories.module'; import { CategoriesModule } from './categories/categories.module';
import { MailerModule } from './mailer/mailer.module';
@Module({ @Module({
imports: [ imports: [
ConfigurationModule, ConfigurationModule,
...@@ -12,6 +13,7 @@ import { CategoriesModule } from './categories/categories.module'; ...@@ -12,6 +13,7 @@ import { CategoriesModule } from './categories/categories.module';
), ),
StructuresModule, StructuresModule,
CategoriesModule, CategoriesModule,
MailerModule,
], ],
controllers: [AppController], controllers: [AppController],
}) })
......
export const config = {
url: process.env.MAIL_URL,
token: process.env.MAIL_TOKEN,
host: 'ram.grandlyon.com',
protocol: 'https',
port: '443',
from: 'inclusionnumerique@grandlyon.com',
from_name: 'Réseau des acteurs de la médiation numérique',
replyTo: 'inclusionnumerique@grandlyon.com',
templates: {
directory: './src/mailer/mail-templates',
verify: {
ejs: 'verify.ejs',
json: 'verify.json',
},
changeEmail: {
ejs: 'changeEmail.ejs',
json: 'changeEmail.json',
},
},
};
import * as dotenv from 'dotenv'; import * as dotenv from 'dotenv';
import { config } from './config';
export class ConfigurationService { export class ConfigurationService {
private _config = config;
constructor() { constructor() {
// Initializing conf with values from var env // Initializing conf with values from var env
dotenv.config(); dotenv.config();
} }
get config() {
return this._config;
}
} }
Bonjour,<br />
<br />
Votre adresse email a été modifiée, si vous en avez bien fait la demande,
<a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/change-email/<%= token %>"
>cliquez ici pour valider le changement.</a
>
<br />
Ce mail est un mail automatique. Merci de ne pas y répondre.
{
"subject": "Changement d'adresse email"
}
Bonjour<br />
<br />
Afin de pouvoir vous connecter sur la plateforme, merci de cliquer sur
<a
href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/users/verify/<%= token %>"
>ce lien</a
>
afin de valider votre inscription<br />
<br />
Ce mail est un mail automatique. Merci de ne pas y répondre.
{
"subject": "Bienvenue sur le Réseau des Acteurs de la Médiation Numérique de la Métropole de Lyon"
}
import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/common/http/http.module';
import { MailerService } from './mailer.service';
@Module({
imports: [HttpModule],
providers: [MailerService],
exports: [MailerService],
})
export class MailerModule {}
import { Test, TestingModule } from '@nestjs/testing';
import { MailerService } from './mailer.service';
describe('MailerService', () => {
let service: MailerService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MailerService],
}).compile();
service = module.get<MailerService>(MailerService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { HttpService, Injectable, Logger } from '@nestjs/common';
import { ConfigurationService } from '../configuration/configuration.service';
import * as fs from 'fs';
import * as path from 'path';
@Injectable()
export class MailerService {
public config = null;
constructor(private readonly httpService: HttpService, private configurationService: ConfigurationService) {
this.config = this.configurationService.config;
}
/**
* Send an email
*
* @param {string} from
* @param {string} to
* @param {string} replyTo
* @param {string} subject
* @param {string} html
* @param {string} text
*/
public send(to: string, subject: string, html: string): Promise<any> {
const data = JSON.stringify({
from: this.config.from,
// eslint-disable-next-line camelcase
from_name: this.config.from_name,
to: to,
subject: subject,
content: html,
});
Logger.log(`[Mailer] Send mail : ${subject}`);
return new Promise((resolve, reject) => {
this.httpService
.post(process.env.MAIL_URL, data, {
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + process.env.MAIL_TOKEN,
},
})
.subscribe(
(body) => {
Logger.log(`[Mailer] Send mail : ${subject} success`);
return resolve(body);
},
(err) => {
Logger.error(err);
return reject(err);
}
);
});
}
/**
* Get email template location from config directory and given filename. Also, check if file exists.
*
* @param {string} filename
*/
public getTemplateLocation(filename) {
const ejsPath = path.join(this.config.templates.directory, filename);
if (!fs.existsSync(ejsPath)) {
throw new Error(`Email template '${filename}' cannot be found in ${this.config.templates.directory}`);
}
return ejsPath;
}
/**
* Load email json config file from config directory and given filename. Also, check if file exists
*
* @param {filename} filename
*/
public loadJsonConfig(filename) {
const jsonPath = path.join(this.config.templates.directory, filename);
if (!fs.existsSync(jsonPath)) {
throw new Error(`Email json definition file '${filename}' cannot be found in ${this.config.templates.directory}`);
}
return JSON.parse(fs.readFileSync(jsonPath).toString());
}
}
import { HttpModule, Module } from '@nestjs/common'; import { HttpModule, Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose'; import { MongooseModule } from '@nestjs/mongoose';
import { MailerModule } from '../mailer/mailer.module';
import { Structure, StructureSchema } from './schemas/structure.schema'; import { Structure, StructureSchema } from './schemas/structure.schema';
import { StructuresController } from './structures.controller'; import { StructuresController } from './structures.controller';
import { StructuresService } from './structures.service'; import { StructuresService } from './structures.service';
@Module({ @Module({
imports: [MongooseModule.forFeature([{ name: Structure.name, schema: StructureSchema }]), HttpModule], imports: [MongooseModule.forFeature([{ name: Structure.name, schema: StructureSchema }]), HttpModule, MailerModule],
controllers: [StructuresController], controllers: [StructuresController],
providers: [StructuresService], providers: [StructuresService],
}) })
......
...@@ -9,3 +9,5 @@ MONGO_DB_HOST_AND_PORT=<host:port used by the api to connect to mongo db> ...@@ -9,3 +9,5 @@ MONGO_DB_HOST_AND_PORT=<host:port used by the api to connect to mongo db>
ME_CONFIG_BASICAUTH_USERNAME=<mongo express username> ME_CONFIG_BASICAUTH_USERNAME=<mongo express username>
ME_CONFIG_BASICAUTH_PASSWORD=<mongo express password> ME_CONFIG_BASICAUTH_PASSWORD=<mongo express password>
ME_PORT=<mongo express port> ME_PORT=<mongo express port>
MAIL_URL=<API url>
MAIL_TOKEN=<API token>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment