Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f98e7d6

Browse files
authored
Merge pull request #3658 from processing/pr05/migrate_mail_system
pr05 Typescript Migration 12: Migrate server files related to emailing/nodemailer -- REBUILD
2 parents 79e8a5c + f10adb7 commit f98e7d6

File tree

12 files changed

+5603
-1304
lines changed

12 files changed

+5603
-1304
lines changed

‎package-lock.json‎

Lines changed: 5459 additions & 1261 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,11 @@
137137
"@testing-library/react": "^12.1.2",
138138
"@types/friendly-words": "^1.2.2",
139139
"@types/jest": "^29.5.14",
140+
"@types/mjml": "^4.7.4",
140141
"@types/node": "^16.18.126",
142+
"@types/nodemailer": "^7.0.1",
141143
"@types/passport": "^1.0.17",
144+
"@types/nodemailer-mailgun-transport": "^1.4.6",
142145
"@types/react": "^16.14.0",
143146
"@types/react-dom": "^16.9.25",
144147
"@types/react-router-dom": "^5.3.3",

‎server/controllers/user.controller.js‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import crypto from 'crypto';
22

33
import User from '../models/user';
4-
import mail from '../utils/mail';
4+
import {mailerService} from '../utils/mail';
55
import { renderEmailConfirmation, renderResetPassword } from '../views/mail';
66

77
export * from './user.controller/apiKey';
@@ -83,7 +83,7 @@ export async function createUser(req, res) {
8383
});
8484

8585
try {
86-
await mail.send(mailOptions);
86+
await mailerService.send(mailOptions);
8787
res.json(userResponse(user));
8888
} catch (mailErr) {
8989
console.error(mailErr);
@@ -155,7 +155,7 @@ export async function resetPasswordInitiate(req, res) {
155155
to: user.email
156156
});
157157

158-
await mail.send(mailOptions);
158+
await mailerService.send(mailOptions);
159159
res.json({
160160
success: true,
161161
message:
@@ -203,7 +203,7 @@ export async function emailVerificationInitiate(req, res) {
203203
to: user.email
204204
});
205205
try {
206-
await mail.send(mailOptions);
206+
await mailerService.send(mailOptions);
207207
} catch (mailErr) {
208208
res.status(500).send({ error: 'Error sending mail' });
209209
return;
@@ -334,7 +334,7 @@ export async function updateSettings(req, res) {
334334
to: user.email
335335
});
336336

337-
await mail.send(mailOptions);
337+
await mailerService.send(mailOptions);
338338
} else {
339339
await saveUser(res, user);
340340
}

‎server/migrations/emailConsolidation.js‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
moveObjectToUserInS3,
88
copyObjectInS3
99
} from '../controllers/aws.controller';
10-
import mail from '../utils/mail';
10+
import {mailerService} from '../utils/mail';
1111
import { renderAccountConsolidation } from '../views/mail';
1212

1313
const mongoConnectionString = process.env.MONGO_URL;
@@ -31,7 +31,8 @@ mongoose.connection.on('error', () => {
3131
* https://mongodb.github.io/node-mongodb-native
3232
*/
3333

34-
const agg = [ // eslint-disable-line
34+
const agg = [
35+
// eslint-disable-line
3536
{
3637
$project: {
3738
email: {
@@ -187,7 +188,7 @@ async function consolidateAccount(email) {
187188
});
188189

189190
return new Promise((resolve, reject) => {
190-
mail.send(mailOptions, (mailErr, result) => {
191+
mailerService.send(mailOptions, (mailErr, result) => {
191192
console.log('Sent email.');
192193
if (mailErr) {
193194
return reject(mailErr);
@@ -226,7 +227,7 @@ async function consolidateAccount(email) {
226227
// });
227228

228229
// return new Promise((resolve, reject) => {
229-
// mail.send(mailOptions, (mailErr, result) => {
230+
// mailerService.send(mailOptions, (mailErr, result) => {
230231
// console.log('Sent email.');
231232
// if (mailErr) {
232233
// return reject(mailErr);

‎server/types/email.ts‎

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/** Rendered mail data for the mailer service, without the 'from' property, which will be automatically added */
2+
export interface RenderedMailerData {
3+
to: string;
4+
subject: string;
5+
html?: string;
6+
}
7+
8+
// -------- EMAIL OPTIONS --------
9+
/** Options to generate the account consolidation email */
10+
export interface AccountConsolidationEmailOptions {
11+
body: {
12+
domain: string;
13+
username: string;
14+
email: string;
15+
};
16+
to: string;
17+
}
18+
/** Options to generate the reset password email */
19+
export interface ResetPasswordEmailOptions {
20+
body: {
21+
domain: string;
22+
link: string;
23+
};
24+
to: string;
25+
}
26+
/** Options to generate the confirm email email */
27+
export interface ConfirmEmailEmailOptions {
28+
body: {
29+
domain: string;
30+
link: string;
31+
};
32+
to: string;
33+
}
34+
35+
// -------- EMAIL RENDERING TEMPLATES --------
36+
/** Base template for emails */
37+
export interface BaseEmailTemplate {
38+
domain: string;
39+
headingText: string;
40+
greetingText: string;
41+
messageText: string;
42+
directLinkText: string;
43+
noteText: string;
44+
meta: {
45+
keywords: string;
46+
description: string;
47+
};
48+
}
49+
/** Template for an email with a primary button, which contains text and a link */
50+
export interface EmailWithPrimaryButtonTemplate extends BaseEmailTemplate {
51+
link: string;
52+
buttonText: string;
53+
}
54+
/** Template for rendering the account consolidation email */
55+
export interface AccountConsolidationEmailTemplate extends BaseEmailTemplate {
56+
username: string;
57+
email: string;
58+
message2Text: string;
59+
resetPasswordLink: string;
60+
resetPasswordText: string;
61+
}
62+
/** Template for rendering the confirm email email */
63+
export type ConfirmEmailEmailTemplate = EmailWithPrimaryButtonTemplate;
64+
/** Template for rendering the reset password email */
65+
export type ResetPasswordEmailTemplate = EmailWithPrimaryButtonTemplate;

‎server/types/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './email';

‎server/utils/mail.js‎ renamed to ‎server/utils/mail.ts‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
1-
/**
2-
* Mail service wrapping around mailgun
3-
*/
4-
51
import nodemailer from 'nodemailer';
62
import mg from 'nodemailer-mailgun-transport';
3+
import { RenderedMailerData } from '../types/email';
4+
5+
if (!process.env.MAILGUN_KEY) {
6+
throw new Error('Mailgun key missing');
7+
}
78

89
const auth = {
910
api_key: process.env.MAILGUN_KEY,
1011
domain: process.env.MAILGUN_DOMAIN
1112
};
1213

14+
/** Mail service class wrapping around mailgun */
1315
class Mail {
16+
client: nodemailer.Transporter;
17+
18+
sendOptions: Pick<nodemailer.SendMailOptions, 'from'>;
19+
1420
constructor() {
1521
this.client = nodemailer.createTransport(mg({ auth }));
1622
this.sendOptions = {
1723
from: process.env.EMAIL_SENDER
1824
};
1925
}
2026

21-
async sendMail(mailOptions) {
27+
async sendMail(mailOptions: nodemailer.SendMailOptions) {
2228
try {
2329
const response = await this.client.sendMail(mailOptions);
2430
return response;
@@ -28,8 +34,8 @@ class Mail {
2834
}
2935
}
3036

31-
async send(data) {
32-
const mailOptions = {
37+
async send(data: RenderedMailerData) {
38+
const mailOptions: nodemailer.SendMailOptions = {
3339
from: this.sendOptions.from,
3440
to: data.to,
3541
subject: data.subject,
@@ -46,4 +52,7 @@ class Mail {
4652
}
4753
}
4854

49-
export default new Mail();
55+
/**
56+
* Mail service wrapping around mailgun
57+
*/
58+
export const mailerService = new Mail();

‎server/utils/renderMjml.js‎

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎server/utils/renderMjml.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* eslint-disable consistent-return */
2+
import mjml2html from 'mjml';
3+
4+
/** Parse template string containing mjml tags into html for nodemailer.SendMailOptions.html */
5+
export function renderMjml(template: string): string | undefined {
6+
try {
7+
const output = mjml2html(template);
8+
return output.html;
9+
} catch (e) {
10+
console.error(e);
11+
// fall through to undefined (null is not valid for nodemailer.SendMailOptions.html)
12+
return undefined;
13+
}
14+
}

‎server/views/consolidationMailLayout.js‎ renamed to ‎server/views/consolidationMailLayout.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
export default ({
1+
import type { AccountConsolidationEmailTemplate } from '../types/email';
2+
3+
/** Returns mjml for an Account Consolidation email */
4+
export const consolidationMailLayout = ({
25
domain,
36
headingText,
47
greetingText,
@@ -11,7 +14,7 @@ export default ({
1114
resetPasswordText,
1215
noteText,
1316
meta
14-
}) =>
17+
}: AccountConsolidationEmailTemplate) =>
1518
`
1619
<mjml>
1720
<mj-head>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /