Skip to content

Commit

Permalink
- Reldens - v4.0.0 - Mailer fix WIP.
Browse files Browse the repository at this point in the history
  • Loading branch information
damian-pastorini committed Nov 28, 2023
1 parent 0822a34 commit 4e60e1d
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 80 deletions.
11 changes: 9 additions & 2 deletions install/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,15 @@ <h3 class="form-title">- Mailer -</h3>
<input type="checkbox" value="1" name="mailer-enable" id="mailer-enable"/>
</div>
<div class="input-box mailer-service mailer-filter">
<label for="mailer-service">Service Name or Host</label>
<input type="text" name="mailer-service" id="mailer-service"/>
<label for="mailer-service">Service</label>
<select name="mailer-service" id="mailer-service">
<option value="sendgrid">SendGrid</option>
<option value="nodemailer">NodeMailer</option>
</select>
</div>
<div class="input-box mailer-host mailer-filter">
<label for="mailer-host">Host</label>
<input type="text" name="mailer-host" id="mailer-host"/>
</div>
<div class="input-box mailer-secure mailer-filter">
<label for="mailer-secure">Secure (true|false > SSL)</label>
Expand Down
1 change: 1 addition & 0 deletions lib/game/server/install-templates/.env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ RELDENS_ENABLE_TRACE_FOR=emergency,alert,critical,error,warning
# Mailer:
RELDENS_MAILER_ENABLE={{&mailer-enable}}
RELDENS_MAILER_SERVICE={{&mailer-service}}
RELDENS_MAILER_HOST={{&mailer-host}}
RELDENS_MAILER_PORT={{&mailer-port}}
RELDENS_MAILER_USER={{&mailer-username}}
RELDENS_MAILER_PASS={{&mailer-password}}
Expand Down
4 changes: 2 additions & 2 deletions lib/game/server/login-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class LoginManager
if(!this.events){
return false;
}
this.events.on('reldens.serverBeforeListen', (props) => {
props.serverManager.app.get('/reldens-mailer-enabled', (req, res) => {
this.events.on('reldens.serverBeforeListen', async (props) => {
await props.serverManager.app.get('/reldens-mailer-enabled', async (req, res) => {
res.json({
enabled: this.mailer?.isEnabled()
});
Expand Down
113 changes: 44 additions & 69 deletions lib/game/server/mailer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,68 @@
*
* Reldens - Mailer
*
* E-mails sender class.
*
*/

const NodeMailer = require('nodemailer');
const { Logger, ErrorManager, sc } = require('@reldens/utils');
const { SendGridFactory } = require('./mailer/sendgrid-factory');
const { NodemailerFactory } = require('./mailer/nodemailer-factory');
const { Logger, sc } = require('@reldens/utils');

class Mailer
{

constructor(props)
{
this.transporter = false;
this.service = sc.get(props, 'service', false);
this.user = false;
this.pass = false;
this.to = false;
this.subject = false;
this.text = false;
if(this.service || 1 === Number(process.env.RELDENS_MAILER_ENABLE || 0)){
this.setupTransporter(props);
this.enabled = 1 === Number(process.env.RELDENS_MAILER_ENABLE || 0);
this.service = (sc.get(props, 'service', (process.env.RELDENS_MAILER_SERVICE || ''))).toString();
this.serviceInstance = this.fetchServiceInstance(this.service);
this.port = sc.get(props, 'port', process.env.RELDENS_MAILER_PORT);
this.user = sc.get(props, 'user', process.env.RELDENS_MAILER_USER);
this.pass = sc.get(props, 'pass', process.env.RELDENS_MAILER_PASS);
this.from = sc.get(props, 'from', process.env.RELDENS_MAILER_FROM);
this.to = sc.get(props, 'to', false);
this.subject = sc.get(props, 'subject', false);
this.text = sc.get(props, 'text', false);
this.readyForSetup = this.enabled && this.serviceInstance;
}

fetchServiceInstance(serviceKey)
{
switch(serviceKey){
case 'sendgrid':
return new SendGridFactory();
case 'nodemailer':
return new NodemailerFactory();
default:
return false;
}
}

setupTransporter(props)
async setupTransporter()
{
this.service = sc.get(props, 'service', process.env.RELDENS_MAILER_SERVICE);
this.user = sc.get(props, 'user', process.env.RELDENS_MAILER_USER);
this.pass = sc.get(props, 'pass', process.env.RELDENS_MAILER_PASS);
this.from = sc.get(props, 'from', process.env.RELDENS_MAILER_FROM);
// @TODO - BETA - Update and fix.
/*
// samples:
const mailer = nodemailer.createTransport({
host: 'smtp.sendgrid.net',
port: 465,
secure: true,
auth: {
user: 'apikey',
pass: 'SG.XXXX.XXXX',
},
});
OR:
const nodemailer = require('nodemailer');
const nodemailerSendgrid = require('nodemailer-sendgrid');
const transport = nodemailer.createTransport(
nodemailerSendgrid({
apiKey: process.env.SENDGRID_API_KEY
})
);
*/
this.transporter = NodeMailer.createTransport({
service: this.service,
auth: {
user: this.user,
pass: this.pass,
}
});
this.transporter.verify(function(error, success){
if(error){
Logger.error('SMTP create transport error.', error);
}
});
if(this.serviceInstance && sc.isObjectFunction(this.serviceInstance, 'setup')){
this.transporter = this.serviceInstance.setup(this);
return true;
}
return false;
}

isEnabled()
{
return this.transporter ? {service: this.service, user: this.user} : false;
return this.enabled && this.transporter;
}

async sendEmail(props)
{
if(!props){
ErrorManager.error('Send empty props error.');
return false;
}
if(!this.transporter || !this.service || !this.user || !this.pass){
Logger.error('Transporter configuration not specified.', {
transporter: this.transporter,
service: this.service,
user: this.user,
pass: this.pass
});
ErrorManager.error('E-mail error, please try again later.');
if(!sc.isObject(props)){
Logger.error('Send email empty properties error.');
return false;
}
if(!props.to || !props.subject || (!props.text && !props.html)){
ErrorManager.error('Send properties not specified:', props);
Logger.error(
'Send email required properties missing.',
{to: props.to, subject: props.subject, text: props.text, html: props.html}
);
return false;
}
let mailOptions = {
Expand All @@ -103,11 +77,12 @@ class Mailer
if(sc.hasOwn(props, 'html')){
mailOptions.html = props.html;
}
return await this.transporter.sendMail(mailOptions).catch((error) => {
Logger.info(error);
ErrorManager.error('Transporter sendMail error.', mailOptions);
return false;
});
if(this.serviceInstance && sc.isObjectFunction(this.serviceInstance, 'sendMail')){
await this.serviceInstance.sendMail({
mailOptions: mailOptions,
transporter: this.transporter
})
}
}

}
Expand Down
69 changes: 69 additions & 0 deletions lib/game/server/mailer/nodemailer-factory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
*
* Reldens - NodemailerFactory
*
*/

const Nodemailer = require('nodemailer');
const { Logger, sc } = require('@reldens/utils');

class NodemailerFactory
{

setup(mailer)
{
if(!mailer){
Logger.error('Mailer not found on NodemailerFactory.');
return false;
}
if(!mailer.pass){
Logger.error('Required mailer password not found on NodemailerFactory.');
return false;
}
if(!mailer.host || !mailer.port || !mailer.user || !mailer.pass){
Logger.error('NodemailerFactory required configuration not specified.', {
host: mailer.host,
port: mailer.port,
user: mailer.user,
pass: mailer.pass
});
return false;
}
try {
return Nodemailer.createTransport({
host: mailer.host,
port: mailer.port,
secure: Boolean(sc.get(mailer, 'secure', true)),
auth: {
// @NOTE: for example, this could be "user" and "password" values from https://forwardemail.net.
user: mailer.user,
pass: mailer.pass
}
});
} catch (error) {
Logger.error('Nodemailer transport error.', error);
return false;
}
}

async sendEmail(props)
{
if(!props.transporter){
Logger.error('Transporter not found on Nodemailer.');
return false;
}
if(!props.mailOptions){
Logger.error('Mail options not found on Nodemailer.');
return false;
}
try {
return await props.transporter.sendMail(props.mailOptions);
} catch (error) {
Logger.error('Nodemailer sendMail error.', error, props.mailOptions);
return false;
}
}

}

module.exports.NodemailerFactory = NodemailerFactory;
52 changes: 52 additions & 0 deletions lib/game/server/mailer/sendgrid-factory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
*
* Reldens - SendGridFactory
*
*/

const SendGridMail = require('@sendgrid/mail');
const { Logger } = require('@reldens/utils');

class SendGridFactory
{

async setup(mailer)
{
if(!mailer){
Logger.error('Mailer not found on SendGridFactory.');
return false;
}
if(!mailer.pass){
Logger.error('Required mailer password not found on SendGridFactory.');
return false;
}
try {
SendGridMail.setApiKey(mailer.pass);
return SendGridMail;
} catch (error) {
Logger.error('SendGrid transport error.', error);
return false;
}
}

async sendEmail(props)
{
if(!props.transporter){
Logger.error('Transporter not found on SendGrid.');
return false;
}
if(!props.mailOptions){
Logger.error('Mail options not found on SendGrid.');
return false;
}
try {
return await props.transporter.send(props.mailOptions);
} catch (error) {
Logger.error('SendGrid sendMail error.', error, props.mailOptions);
return false;
}
}

}

module.exports.SendGridFactory = SendGridFactory;
20 changes: 13 additions & 7 deletions lib/game/server/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const { MapsLoader } = require('./maps-loader');
const { ForgotPassword } = require('./forgot-password');
const { Installer } = require('./installer');
const { EventsManagerSingleton, Logger, sc } = require('@reldens/utils');
const {expectedResult} = require("adminjs/types/spec/backend/helpers/resource-stub");

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable expectedResult.

class ServerManager
{
Expand Down Expand Up @@ -293,22 +294,27 @@ class ServerManager
});
}

async initializeMailer()
async initializeMailer(mailer)
{
// @TODO - BETA - Extract and pass to the ServerManager in the constructor.
this.mailer = new Mailer();
Logger.info('Mailer: ' +(this.mailer.isEnabled() ? 'enabled' : 'disabled'));
this.mailer = mailer || new Mailer();
if(this.mailer.readyForSetup){
let result = await this.mailer.setupTransporter();
if (!result){
Logger.error('Mailer setup failed.');
return false;
}
}
Logger.info('Mailer: '+(this.mailer?.isEnabled() ? 'enabled' : 'disabled'));
// @TODO - BETA - Check if the forgot password is enabled or not before add the calls to the server.
await ForgotPassword.defineRequestOnServerManagerApp(this);
}

async initializeConfigManager()
{
await this.configManager.loadConfigurations();
this.configManager.projectPaths = this.themeManager.paths();
await this.events.emit('reldens.serverConfigReady', {
serverManager: this,
configProcessor: this.configManager
});
await this.events.emit('reldens.serverConfigReady', {serverManager: this, configProcessor: this.configManager});
}

}
Expand Down
Loading

0 comments on commit 4e60e1d

Please sign in to comment.