Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RN-1060: (task) Moved sendEmail to @tupaia/server-utils #5126

Merged
merged 1 commit into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/central-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
"moment-timezone": "^0.5.28",
"morgan": "^1.9.0",
"multer": "^1.4.3",
"nodemailer": "^4.7.0",
"public-ip": "^2.5.0",
"react-autobind": "^1.0.6",
"react-native-uuid": "^1.4.9",
Expand Down
7 changes: 5 additions & 2 deletions packages/central-server/src/apiV2/deleteAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
* Copyright (c) 2017 - 2022 Beyond Essential Systems Pty Ltd
*/
import { respond } from '@tupaia/utils';
import { sendEmail } from '../utilities';
import { sendEmail } from '@tupaia/server-utils';
import { getUserInfoInString } from './utilities';

const sendRequest = userInfo => {
const { TUPAIA_ADMIN_EMAIL_ADDRESS } = process.env;

const emailText = `${userInfo} has requested to delete their account`;
return sendEmail(TUPAIA_ADMIN_EMAIL_ADDRESS, 'Tupaia Account Deletion Request', emailText);
return sendEmail(TUPAIA_ADMIN_EMAIL_ADDRESS, {
subject: 'Tupaia Account Deletion Request',
text: emailText,
});
};

export const deleteAccount = async (req, res) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
* Copyright (c) 2017 - 2021 Beyond Essential Systems Pty Ltd
*/

import { sendEmail } from '@tupaia/server-utils';
import { respond } from '@tupaia/utils';
import { sendEmail } from '../../utilities';

const sendResponseAsEmail = (user, subject, message, attachments) => {
const text = `Hi ${user.first_name},

${message}
`;
sendEmail(user.email, subject, text, attachments);
sendEmail(user.email, { subject, text, attachments });
};

const setupEmailResponse = async (req, res, constructEmailFromResponse) => {
Expand Down
7 changes: 5 additions & 2 deletions packages/central-server/src/apiV2/requestCountryAccess.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* Copyright (c) 2017 Beyond Essential Systems Pty Ltd
*/
import { respond, UnauthenticatedError, ValidationError } from '@tupaia/utils';
import { sendEmail } from '@tupaia/server-utils';
import { getTokenClaimsFromBearerAuth } from '@tupaia/auth';
import { sendEmail } from '../utilities';
import { getUserInfoInString } from './utilities';

const checkUserPermission = (req, userId) => {
Expand Down Expand Up @@ -33,7 +33,10 @@ For the project ${project.code} (linked to permission groups: ${project.permissi
}
With the message: '${message}'
`;
return sendEmail(TUPAIA_ADMIN_EMAIL_ADDRESS, 'Tupaia Country Access Request', emailText);
return sendEmail(TUPAIA_ADMIN_EMAIL_ADDRESS, {
subject: 'Tupaia Country Access Request',
text: emailText,
});
};

const createAccessRequests = async (models, userId, entities, message, project) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/central-server/src/apiV2/requestPasswordReset.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Copyright (c) 2017 Beyond Essential Systems Pty Ltd
*/
import { respond, DatabaseError, FormValidationError } from '@tupaia/utils';
import { sendEmail } from '../utilities';
import { sendEmail } from '@tupaia/server-utils';
import { allowNoPermissions } from '../permissions';

export const requestPasswordReset = async (req, res) => {
Expand Down Expand Up @@ -43,7 +43,7 @@ ${resetUrl}
If you believe this email was sent to you in error, please contact us immediately at
admin@tupaia.org.`;

sendEmail(user.email, 'Password reset on Tupaia.org', emailText);
sendEmail(user.email, { subject: 'Password reset on Tupaia.org', text: emailText });

respond(res, {
success: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { encryptPassword } from '@tupaia/auth';
import { sendEmail } from '../../utilities';
import { sendEmail } from '@tupaia/server-utils';

const { TUPAIA_FRONT_END_URL, LESMIS_FRONT_END_URL } = process.env;

Expand Down Expand Up @@ -33,7 +33,7 @@ export const sendEmailVerification = async user => {
const platform = user.primary_platform ? user.primary_platform : 'tupaia';
const { subject, body, signOff } = EMAILS[platform];

return sendEmail(user.email, subject, body(token), null, signOff);
return sendEmail(user.email, { subject, text: body(token), signOff });
};

export const verifyEmailHelper = async (models, searchCondition, token) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
*/

import { UserEntityPermissionModel as CommonUserEntityPermissionModel } from '@tupaia/database';

import { sendEmail } from '../../utilities';
import { sendEmail } from '@tupaia/server-utils';

export class UserEntityPermissionModel extends CommonUserEntityPermissionModel {
notifiers = [onUpsertSendPermissionGrantEmail, expireAccess];
Expand Down Expand Up @@ -54,13 +53,11 @@ async function onUpsertSendPermissionGrantEmail(

const { subject, body, signOff } = EMAILS[platform];

sendEmail(
user.email,
sendEmail(user.email, {
subject,
body(user.first_name, permissionGroup.name, entity.name),
null,
text: body(user.first_name, permissionGroup.name, entity.name),
signOff,
);
});
}

/**
Expand Down
9 changes: 5 additions & 4 deletions packages/central-server/src/tests/scaffolding.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import winston from 'winston';

import { clearAllTestData } from '@tupaia/database';
import { getIsProductionEnvironment } from '@tupaia/utils';
import * as ServerUtils from '@tupaia/server-utils';
import { getModels, resetTestData } from './testUtilities';
import * as SendEmail from '../utilities/sendEmail';
import { clearAllTestData } from '@tupaia/database';

// These setup tasks need to be performed before any test, so we
// do them in this file outside of any describe block.
let sendEmailStub;

before(async () => {
const isProductionEnvironment = getIsProductionEnvironment();
Expand All @@ -21,7 +22,7 @@ before(async () => {
throw new Error('Never run the test suite on the production server, it messes with data!');
}

sinon.stub(SendEmail, 'sendEmail');
sendEmailStub = sinon.stub(ServerUtils, 'sendEmail');

await resetTestData();

Expand All @@ -39,7 +40,7 @@ before(async () => {

after(async () => {
const models = getModels();
SendEmail.sendEmail.restore();
sendEmailStub.restore();
await clearAllTestData(models.database);
await models.database.closeConnections();
});
1 change: 0 additions & 1 deletion packages/central-server/src/utilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@
export { getApiUrl } from './getApiUrl';
export { getTempDirectory } from './getTempDirectory';
export { resourceToRecordType } from './resourceToRecordType';
export { sendEmail } from './sendEmail';
export { getStandardisedImageName } from './getStandardisedImageName';
4 changes: 4 additions & 0 deletions packages/server-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
"@aws-sdk/lib-storage": "^3.348.0",
"@tupaia/utils": "1.0.0",
"cookie": "^0.5.0",
"nodemailer": "^6.9.7",
"puppeteer": "^15.4.0"
},
"devDependencies": {
"@types/nodemailer": "^6.4.13"
}
}
3 changes: 2 additions & 1 deletion packages/server-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './downloadPageAsPDF';
export { downloadPageAsPDF } from './downloadPageAsPDF';
export * from './s3';
export { sendEmail } from './sendEmail';
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@
* Copyright (c) 2017 Beyond Essential Systems Pty Ltd
*/
import nodemailer from 'nodemailer';
import { getIsProductionEnvironment } from '@tupaia/utils';
import { getIsProductionEnvironment, requireEnv } from '@tupaia/utils';
import Mail from 'nodemailer/lib/mailer';

const DEFAULT_SIGN_OFF = 'Cheers,\n\nThe Tupaia Team';

export const sendEmail = async (to, subject, text, attachments, signOff = DEFAULT_SIGN_OFF) => {
type MailOptions = {
subject?: string;
text?: string;
attachments?: Mail.Attachment[];
signOff?: string;
};

export const sendEmail = async (to: string | string[], mailOptions: MailOptions = {}) => {
const { subject, text, attachments, signOff = DEFAULT_SIGN_OFF } = mailOptions;
const { SMTP_HOST, SMTP_USER, SMTP_PASSWORD, SITE_EMAIL_ADDRESS } = process.env;

if (!SMTP_HOST || !SMTP_USER || !SMTP_PASSWORD || !SITE_EMAIL_ADDRESS) {
Expand All @@ -25,13 +34,11 @@ export const sendEmail = async (to, subject, text, attachments, signOff = DEFAUL
});

// Make sure it doesn't send real users mail from the dev server
if (!getIsProductionEnvironment()) {
to = process.env.DEV_EMAIL_ADDRESS;
}
const sendTo = getIsProductionEnvironment() ? to : (requireEnv('DEV_EMAIL_ADDRESS') as string);

return transporter.sendMail({
from: SITE_EMAIL_ADDRESS,
to,
to: sendTo,
subject,
attachments,
text: `${text}\n${signOff}`,
Expand Down
21 changes: 19 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9847,7 +9847,6 @@ __metadata:
moment-timezone: ^0.5.28
morgan: ^1.9.0
multer: ^1.4.3
nodemailer: ^4.7.0
npm-run-all: ^4.1.5
nyc: ^15.1.0
public-ip: ^2.5.0
Expand Down Expand Up @@ -10446,7 +10445,9 @@ __metadata:
"@aws-sdk/credential-providers": ^3.341.0
"@aws-sdk/lib-storage": ^3.348.0
"@tupaia/utils": 1.0.0
"@types/nodemailer": ^6.4.13
cookie: ^0.5.0
nodemailer: ^6.9.7
puppeteer: ^15.4.0
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -11758,6 +11759,15 @@ __metadata:
languageName: node
linkType: hard

"@types/nodemailer@npm:^6.4.13":
version: 6.4.13
resolution: "@types/nodemailer@npm:6.4.13"
dependencies:
"@types/node": "*"
checksum: fd27d57d5801aaa7594d3bab748aedb1addc0c3a8ff9a21ea7675eec0e7e99cc477d05264b757b97691612fcfab37e52ded6c0725a700a90ad24fc7829dcc641
languageName: node
linkType: hard

"@types/normalize-package-data@npm:^2.4.0":
version: 2.4.0
resolution: "@types/normalize-package-data@npm:2.4.0"
Expand Down Expand Up @@ -32775,13 +32785,20 @@ __metadata:
languageName: node
linkType: hard

"nodemailer@npm:^4.6.7, nodemailer@npm:^4.7.0":
"nodemailer@npm:^4.6.7":
version: 4.7.0
resolution: "nodemailer@npm:4.7.0"
checksum: 33f8774cd1883c693b4cafe66eb599e2351c3e0dfa29f4d37dcfcc26ad789490e9cede64784f4cd79db8ee7675381aafb9e52243859977a5c1ecd2fff6607d97
languageName: node
linkType: hard

"nodemailer@npm:^6.9.7":
version: 6.9.7
resolution: "nodemailer@npm:6.9.7"
checksum: 0cf66d27aed3bd2cbdff9939402cec3d2119c31b2b9ff4af3bcd59f48287ea75b90c0ce2cd9eb0df838164972cd25581b4b723c91fd673e2608bcb28445ccb1b
languageName: node
linkType: hard

"nodemon@npm:^2.0.4":
version: 2.0.4
resolution: "nodemon@npm:2.0.4"
Expand Down