ctrlplusb / react-universally

A starter kit for universal react applications.
MIT License
1.69k stars 243 forks source link

implementation of a mailHandler #417

Closed mschipperheyn closed 7 years ago

mschipperheyn commented 7 years ago

I have implemented a mailhandler using nodemailer that, as a default, can be used to implement a standard contact form. I thought I would share it here. If there is interest, I can implement the handler in the codebase.

server/index.js

[...]
import bodyParser from 'body-parser';
import mailHandler from './middleware/mailHandler';

[...]
// Security middlewares.
app.use(...security);

// Process form body
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));

// parse application/json
app.use(bodyParser.json());

[...]

//Processing mail
app.post('/contact', mailHandler);

// The React application middleware.
app.get('*', reactApplication);

config/values.js

const values = {
    [...]
    mail: true,
},
mail: {
  defaultFrom: 'default@fromaddress.com',
  defaultTo: 'default@toaddress.com',
  config:{//see nodemailer for other options
      service: 'Gmail',
      auth:{
          user: 'you@gmail.com',
          pass: '*****'
      }
  },
},

server/middleware/mailHandler

/**
 * Send mail with the mailHandler by using for example: fetch. E.g.

 export function sendMessage(name, email, message){
     return async dispatch => {

         const res = await fetch('/contact', {
             method : 'POST',
             headers: {
                 'Content-Type': 'application/json'
             },
             body: JSON.stringify({
                 name,
                 email,
                 message
             })
         });

         const json = await res.json();

         return json;

     }
  }

 * fields:
 * name
 * email
 * message
 * topic
 * subject: The subject for the email, default: Mail form
 * from:    The from address, default: config.defaultFrom
 * to:      The to address, default: config.defaultTo
 *
 * Configuration (config/values.js):
 * clientConfigFilter.mail: true
 * mail.config: use nodemailer configuration options: https://nodemailer.com/
 */

import nodemailer from 'nodemailer';
import smtpTransport from 'nodemailer-smtp-transport';
import config from '../../config';

let transporter = nodemailer.createTransport(config('mail.config'));

console.log('Nodemailer configured');

function sendMail(from, to, subject, text){
    transporter.sendMail({
        from,
        to,
        subject,
        text
    }, (error, info) => {
        if(error){
            console.error(`mail error. from: ${from}, to: ${to}, subject: ${subject}, text: ${text}`, error);

            return {
                error
            };
        }

        console.info(`mail sent from ${from} to ${to} - ${Date.now()}`);

        return {
            success: info.response
        };

    });
}

export default function handleMail(req, res) {

    const name = req.body.name;
    const email = req.body.email;
    const message = req.body.message;
    const topic = req.body.topic;

    const text = `name: ${name}\nfrom: ${email}\nsubject: ${topic}\nmessage:\n${message}`;

    const subject = req.body.subject || 'Mail form';
    const from = req.body.from || config('mail.defaultFrom');
    const to = req.body.to || config('mail.defaultTo');

    res.json(sendMail(from, to, subject, text));

}

contactActions.js

export function sendMessage(name, email, message){
    return async dispatch => {

        const res = await fetch('/contact', {
            method : 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                name,
                email,
                message
            })
        });

        const json = await res.json();

        return json;

    }
}
birkir commented 7 years ago

Great work. The thing is that we're trying to make react-universally as lean as possible, so I don't think we would include something like this in the codebase at this time.

But on that topic, I recommend mailgun as a service for email things.

diondirza commented 7 years ago

I also using mailgun here. lol

mschipperheyn commented 7 years ago

Yeah, mailgun can be easily configured using this base (https://github.com/orliesaurus/nodemailer-mailgun-transport) as well. Totally get lean and mean. So, this issue can be used as a reference for anyone looking to shave a few hours of.