Created
June 5, 2017 17:40
-
-
Save jyntran/0d2d8bfe1ced972beea0ce750aa3c692 to your computer and use it in GitHub Desktop.
Meteor + ReactJS Contact Form with reCAPTCHA
This file contains hidden or 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
import React, { Component } from 'react'; | |
import { Meteor } from 'meteor/meteor'; | |
function Status(props) { | |
const success = props.success; | |
const error = props.error; | |
console.log(props); | |
if (error) { | |
return ( | |
<div className="message error contact-message" data-component="message">{error.message}<span className="close small"></span></div> | |
); | |
} else if (success) { | |
return ( | |
<div className="message success contact-message" data-component="message">Success! Your message has been sent.<span className="close small"></span></div> | |
); | |
} else { return null; } | |
} | |
export default class ContactSection extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
nameVal: '', | |
emailVal: '', | |
messageVal: '' | |
} | |
this.handleNameChange = this.handleNameChange.bind(this); | |
this.handleEmailChange = this.handleEmailChange.bind(this); | |
this.handleMessageChange = this.handleMessageChange.bind(this); | |
this.handleSubmit = this.handleSubmit.bind(this); | |
this.handleClearForm = this.handleClearForm.bind(this); | |
this.handleClearStatus = this.handleClearStatus.bind(this); | |
this.handleError = this.handleError.bind(this); | |
this.handleSuccess = this.handleSuccess.bind(this); | |
} | |
componentDidMount() { | |
Meteor.startup(function() { | |
reCAPTCHA.config({ | |
publickey: 'your_public_key_from_google', | |
//hl: 'ja' // optional display language | |
}); | |
}); | |
} | |
handleNameChange(e) { | |
this.setState({nameVal: e.target.value}); | |
} | |
handleEmailChange(e) { | |
this.setState({emailVal: e.target.value}); | |
} | |
handleMessageChange(e) { | |
this.setState({messageVal: e.target.value}); | |
} | |
handleSubmit(e) { | |
e.preventDefault(); | |
let form = this; | |
this.handleClearStatus(); | |
console.log(this.state); | |
var formData = { | |
name: this.state.nameVal, | |
email: this.state.emailVal, | |
message: this.state.messageVal | |
} | |
var captchaData = grecaptcha.getResponse(); | |
console.log(captchaData); | |
Meteor.call('sendEmail', formData, captchaData, function(err){ | |
// reset the captcha | |
grecaptcha.reset(); | |
if (err) { | |
//console.log('Error', err); | |
form.handleError(err); | |
} else { | |
//console.log('Success: email sent'); | |
form.handleSuccess(); | |
} | |
}) | |
} | |
handleClearForm(e) { | |
e.preventDefault(); | |
this.setState({ | |
nameVal: '', | |
emailVal: '', | |
messageVal: '' | |
}); | |
} | |
handleError(e) { | |
this.setState({error: e}); | |
} | |
handleSuccess(e) { | |
this.setState({success: true}); | |
} | |
handleClearStatus(e) { | |
this.setState({ | |
error: false, | |
success: false | |
}); | |
} | |
render() { | |
return ( | |
<div className="row align-center"> | |
<div className="col col-8"> | |
<h2>Contact</h2> | |
<form method="post" action="" className="form" onSubmit={this.handleSubmit}> | |
<div className="form-item"> | |
<label>Name:</label> | |
<input required type="text" name="name" value={this.state.nameVal} onChange={this.handleNameChange} /> | |
</div> | |
<div className="form-item"> | |
<label>Email:</label> | |
<input required type="email" name="email" value={this.state.emailVal} onChange={this.handleEmailChange} /> | |
</div> | |
<div className="form-item"> | |
<label>Message:</label> | |
<textarea required rows="6" value={this.state.messageVal} onChange={this.handleMessageChange}></textarea> | |
</div> | |
<div className="form-item"> | |
<div className="g-recaptcha" data-sitekey="your_public_key_from_google"></div> | |
</div> | |
<div className="form-item form-buttons contact-form-buttons"> | |
<button className="button" type="submit">Submit</button> | |
<button className="button secondary" onClick={this.handleClearForm}>Clear All</button> | |
<Status success={this.state.success} error={this.state.error} /> | |
</div> | |
</form> | |
</div> | |
</div> | |
); | |
} | |
} |
This file contains hidden or 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
import { Email } from 'meteor/email'; | |
Meteor.startup(function() { | |
process.env.MAIL_URL='smtp://DOMAIN:[email protected]:587'; | |
reCAPTCHA.config({ | |
privatekey: 'your_private_key_from_google' | |
}); | |
}); | |
if (Meteor.isServer) { | |
Meteor.methods({ | |
sendEmail: function(formData, captchaData) { | |
console.log('Meteor sendEmail'); | |
// captcha verification | |
var verifyCaptchaResponse = reCAPTCHA.verifyCaptcha(this.connection.clientAddress, captchaData); | |
if (!verifyCaptchaResponse.success) { | |
console.log('reCAPTCHA check failed!', verifyCaptchaResponse); | |
throw new Meteor.Error(422, 'reCAPTCHA Failed: ' + verifyCaptchaResponse.error); | |
} else | |
console.log('reCAPTCHA verification passed!'); | |
// make sure all aruments are strings | |
check([formData.name, formData.email, formData.message], [String]); | |
// replace line breaks for html | |
var htmlMessage = formData.message; | |
htmlMessage = htmlMessage.replace(/(?:\r\n|\r|\n)/g, '<br />'); | |
Email.send({ | |
to: "recipient_email", | |
from: formData.email, | |
subject: "Contact", | |
html: "<p><b>Message from " + formData.name + " (" + formData.email + "):</b></p><p>" + htmlMessage + "</p>", | |
text: "Message from " + formData.name + " (" + formData.email + "):\n\n" + formData.message | |
}); | |
console.log('sendEmail success'); | |
return true; | |
} | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment