mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 10:22:16 +00:00
refator(api): drop useless SES SDK (#65496)
This commit is contained in:
committed by
GitHub
parent
1fb20ded39
commit
7b8273e0e0
@@ -4,7 +4,6 @@
|
||||
"url": "https://github.com/freeCodeCamp/freeCodeCamp/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-ses": "3.1019.0",
|
||||
"@fastify/accepts": "5.0.4",
|
||||
"@fastify/cookie": "11.0.2",
|
||||
"@fastify/csrf-protection": "7.1.0",
|
||||
|
||||
+2
-6
@@ -18,8 +18,7 @@ import addFormats from 'ajv-formats';
|
||||
import prismaPlugin from './db/prisma.js';
|
||||
import cookies from './plugins/cookies.js';
|
||||
import cors from './plugins/cors.js';
|
||||
import { NodemailerProvider } from './plugins/mail-providers/nodemailer.js';
|
||||
import { SESProvider } from './plugins/mail-providers/ses.js';
|
||||
import { createMailProvider } from './plugins/mail-providers/nodemailer.js';
|
||||
import mailer from './plugins/mailer.js';
|
||||
import redirectWithMessage from './plugins/redirect-with-message.js';
|
||||
import security from './plugins/security.js';
|
||||
@@ -36,7 +35,6 @@ import * as protectedRoutes from './routes/protected/index.js';
|
||||
|
||||
import {
|
||||
API_LOCATION,
|
||||
EMAIL_PROVIDER,
|
||||
FCC_ENABLE_DEV_LOGIN_MODE,
|
||||
FCC_ENABLE_SWAGGER_UI,
|
||||
FCC_ENABLE_SHADOW_CAPTURE,
|
||||
@@ -135,9 +133,7 @@ export const build = async (
|
||||
clientKey: GROWTHBOOK_FASTIFY_CLIENT_KEY
|
||||
});
|
||||
|
||||
const provider =
|
||||
EMAIL_PROVIDER === 'ses' ? new SESProvider() : new NodemailerProvider();
|
||||
void fastify.register(mailer, { provider });
|
||||
void fastify.register(mailer, { provider: createMailProvider() });
|
||||
|
||||
// Swagger plugin
|
||||
if (FCC_ENABLE_SWAGGER_UI ?? fastify.gb.isOn('swagger-ui')) {
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
import nodemailer, { Transporter } from 'nodemailer';
|
||||
|
||||
import { MailProvider, SendEmailArgs } from '../mailer.js';
|
||||
import { MAILPIT_HOST } from '../../utils/env.js';
|
||||
import {
|
||||
EMAIL_PROVIDER,
|
||||
MAILPIT_HOST,
|
||||
SES_SMTP_HOST,
|
||||
SES_SMTP_USERNAME,
|
||||
SES_SMTP_PASSWORD
|
||||
} from '../../utils/env.js';
|
||||
|
||||
export type NodemailerConfig = {
|
||||
host: string;
|
||||
port: number;
|
||||
secure: boolean;
|
||||
auth: { user: string; pass: string };
|
||||
tls?: { rejectUnauthorized: boolean };
|
||||
};
|
||||
|
||||
/**
|
||||
* NodemailerProvider is a wrapper around nodemailer that provides a clean
|
||||
@@ -11,22 +25,12 @@ export class NodemailerProvider implements MailProvider {
|
||||
private transporter: Transporter;
|
||||
|
||||
/**
|
||||
* Sets up nodemailer, with hardcoded configuration. This is intended for
|
||||
* use in development with Mailpit.
|
||||
* Sets up nodemailer with the provided configuration.
|
||||
*
|
||||
* @param config - The nodemailer transport configuration.
|
||||
*/
|
||||
constructor() {
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host: MAILPIT_HOST,
|
||||
secure: false,
|
||||
port: 1025,
|
||||
auth: {
|
||||
user: 'test',
|
||||
pass: 'test'
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
});
|
||||
constructor(config: NodemailerConfig) {
|
||||
this.transporter = nodemailer.createTransport(config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,3 +53,26 @@ export class NodemailerProvider implements MailProvider {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mail provider based on the EMAIL_PROVIDER environment variable.
|
||||
*/
|
||||
export function createMailProvider(): NodemailerProvider {
|
||||
return EMAIL_PROVIDER === 'ses'
|
||||
? new NodemailerProvider({
|
||||
host: SES_SMTP_HOST,
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: SES_SMTP_USERNAME ?? '',
|
||||
pass: SES_SMTP_PASSWORD ?? ''
|
||||
}
|
||||
})
|
||||
: new NodemailerProvider({
|
||||
host: MAILPIT_HOST,
|
||||
port: 1025,
|
||||
secure: false,
|
||||
auth: { user: 'test', pass: 'test' },
|
||||
tls: { rejectUnauthorized: false }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import {
|
||||
SESClient,
|
||||
SESClientConfig,
|
||||
SendEmailCommand
|
||||
} from '@aws-sdk/client-ses';
|
||||
|
||||
import { MailProvider, SendEmailArgs } from '../mailer.js';
|
||||
import { SES_ID, SES_SECRET, SES_REGION } from '../../utils/env.js';
|
||||
|
||||
/**
|
||||
* SESProvider is a wrapper around nodemailer that provides a clean interface
|
||||
* for sending email.
|
||||
*/
|
||||
export class SESProvider implements MailProvider {
|
||||
private client: SESClient;
|
||||
|
||||
/**
|
||||
* Sets up SESClient and configures it with keys pulled from environment.
|
||||
*/
|
||||
constructor() {
|
||||
if (!SES_ID || !SES_SECRET || !SES_REGION) {
|
||||
throw new Error('Email service is set to SES but missing required keys.');
|
||||
}
|
||||
const awsConfig: SESClientConfig = {
|
||||
credentials: {
|
||||
accessKeyId: SES_ID,
|
||||
secretAccessKey: SES_SECRET
|
||||
},
|
||||
region: SES_REGION
|
||||
};
|
||||
this.client = new SESClient(awsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email using the SES sdk.
|
||||
*
|
||||
* @param param Email options.
|
||||
* @param param.to Email address to send to.
|
||||
* @param param.from Email address to send from.
|
||||
* @param param.subject Email subject.
|
||||
* @param param.text Email body (raw text only).
|
||||
* @param param.cc [Optional] Email address to CC.
|
||||
*/
|
||||
async send({ to, from, subject, text, cc }: SendEmailArgs) {
|
||||
const opts = new SendEmailCommand({
|
||||
Destination: {
|
||||
ToAddresses: [to],
|
||||
CcAddresses: cc ? [cc] : []
|
||||
},
|
||||
Message: {
|
||||
Subject: {
|
||||
Data: subject,
|
||||
Charset: 'UTF-8'
|
||||
},
|
||||
Body: {
|
||||
Text: {
|
||||
Charset: 'UTF-8',
|
||||
Data: text
|
||||
}
|
||||
}
|
||||
},
|
||||
Source: from
|
||||
});
|
||||
|
||||
await this.client.send(opts);
|
||||
}
|
||||
}
|
||||
+15
-8
@@ -94,12 +94,18 @@ assert.ok(
|
||||
);
|
||||
|
||||
if (process.env.FREECODECAMP_NODE_ENV !== 'development') {
|
||||
assert.ok(process.env.SES_ID);
|
||||
assert.ok(process.env.SES_SECRET);
|
||||
assert.ok(
|
||||
process.env.SES_SMTP_USERNAME,
|
||||
'SES_SMTP_USERNAME is required in production.'
|
||||
);
|
||||
assert.ok(
|
||||
process.env.SES_SMTP_PASSWORD,
|
||||
'SES_SMTP_PASSWORD is required in production.'
|
||||
);
|
||||
assert.notEqual(
|
||||
process.env.SES_SECRET,
|
||||
'ses_secret_from_aws',
|
||||
'The SES secret should be changed from the default value.'
|
||||
process.env.SES_SMTP_PASSWORD,
|
||||
'ses_smtp_password_from_aws',
|
||||
'The SES SMTP password should be changed from the default value.'
|
||||
);
|
||||
assert.ok(process.env.COOKIE_DOMAIN);
|
||||
assert.notEqual(process.env.COOKIE_SECRET, 'a_cookie_secret');
|
||||
@@ -209,9 +215,10 @@ export const SENTRY_ENVIRONMENT =
|
||||
export const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN;
|
||||
export const COOKIE_SECRET = process.env.COOKIE_SECRET;
|
||||
export const JWT_SECRET = process.env.JWT_SECRET;
|
||||
export const SES_ID = process.env.SES_ID;
|
||||
export const SES_SECRET = process.env.SES_SECRET;
|
||||
export const SES_REGION = process.env.SES_REGION || 'us-east-1';
|
||||
export const SES_SMTP_USERNAME = process.env.SES_SMTP_USERNAME;
|
||||
export const SES_SMTP_PASSWORD = process.env.SES_SMTP_PASSWORD;
|
||||
export const SES_SMTP_HOST =
|
||||
process.env.SES_SMTP_HOST || 'email-smtp.us-east-1.amazonaws.com';
|
||||
export const SHOW_UPCOMING_CHANGES =
|
||||
process.env.SHOW_UPCOMING_CHANGES === 'true';
|
||||
export const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
"SES_ID",
|
||||
"SES_REGION",
|
||||
"SES_SECRET",
|
||||
"SES_SMTP_HOST",
|
||||
"SES_SMTP_PASSWORD",
|
||||
"SES_SMTP_USERNAME",
|
||||
"SHOW_UPCOMING_CHANGES",
|
||||
"SOCRATES_API_KEY",
|
||||
"SOCRATES_ENDPOINT",
|
||||
@@ -73,6 +76,9 @@
|
||||
"SES_ID",
|
||||
"SES_REGION",
|
||||
"SES_SECRET",
|
||||
"SES_SMTP_HOST",
|
||||
"SES_SMTP_PASSWORD",
|
||||
"SES_SMTP_USERNAME",
|
||||
"SHOW_UPCOMING_CHANGES",
|
||||
"SOCRATES_API_KEY",
|
||||
"SOCRATES_ENDPOINT",
|
||||
|
||||
Generated
+17
-886
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -70,13 +70,13 @@ FCC_API_LOG_LEVEL=info
|
||||
FCC_API_LOG_TRANSPORT=pretty
|
||||
|
||||
# Email
|
||||
# use ses in production
|
||||
# use ses in production, nodemailer for local development (with Mailpit)
|
||||
EMAIL_PROVIDER=nodemailer
|
||||
# SES_ID needs to be empty for now, since the api-server will use SES in testing
|
||||
# if it is set.
|
||||
SES_ID=
|
||||
SES_SECRET=ses_secret_from_aws
|
||||
SES_REGION=us-east-1
|
||||
# SES SMTP credentials (required in production)
|
||||
# Generate these from AWS IAM: https://docs.aws.amazon.com/ses/latest/dg/smtp-credentials.html
|
||||
SES_SMTP_USERNAME=
|
||||
SES_SMTP_PASSWORD=ses_smtp_password_from_aws
|
||||
SES_SMTP_HOST=email-smtp.us-east-1.amazonaws.com
|
||||
|
||||
# ---------------------
|
||||
# Client
|
||||
|
||||
Reference in New Issue
Block a user