Skip to content

Instantly share code, notes, and snippets.

@diegovalle diegovalle/index.js
Last active Aug 23, 2018

Embed
What would you like to do?
openwhisk contact form with recaptcha
// Contact form for www.ilsevalle.com
// The form requieres 4 parameters:
// SENDGRID_API - Sendgrid API key to send emails
// EMAIL_SENDER - address from which the mail is sent
// SEND_TO - address to which the mail is sent
// RECAPTCHA_SECRET - Server secret from Google's recaptcha service
// TIMEZONE - time zone in which to display the submission time (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
const request = require('request');
const sgMail = require('@sendgrid/mail');
function parseBody(body) {
let sysData = new Date();
return msg = {
to: body.SEND_TO,
from: body.EMAIL_SENDER,
replyTo: body.email,
subject: "[Contat Form @ ilsevalle.com] new message from " + body.name,
text: 'Name: ' + body.name +
'\n\nEmail: ' + body.email +
'\n\nSubmitted: ' + sysData.toLocaleString('en-US',
{ timeZone: body.TIMEZONE }) +
'\n\n----\n\n' + body.message,
};
}
function validateEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
function checkRecaptcha(recaptcha_challenge, recaptcha_secret, ip) {
return new Promise((resolve, reject) => {
let errors = [];
request.post(' https://www.google.com/recaptcha/api/siteverify', {
form:{
secret: recaptcha_secret,
response: recaptcha_challenge,
ip: ip
}
}, (err, resp, body) => {
if(!JSON.parse(body).success) {
console.log(body);
errors.push('You did not fill out the recaptcha or resubmitted the form.');
}
resolve({errors:errors});
});
});
}
function send_mail(args) {
return new Promise((resolve, reject) => {
sgMail.send(parseBody(args)).then(() => {
resolve({ body: {success: "true",
message: "Message Sent"},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
});
}).catch(e => {
console.log("sendgrid catch error");
console.error(e.toString());
reject({
body: {success: "false",
message: "Sendgrid error"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
});
});
})
}
const wait = ms => new Promise(r => setTimeout(r, ms));
const sendRetry = (fn, args, delay, times) => new Promise((resolve, reject) => {
fn(args)
.then(resolve)
.catch((reason) => {
console.log("retrying "+ times);
if (times - 1 > 0) {
return wait(delay)
.then(sendRetry.bind(null, fn, args, delay, times - 1))
.then(resolve)
.catch(reject);
}
return resolve({
body: {success: "false",
message: "Sendgrid error"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
});
});
});
async function main(args) {
if(args.__ow_method !== "post") {
return {
body: {success: "false",
message: "Only POST request are accepted"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
};
}
// Check arguments
if ((!args.name) || (!args.email) || (!args.message))
return {
body: {success: "false",
message: "Error validating data"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
};
if (!validateEmail(args.email))
return {
body: {success: "false",
message: "Email is not valid"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
};
if(!args.recaptcha) {
return {
body: {success: "false",
message: "Missing recaptcha response"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
};
}
// Check that it's not a bot with Google's recaptcha
ip = args.__ow_headers["x-client-ip"];
const recaptcha_check = await checkRecaptcha(args.recaptcha,
args.RECAPTCHA_SECRET, ip);
if(recaptcha_check.errors.length) {
return {
body: {success: "false",
message: "Failed recaptcha challenge"},
statusCode:400,
headers:{ 'Content-Type': 'application/json'}
};
}
// Send email with SendGrid
sgMail.setApiKey(args.SENDGRID_API);
return sendRetry(send_mail, args, 7000, 5);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.