Last active
August 23, 2018 00:20
-
-
Save diegovalle/49ed2908441fd94c170a498f2ab1554e to your computer and use it in GitHub Desktop.
openwhisk contact form with recaptcha
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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