refactor: normalize email calls

This commit is contained in:
KernelDeimos 2024-04-29 17:34:10 -04:00
parent 8cad610a54
commit c44028f413
8 changed files with 122 additions and 132 deletions

View File

@ -0,0 +1,2 @@
### `vscode`
- `es6-string-html`

14
package-lock.json generated
View File

@ -5276,6 +5276,19 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/dedent": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
"integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
"peerDependencies": {
"babel-plugin-macros": "^3.1.0"
},
"peerDependenciesMeta": {
"babel-plugin-macros": {
"optional": true
}
}
},
"node_modules/deep-eql": { "node_modules/deep-eql": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
@ -10859,6 +10872,7 @@
"composite-error": "^1.0.2", "composite-error": "^1.0.2",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"dedent": "^1.5.3",
"express": "^4.18.2", "express": "^4.18.2",
"file-type": "^18.5.0", "file-type": "^18.5.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",

View File

@ -28,6 +28,7 @@
"composite-error": "^1.0.2", "composite-error": "^1.0.2",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"dedent": "^1.5.3",
"express": "^4.18.2", "express": "^4.18.2",
"file-type": "^18.5.0", "file-type": "^18.5.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",

View File

@ -195,6 +195,9 @@ const install = async ({ services, app }) => {
const { EdgeRateLimitService } = require('./services/abuse-prevention/EdgeRateLimitService'); const { EdgeRateLimitService } = require('./services/abuse-prevention/EdgeRateLimitService');
services.registerService('edge-rate-limit', EdgeRateLimitService); services.registerService('edge-rate-limit', EdgeRateLimitService);
const { Emailservice } = require('./services/EmailService');
services.registerService('email', Emailservice);
} }
const install_legacy = async ({ services }) => { const install_legacy = async ({ services }) => {
@ -206,7 +209,6 @@ const install_legacy = async ({ services }) => {
const { OperationTraceService } = require('./services/OperationTraceService'); const { OperationTraceService } = require('./services/OperationTraceService');
const { WSPushService } = require('./services/WSPushService'); const { WSPushService } = require('./services/WSPushService');
const { ReferralCodeService } = require('./services/ReferralCodeService'); const { ReferralCodeService } = require('./services/ReferralCodeService');
const { Emailservice } = require('./services/EmailService');
const { ClientOperationService } = require('./services/ClientOperationService'); const { ClientOperationService } = require('./services/ClientOperationService');
const { EngPortalService } = require('./services/EngPortalService'); const { EngPortalService } = require('./services/EngPortalService');
const { AppInformationService } = require('./services/AppInformationService'); const { AppInformationService } = require('./services/AppInformationService');
@ -220,7 +222,6 @@ const install_legacy = async ({ services }) => {
services.registerService('operationTrace', OperationTraceService); services.registerService('operationTrace', OperationTraceService);
services.registerService('__event-push-ws', WSPushService); services.registerService('__event-push-ws', WSPushService);
services.registerService('referral-code', ReferralCodeService); services.registerService('referral-code', ReferralCodeService);
services.registerService('email', Emailservice);
services.registerService('file-cache', FileCacheService); services.registerService('file-cache', FileCacheService);
services.registerService('client-operation', ClientOperationService); services.registerService('client-operation', ClientOperationService);
services.registerService('app-information', AppInformationService); services.registerService('app-information', AppInformationService);

View File

@ -1547,56 +1547,16 @@ async function generate_system_fsentries(user){
} }
function send_email_verification_code(email_confirm_code, email){ function send_email_verification_code(email_confirm_code, email){
const nodemailer = require("nodemailer"); const svc_email = Context.get('services').get('email');
svc_email.send_email({ email }, 'email_verification_code', {
// send email notif code: hyphenize_confirm_code(email_confirm_code),
let transporter = nodemailer.createTransport({ })
host: config.smtp_server,
port: config.smpt_port,
secure: true, // STARTTLS
auth: {
user: config.smtp_username,
pass: config.smtp_password,
},
});
transporter.sendMail({
from: '"Puter" no-reply@puter.com', // sender address
to: email, // list of receivers
subject: `${hyphenize_confirm_code(email_confirm_code)} is your confirmation code`, // Subject line
html: `<p>Hi there,</p>
<p><strong>${hyphenize_confirm_code(email_confirm_code)}</strong> is your email confirmation code.</p>
<p>Sincerely,</p>
<p>Puter</p>
`,
});
} }
function send_email_verification_token(email_confirm_token, email, user_uuid){ function send_email_verification_token(email_confirm_token, email, user_uuid){
const nodemailer = require("nodemailer"); const svc_email = Context.get('services').get('email');
const link = `${config.origin}/confirm-email-by-token?user_uuid=${user_uuid}&token=${email_confirm_token}`;
// send email notif svc_email.send_email({ email }, 'email_verification_link', { link });
let transporter = nodemailer.createTransport({
host: config.smtp_server,
port: config.smpt_port,
secure: true, // STARTTLS
auth: {
user: config.smtp_username,
pass: config.smtp_password,
},
});
let link = `${config.origin}/confirm-email-by-token?user_uuid=${user_uuid}&token=${email_confirm_token}`;
transporter.sendMail({
from: '"Puter" no-reply@puter.com', // sender address
to: email, // list of receivers
subject: `Please confirm your email`, // Subject line
html: `<p>Hi there,</p>
<p>Please confirm your email address using this link: <strong><a href="${link}">${link}</a></strong>.</p>
<p>Sincerely,</p>
<p>Puter</p>
`,
});
} }
async function generate_random_username(){ async function generate_random_username(){

View File

@ -71,20 +71,8 @@ router.post('/contactUs', auth, express.json(), async (req, res, next)=>{
let user = await get_user({id: req.user.id}); let user = await get_user({id: req.user.id});
// send email to support // send email to support
const nodemailer = require("nodemailer"); const svc_email = req.services.get('email');
svc_email.sendMail({
// send email notif
let transporter = nodemailer.createTransport({
host: config.smtp_server,
port: config.smpt_port,
secure: true, // STARTTLS
auth: {
user: config.smtp_username,
pass: config.smtp_password,
},
});
transporter.sendMail({
from: '"Puter" no-reply@puter.com', // sender address from: '"Puter" no-reply@puter.com', // sender address
to: 'support@puter.com', // list of receivers to: 'support@puter.com', // list of receivers
replyTo: user.email === null ? undefined : user.email, replyTo: user.email === null ? undefined : user.email,

View File

@ -86,31 +86,12 @@ router.post('/send-pass-recovery-email', express.json(), body_parser_error_handl
); );
invalidate_cached_user(user); invalidate_cached_user(user);
// prepare email
let transporter = nodemailer.createTransport({
host: config.smtp_server,
port: config.smpt_port,
secure: true, // STARTTLS
auth: {
user: config.smtp_username,
pass: config.smtp_password,
},
});
// create link // create link
const rec_link = config.origin + '/action/set-new-password?user=' + user.uuid + '&token=' + token; const rec_link = config.origin + '/action/set-new-password?user=' + user.uuid + '&token=' + token;
// send email const svc_email = req.services.get('email');
transporter.sendMail({ await svc_email.send_email({ email: user.email }, 'email_password_recovery', {
from: 'no-reply@puter.com', // sender address link: rec_link,
to: user.email, // list of receivers
subject: "Password Recovery", // Subject line
html: `
<p>Hi there,</p>
<p>A password recovery request was issued for your account, please follow the link below to reset your password:</p>
<p><a href="${rec_link}">${rec_link}</a></p>
<p>Sincerely,</p>
<p>Puter</p>`,
}); });
// Send response // Send response

View File

@ -16,22 +16,14 @@
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
const { AdvancedBase } = require("@heyputer/puter-js-common");
class Emailservice extends AdvancedBase { const BaseService = require('./BaseService');
static MODULES = {
nodemailer: require('nodemailer'),
handlebars: require('handlebars'),
};
constructor ({ services, config }) { const TEMPLATES = {
super();
this.config = config;
this.templates = {
'new-referral': { 'new-referral': {
subject: `You've made a referral!`, subject: `You've made a referral!`,
html: `<p>Hi there,</p> html: `
<p>Hi there,</p>
<p>A new user has used your referral code. Enjoy an extra {{storage_increase}} of storage, on the house!</p> <p>A new user has used your referral code. Enjoy an extra {{storage_increase}} of storage, on the house!</p>
<p>Sincerely,</p> <p>Sincerely,</p>
<p>Puter</p> <p>Puter</p>
@ -77,46 +69,97 @@ If this was not you, please contact support@puter.com immediately.
</p> </p>
`, `,
}, },
'email_verification_code': {
subject: `{{code}} is your confirmation code`,
html: /*html*/`
<p>Hi there,</p>
<p><strong>{{code}}</strong> is your email confirmation code.</p>
<p>Sincerely,</p>
<p>Puter</p>
`
},
'email_verification_link': {
subject: `Please confirm your email`,
html: /*html*/`
<p>Hi there,</p>
<p>Please confirm your email address using this link: <strong><a href="{{link}}">{{link}}</a></strong>.</p>
<p>Sincerely,</p>
<p>Puter</p>
`
},
'email_password_recovery': {
subject: `Password Recovery`,
html: /*html*/`
<p>Hi there,</p>
<p>A password recovery request was issued for your account, please follow the link below to reset your password:</p>
<p><a href="{{link}}">{{link}}</a></p>
<p>Sincerely,</p>
<p>Puter</p>
`,
},
}
class Emailservice extends BaseService {
static MODULES = {
nodemailer: require('nodemailer'),
handlebars: require('handlebars'),
dedent: require('dedent'),
}; };
_construct () {
this.templates = TEMPLATES;
this.template_fns = {}; this.template_fns = {};
for ( const k in this.templates ) { for ( const k in this.templates ) {
const template = this.templates[k]; const template = this.templates[k];
this.template_fns[k] = values => { this.template_fns[k] = values => {
const html = this.modules.handlebars.compile(template.html); const subject = this.modules.handlebars.compile(template.subject);
const html =
this.modules.handlebars.compile(
this.modules.dedent(template.html));
return { return {
...template, ...template,
subject: subject(values),
html: html(values), html: html(values),
}; };
} }
} }
} }
async send_email (user, template, values) { _init () {
const config = this.config; console.log('the config', this.config);
}
get_transport_ () {
const nodemailer = this.modules.nodemailer; const nodemailer = this.modules.nodemailer;
let transporter = nodemailer.createTransport({ const config = { ...this.config };
host: config.smtp_server, delete config.engine;
port: config.smpt_port,
secure: true, // STARTTLS
auth: {
user: config.smtp_username,
pass: config.smtp_password,
},
});
let transport = nodemailer.createTransport(config);
return transport;
}
async send_email (user, template, values) {
const email = user.email; const email = user.email;
const template_fn = this.template_fns[template]; const template_fn = this.template_fns[template];
const { subject, html } = template_fn(values); const { subject, html } = template_fn(values);
const transporter = this.get_transport_();
transporter.sendMail({ transporter.sendMail({
from: '"Puter" no-reply@puter.com', // sender address from: '"Puter" no-reply@puter.com', // sender address
to: email, // list of receivers to: email, // list of receivers
subject, html, subject, html,
}); });
} }
// simple passthrough to nodemailer
sendMail (params) {
const transporter = this.get_transport_();
transporter.sendMail(params);
}
} }
module.exports = { module.exports = {