Skip to content
This repository was archived by the owner on Dec 31, 2020. It is now read-only.
Open
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
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
All Open Source for Good projects follow Free Code Camp's [contributor's guide](https://github.com/FreeCodeCamp/FreeCodeCamp/blob/staging/CONTRIBUTING.md).
All Open Source for Good projects follow Free Code Camp's [contributor's guide](https://github.com/freeCodeCamp/freeCodeCamp/blob/master/CONTRIBUTING.md).
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ With Mail for Good you can:

### Performance

We're currently sending weekly email blasts of over 800,000 emails in 4 hours on a $10 per month Digital Ocean VPS with 1gb memory and 1 core processor.
We're currently sending weekly email blasts of over 800,000 emails in 4 hours on a $10 per month Digital Ocean VPS with 1 GB memory and 1 core processor.

Mail for Good is fast and scales to the rate limit enforced by AWS.

Expand Down
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Mail for Good",
"description": "An open source email campaign management tool for nonprofits",
"repository": "https://github.com/freeCodeCamp/mail-for-good",
"repository": "https://github.com/saviorand/mail-for-good/tree/heroku/stable",
"logo": "https://raw.githubusercontent.com/freeCodeCamp/assets/master/assets/logos/fcc_puck600.png",
"keywords": ["email", "nonprofit", "freecodecamp"],
"formation": {
Expand Down
4 changes: 2 additions & 2 deletions client/containers/lists/ImportCSV.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export class ImportCSVComponent extends Component {
handleNewFile(file) {

const callback = results => {
if (!results.meta.fields.some(field => field.toLowerCase() === 'email')) { // Check if any header field is labeled email
this.handleErrorWithFile('Please ensure the CSV file contains at least one column field labeled "email" (check the first row)');
if (!results.meta.fields.some(field => field.toLowerCase() === 'email' || 'e-mail')) { // Check if any header field is labeled email
this.handleErrorWithFile('Please ensure the CSV file contains at least one column field labeled "email/e-mail" (check the first row)');
} else {

const errors = results.errors;
Expand Down
8 changes: 4 additions & 4 deletions docs/aws_deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Select Ubuntu as your operating system.

![](resources/deploy_images/5.png)

Here is the preselected instance is fine. (t2.micro instances are eligible for the free tier).
Here the preselected instance is fine. (t2.micro instances are eligible for the free tier).

![](resources/deploy_images/6.png)

Expand Down Expand Up @@ -235,8 +235,8 @@ In the left menu, select **Dashboard**. Now select **Enable API**, search for `G
In the left menu, select **Credentials**. Then click **Create Credentials** > **OAuth client ID**.

Select **Web Application**. Name it as you wish
- Under **Authorised Javascript Origins** put the “Public DNS (IPv4)” you received from Amazon earlier.
- Under **Authorised redirect URIs** put your “Public DNS (IPv4)” followed by `/auth/google/callback`.
- Under **Authorized Javascript Origins** put the “Public DNS (IPv4)” you received from Amazon earlier.
- Under **Authorized redirect URIs** put your “Public DNS (IPv4)” followed by `/auth/google/callback`.

![](resources/deploy_images/google_origins.png)

Expand Down Expand Up @@ -274,7 +274,7 @@ GOOGLE_CONSUMER_KEY=
# E.g abcdefQVw1ghijzeaQklmnop
GOOGLE_CONSUMER_SECRET=
# The URL Google will send you back to after logging in.
# It must match what is under "Authorised redirect URIs" in the Google Dashboard exactly
# It must match what is under "Authorized redirect URIs" in the Google Dashboard exactly
GOOGLE_CALLBACK=
# A random, preferably long sequence of characters. You do not need to remember this.
ENCRYPTION_PASSWORD=
Expand Down
4 changes: 2 additions & 2 deletions docs/docs-hugo-templates/content/google-api-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ date: 2017-09-30T16:56:37-05:00
1. Login to [Google API Manager](https://console.developers.google.com/apis/).
2. In the left menu, select **Dashboard**. Now select **Enable API**, search for `Google+` and select it. At the top of the screen, ensure it's enabled by clicking on **Enable**.
3. In the left menu, select **Credentials**. Then click **Create Credentials** > **OAuth client ID**.
4. Select **Web Application**. Name is as you wish, but under **Authorised Javascript Origins** put `http://localhost:8080`, and under **Authorised redirect URIs** put `http://localhost:8080/auth/google/callback`.
5. Click **Create**. You will now have a Client ID and Client Secret. In your .env file, put the Client ID as your GOOGLE_CONSUMER_KEY, and the Client Secret as your GOOGLE_CONSUMER_SECRET.
4. Select **Web Application**. Name is as you wish, but under **Authorized Javascript Origins** put `http://localhost:8080`, and under **Authorized redirect URIs** put `http://localhost:8080/auth/google/callback`.
5. Click **Create**. You will now have a Client ID and Client Secret. In your .env file, put the Client ID as your GOOGLE_CONSUMER_KEY, and the Client Secret as your GOOGLE_CONSUMER_SECRET.
4 changes: 2 additions & 2 deletions docs/docs-hugo-templates/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ With Mail for Good you can:
- Send email campaigns of unlimited size.
- Import emails saved in CSV format.
- Create templates to reuse for convenience when sending email campaigns.
- Track bounce rate and other standard metrics. You can also insert tracking pixels and unsubcribe links at the click of a button.
- Track bounce rate and other standard metrics. You can also insert tracking pixels and unsubscribe links at the click of a button.
- Add custom fields to imported email lists such as names or cities.
- Grant other users (limited or otherwise) permissions to use your account on your behalf.
- Add embedded HTML newsletter sign up forms to your site. These are snippets of code that will let your users sign up with you at the click of a button.
Expand All @@ -46,4 +46,4 @@ Mail for Good is fast and scales to the rate limit enforced by AWS.

## Why are we doing this?

We want to help nonprofits manage their email campaigns as inexpensively as possible, and have full control over their data.
We want to help nonprofits manage their email campaigns as inexpensively as possible, and have full control over their data.
30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
"name": "nonprofit-email-service",
"version": "1.0.0",
"description": "A cost effective, open source solution to sending mass emails",
"main": "index.js",
"engines": {
"npm": "5",
"node": "7.6.0"
"node": "8.x"
},
"main": "index.js",
"scripts": {
"check-env-file": "python ./tools/setup/initial_setup.py",
"client:lint": "esw webpack.config.* client tools --color",
Expand All @@ -25,7 +24,7 @@
"test:server:functional": "babel-tape-runner -r dotenv/config server/tests/**/*.func.js | node_modules/.bin/tap-spec",
"test:client": "mocha --require tools/testClientSetup.js tools/testSetup.js \"client/**/*.spec.js\"",
"test": "npm run test:client && npm run test:server",
"updateDB":"node_modules/.bin/sequelize db:migrate --env production"
"updateDB": "node_modules/.bin/sequelize db:migrate --env production"
},
"repository": {
"type": "git",
Expand All @@ -41,14 +40,15 @@
"admin-lte": "^2.3.6",
"async": "^2.4.1",
"aws-sdk": "^2.69.0",
"bcrypt": "^1.0.3",
"bcrypt": "^3.0.0",
"bluebird": "^3.5.0",
"body-parser": "^1.17.2",
"bootstrap": "^3.3.7",
"bootstrap": "^3.4.1",
"bottleneck": "^1.15.1",
"connect-history-api-fallback": "^1.3.0",
"connect-redis": "^3.3.0",
"cookie-parser": "^1.4.3",
"cookie-session": "^1.4.0",
"csv": "^1.1.0",
"debug": "^2.6.8",
"dompurify": "^0.9.0",
Expand All @@ -57,21 +57,21 @@
"express": "^4.15.3",
"express-session": "^1.15.3",
"geoip-lite": "^1.2.1",
"handlebars": "^4.0.10",
"helmet": "^3.6.1",
"handlebars": "^4.7.6",
"helmet": "^3.22.0",
"highcharts": "^5.0.6",
"jquery": "^3.2.1",
"lodash": "^4.15.0",
"jquery": "^3.5.1",
"lodash": "^4.17.15",
"moment": "^2.18.1",
"multer": "^1.2.0",
"npm-run-all": "^4.0.2",
"papaparse": "^4.3.3",
"passport": "^0.3.2",
"passport-google-oauth": "^1.0.0",
"passport-google-oauth": "^2.0.0",
"passport-local": "^1.0.0",
"pg": "^6.2.4",
"pug": "^2.0.0-rc.4",
"quill": "^1.2.6",
"quill": "^1.3.7",
"react": "^15.6.1",
"react-bootstrap": "^0.31.0",
"react-bootstrap-table": "^3.4.0",
Expand All @@ -96,14 +96,14 @@
"sequelize": "^3.24.3",
"sequelize-cli": "^4.0.0",
"shortid": "^2.2.8",
"slug": "^0.9.1",
"slug": "^0.9.4",
"socket.io": "^2.0.3",
"sqs-consumer": "^3.6.0",
"ua-parser-js": "^0.7.10",
"webpack": "^2.6.1"
},
"devDependencies": {
"axios": "^0.16.2",
"axios": "^0.19.2",
"babel-cli": "^6.24.1",
"babel-core": "^6.25.0",
"babel-eslint": "^7.2.3",
Expand Down Expand Up @@ -136,7 +136,7 @@
"mocha": "^3.2.0",
"node-amazon-ses-simulator": "^1.0.1",
"node-mocks-http": "^1.6.2",
"node-sass": "^4.5.3",
"node-sass": "^4.14.1",
"react-addons-test-utils": "^15.6.0",
"react-fontawesome": "^1.6.1",
"redux-immutable-state-invariant": "^2.0.0",
Expand Down
6 changes: 2 additions & 4 deletions server/config/secrets.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ module.exports = {
secretAccessKey: process.env.AMAZON_SECRET_ACCESS_KEY || null
}
},
//


smtpServer: {
port: process.env.SMTP_TEST_PORT || '2025', // Linux envs disallo use of port <= 1024 without root
port: process.env.SMTP_TEST_PORT || '2025', // Linux envs disallow use of port <= 1024 without root
host: process.env.SMTP_TEST_HOST || '127.0.0.1'
},

Expand All @@ -20,5 +19,4 @@ module.exports = {
consumerSecret: process.env.GOOGLE_CONSUMER_SECRET,
callbackURL: process.env.GOOGLE_CALLBACK || 'http://localhost:8080/auth/google/callback'
},

};
15 changes: 9 additions & 6 deletions server/config/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
const express = require('express');
const passport = require('passport');
const helmet = require('helmet');

const cookieSession = require('cookie-session');
const configureSequelize = require('./sequelize');
const configureWebpackDevMiddleware = require('./webpack-dev-middleware');
const configureRedis = require('./redis');
Expand All @@ -23,11 +23,7 @@ module.exports = () => {
configureWebpackDevMiddleware(app);

// Configure redis, receiving connections to client, subscriber and publisher
const {
client,
subscriber,
publisher,
} = configureRedis();
const { client, subscriber, publisher } = configureRedis();

// Configure session handling with redis, through the client connection.
const { sessionMiddleware } = configureSession(client);
Expand All @@ -42,6 +38,13 @@ module.exports = () => {
app.use(passport.session()); // Use passport middleware for auth
app.use(helmet()); // Implements various security tweaks to http response headers

app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000,
keys: [process.env.COOKIE_SESSION]
})
);

app.use('/public', express.static(path.join(__dirname, '../../../public'))); // Serve /public static files when unauth
app.use('/dist', express.static(path.join(__dirname, '../../../dist'))); // Serve /dist static diles when auth

Expand Down
3 changes: 3 additions & 0 deletions server/controllers/campaign/email/amazon-ses/send-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ module.exports = (req, res) => {
? new AWS.SES({ accessKeyId: accessKey, secretAccessKey: secretKey, region, endpoint: 'http://localhost:9999' })
: new AWS.SES({ accessKeyId: accessKey, secretAccessKey: secretKey, region, apiVersion: '2010-12-01'});


//replace all variables by their names to not get their '{}' processed by wrapLink()
campaign.emailBody = campaign.emailBody.replace(/{{.*}}/gm,(match)=>{return match.slice(2,-2);});
// Modify email body for analytics
if (campaign.trackLinksEnabled) {
campaign.emailBody = wrapLink(campaign.emailBody, 'example-tracking-id', campaign.type, whiteLabelUrl);
Expand Down
2 changes: 1 addition & 1 deletion server/controllers/list/import-csv.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,4 @@ module.exports = (req, res, io) => {
.catch(err => {
res.status(400).send({ message: err.message });
});
};
};