Skip to content
Permalink
Browse files

V1.1 - A Number of Enhancement

1) Use PHPMailer to allow SMTP authentication
2) Extract Config Values to Env. Variables
3) Use bootstrap checkboxes when a required field's value is filled in
4) Clean up front-end code
5) Simplify back-end sendmail.php
  • Loading branch information...
jonmbake committed Mar 21, 2015
1 parent 846c2de commit f502b9ef0dcda710d4aca2738f75fc22f2e56699
@@ -0,0 +1,2 @@
.DS_STORE
/nbproject
@@ -3,32 +3,48 @@ bootstrap3-contact-form

Bootstrap 3 Contact Form with Captcha

A simple bootstrap 3 contact form using [SecureImage Captcha](https://github.com/dapphp/securimage).
A simple bootstrap 3 contact form using [SecureImage Captcha](https://github.com/dapphp/securimage). Submitted messages are sent to a specified email address using SMTP with support for SSL or TLS transport.

## Dependencies

* [Bootstrap 3](https://github.com/twbs/bootstrap) version >3.1
* PHP (version > 5.2.0) installed on your server **Must have gd library enabled**
### PHP
* version > 5.2.0 (with gd library enabled)
* [SecureImage Captcha](https://github.com/dapphp/securimage) Captcha (included in [library/vender/securimage/**](https://github.com/jonmbake/bootstrap3-contact-form/tree/master/library/vender/securimage))
* [PHPMailer](https://github.com/PHPMailer/PHPMailer) (included in [library/vender/php_mailer/**](https://github.com/jonmbake/bootstrap3-contact-form/tree/master/library/vender/php_mailer))

### HTML/JS
* [Bootstrap 3](https://github.com/twbs/bootstrap) version >3.1
* jQuery
* **The HTML for the contact form**, which can be extracted from index.html
* **Optional** [International Telephone Input](https://github.com/Bluefieldscom/intl-tel-input) (included in [assets/vender/intl-tel-input/**](https://github.com/jonmbake/bootstrap3-contact-form/tree/master/assets/vender/intl-tel-input))- This is used to validate and format the phone input field. Only need this if the phone field is present.

### Adding or Removing Fields
The Optional Fields of Title, Company and Website are commented out in *index.html*; to add these simply uncomment the the code in *index.html* and uncomment the corresponding values in $fields_req in sendmail.php. To add or remove additional fields from the contact form:
## Configuration

#### In the HTML
1. Add or remove the HTML element from the form (the *form-group*)
2. When adding, if the field is optional, then add the class `.optional` to the input within the form group
Configuration values to the contact form are passed in via *Environment Variables*. The following variables need to be defined:
| Name | Description |
|-------------------- | -------------------------------------------------------------------- |
| FEEDBACK_HOSTNAME | Host name for SMTP server |
| FEEDBACK_EMAIL | Email address to authenticate to SMTP server with |
| FEEDBACK_PASSWORD | Password to authenticate to SMTP server with |
| FEEDBACK_ENCRYPTION | If specified will use encryption. Valid values: TLS or SLL |
| FEEDBACK_SKIP_AUTH | **Optional** If specified, will not authenticate with email/password |

#### In sendmail.php
1. Add or remove an entry from the `$fields_req` array (map) in *sendmail.php* (if the field is required the map entry's value must be true, otherwise false)
Environment variables can be specified in a variety of ways. For example, if using *Apache* and *mod_env* is enabled, they can be specified in *.htaccess*:

### Further Configuration
* **Required** Change the MY_EMAIL constant in library/sendmail.php to the email address you want the contant form data to get submitted to. You can also change the email subject by editing EMAIL_SUBJECT.
* By default required field inputs are appended with an asterisk. If you want to remove this feature, add the class `.no-asterisk` to the required input of the form group.
```
SetEnv FEEDBACK_HOSTNAME smtp.gmail.com
SetEnv FEEDBACK_EMAIL me@gmail.com
SetEnv FEEDBACK_PASSWORD my!password!
SetEnv FEEDBACK_ENCRYPTION TLS
```

They can also be specified at the system level, usually in your *.profile* file for a Unix-based OS:

```
export FEEDBACK_HOSTNAME=smtp.gmail.com
export FEEDBACK_EMAIL=me@gmail.com
export FEEDBACK_PASSWORD=my!password!
export FEEDBACK_ENCRYPTION=TLS
```

## Check It Out
Demo: http://jonbake.com/demos/contact-form/

Blog Post: http://jonbake.com/blog/?p=115
@@ -1,96 +1,93 @@
$(document).ready(function() {
if ($("#phone").intlTelInput) {
$("#phone").intlTelInput({validationScript: "assets/vender/intl-tel-input/js/isValidNumber.js"});
$(".intl-tel-input.inside").css('width', '100%');
}
(function () {
var contactFormUtils = {
isValidEmail: function (email) {
var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return regex.test(email);
},
clearErrors: function () {
$('#emailAlert').remove();
$('#feedbackForm .help-block').hide();
$('#feedbackForm .form-group').removeClass('has-error');
},
clearForm: function () {
$('#feedbackForm .glyphicon').removeClass('glyphicon-check').addClass('glyphicon-unchecked').css({color: ''});
$('#feedbackForm input,textarea').val("");
},
addError: function ($input) {
var parentFormGroup = $input.parents('.form-group');
parentFormGroup.children('.help-block').show();
parentFormGroup.addClass('has-error');
},
addAjaxMessage: function(msg, isError) {
$("#feedbackSubmit").after('<div id="emailAlert" class="alert alert-' + (isError ? 'danger' : 'success') + '" style="margin-top: 5px;">' + $('<div/>').text(msg).html() + '</div>');
}
};

$('#feedbackForm input')
.not('.optional,.no-asterisk')
.after('<span class="glyphicon glyphicon-asterisk form-control-feedback"></span>');
$(document).ready(function() {
if ($("#phone").intlTelInput) {
$("#phone").intlTelInput({validationScript: "assets/vender/intl-tel-input/js/isValidNumber.js"});
$(".intl-tel-input.inside").css('width', '100%');
}

$("#feedbackSubmit").click(function() {
var $btn = $(this);
$btn.button('loading');
contactForm.clearErrors();
$("#feedbackSubmit").click(function() {
var $btn = $(this);
$btn.button('loading');
contactFormUtils.clearErrors();

//do a little client-side validation -- check that each field has a value and e-mail field is in proper format
var hasErrors = false;
$('#feedbackForm input,#feedbackForm textarea').not('.optional').each(function() {
var $this = $(this);
if (($this.is(':checkbox') && !$this.is(':checked')) || !$this.val()) {
//do a little client-side validation -- check that each field has a value and e-mail field is in proper format
var hasErrors = false;
$('#feedbackForm input,#feedbackForm textarea').not('.optional').each(function() {
var $this = $(this);
if (($this.is(':checkbox') && !$this.is(':checked')) || !$this.val()) {
hasErrors = true;
contactFormUtils.addError($(this));
}
});
var $email = $('#email');
if (!contactFormUtils.isValidEmail($email.val())) {
hasErrors = true;
contactForm.addError($(this));
contactFormUtils.addError($email);
}
});
var $email = $('#email');
if (!contactForm.isValidEmail($email.val())) {
hasErrors = true;
contactForm.addError($email);
}

var $phone = $('#phone');
if ($phone.val() && $phone.intlTelInput && !$phone.intlTelInput("isValidNumber")) {
hasErrors = true;
contactForm.addError($phone.parent());
}

//if there are any errors return without sending e-mail
if (hasErrors) {
$btn.button('reset');
return false;
}
var $phone = $('#phone');
if ($phone.val() && $phone.intlTelInput && !$phone.intlTelInput("isValidNumber")) {
hasErrors = true;
contactFormUtils.addError($phone.parent());
}

//send the feedback e-mail
$.ajax({
type: "POST",
url: "library/sendmail.php",
data: $("#feedbackForm").serialize(),
success: function(data) {
contactForm.addAjaxMessage(data.message, false);
contactForm.clearForm();
//get new Captcha on success
$('#captcha').attr('src', 'library/vender/securimage/securimage_show.php?' + Math.random());
},
error: function(response) {
contactForm.addAjaxMessage(response.responseJSON.message, true);
},
complete: function() {
//if there are any errors return without sending e-mail
if (hasErrors) {
$btn.button('reset');
return false;
}
});
return false;
});
$('#feedbackForm input').change(function () {
var asteriskSpan = $(this).siblings('.glyphicon-asterisk');
if ($(this).val()) {
asteriskSpan.css('color', '#00FF00');
} else {
asteriskSpan.css('color', 'black');
}
});
});

//namespace as not to pollute global namespace
var contactForm = {
isValidEmail: function (email) {
var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return regex.test(email);
},
clearErrors: function () {
$('#emailAlert').remove();
$('#feedbackForm .help-block').hide();
$('#feedbackForm .form-group').removeClass('has-error');
},
clearForm: function () {
$('.glyphicon-asterisk').css('color', 'black');
$('#feedbackForm input,textarea').val("");
},
addError: function ($input) {
var parentFormGroup = $input.parents('.form-group');
parentFormGroup.children('.help-block').show();
parentFormGroup.addClass('has-error');
},
addAjaxMessage: function(msg, isError) {
$("#feedbackSubmit").after('<div id="emailAlert" class="alert alert-' + (isError ? 'danger' : 'success') + '" style="margin-top: 5px;">' + $('<div/>').text(msg).html() + '</div>');
}
};
//send the feedback e-mail
$.ajax({
type: "POST",
url: "library/sendmail.php",
data: $("#feedbackForm").serialize(),
success: function(data) {
contactFormUtils.addAjaxMessage(data.message, false);
contactFormUtils.clearForm();
//get new Captcha on success
$('#captcha').attr('src', 'library/vender/securimage/securimage_show.php?' + Math.random());
},
error: function(response) {
contactFormUtils.addAjaxMessage(response.responseJSON.message, true);
},
complete: function() {
$btn.button('reset');
}
});
return false;
});
$('#feedbackForm input, #feedbackForm textarea').change(function () {
var checkBox = $(this).siblings('span.input-group-addon').children('.glyphicon');
if ($(this).val()) {
checkBox.removeClass('glyphicon-unchecked').addClass('glyphicon-check').css({color: 'green'});
} else {
checkBox.removeClass('glyphicon-check').addClass('glyphicon-unchecked').css({color: ''});
}
});
});
})();
@@ -33,49 +33,69 @@
<!-- EXTRACT FORM HERE =======> -->
<div class="container">
<div id="contact_form" class="row">
<div class="col-12 col-sm-12 col-lg-12">
<h2>Tell Us What You Think...</h2>
<p>We appreciate any feedback about your overall experience on our site or how to make it even better. Please fill in the below form with any comments and we will get back to you.</p>
<div class="col-md-12">
<h2>Contact Us</h2>
<form role="form" id="feedbackForm">
<div class="form-group has-feedback">
<label class="control-label" for="name">Name</label>
<input type="text" class="form-control input-sm" id="name" name="name" placeholder="Enter your name" />
<div class="form-group">
<label class="control-label" for="name">Name *</label>
<div class="input-group">
<input type="text" class="form-control" id="name" name="name" placeholder="Enter your name" />
<span class="input-group-addon"><i class="glyphicon glyphicon-unchecked form-control-feedback"></i></span>
</div>
<span class="help-block" style="display: none;">Please enter your name.</span>
</div>
<!-- UNCOMMENT HERE IF YOU WANT TITLE, COMPANY AND WEBSITE FIELDS - you must also uncomment values in $fields_req in sendmail.php
<!-- UNCOMMENT HERE IF YOU WANT TITLE, COMPANY, WEBSITE OR PHONE FIELDS - you must also uncomment values in $fields_req in sendmail.php
<div class="form-group">
<label class="control-label" for="title">Title</label>
<input type="text" class="form-control input-sm optional" id="title" name="title" />
<input type="text" class="form-control optional" id="title" name="title" />
</div>
<div class="form-group">
<label class="control-label" for="company">Company</label>
<input type="text" class="form-control input-sm optional" id="company" name="company" />
<input type="text" class="form-control optional" id="company" name="company" />
</div>
<div class="form-group">
<label class="control-label" for="website">Website</label>
<input type="url" class="form-control input-sm optional" id="website" name="website" />
<input type="url" class="form-control optional" id="website" name="website" />
</div>
-->
<div class="form-group has-feedback">
<div class="form-group">
<label class="control-label" for="phone">Phone</label>
<input type="tel" class="form-control input-sm optional" id="phone" name="phone" placeholder="Enter your phone (Optional)"/>
<input type="tel" class="form-control optional" id="phone" name="phone" placeholder="Enter your phone (Optional)"/>
<span class="help-block" style="display: none;">Please enter a valid phone number.</span>
</div>
<div class="form-group has-feedback">
<label class="control-label" for="email">Email Address</label>
<input type="email" class="form-control input-sm" id="email" name="email" placeholder="Enter your email" />
-->
<div class="form-group">
<label class="control-label" for="email">Reason for Contact *</label>
<select name="reason" class="form-control">
<option value="General Inquiry">General Inquiry</option>
<option value="Place Order">Place Order</option>
<option value="Report Issue">Report Issue</option>
</select>
<span class="help-block" style="display: none;">Please enter a valid e-mail address.</span>
</div>
<div class="form-group has-feedback">
<label class="control-label" for="message">Message*</label>
<textarea rows="5" cols="30" class="form-control input-sm" id="message" name="message" placeholder="Enter your message" ></textarea>
<div class="form-group">
<label class="control-label" for="email">Email Address *</label>
<div class="input-group">
<input type="email" class="form-control" id="email" name="email" placeholder="Enter your email" />
<span class="input-group-addon"><i class="glyphicon glyphicon-unchecked form-control-feedback"></i></span>
</div>
<span class="help-block" style="display: none;">Please enter a valid e-mail address.</span>
</div>
<div class="form-group">
<label class="control-label" for="message">Message *</label>
<div class="input-group">
<textarea rows="5" cols="30" class="form-control" id="message" name="message" placeholder="Enter your message" ></textarea>
<span class="input-group-addon"><i class="glyphicon glyphicon-unchecked form-control-feedback"></i></span>
</div>
<span class="help-block" style="display: none;">Please enter a message.</span>
</div>
<img id="captcha" src="library/vender/securimage/securimage_show.php" alt="CAPTCHA Image" />
<a href="#" onclick="document.getElementById('captcha').src = 'library/vender/securimage/securimage_show.php?' + Math.random(); return false" class="btn btn-info btn-sm">Show a Different Image</a><br/>
<div class="form-group has-feedback" style="margin-top: 10px;">
<label class="control-label" for="captcha_code">Text Within Image</label>
<input type="text" class="form-control input-sm" name="captcha_code" id="captcha_code" placeholder="For security, please enter the code displayed in the box." />
<div class="form-group" style="margin-top: 10px;">
<label class="control-label" for="captcha_code">Text Within Image *</label>
<div class="input-group">
<input type="text" class="form-control" name="captcha_code" id="captcha_code" placeholder="For security, please enter the code displayed in the box." />
<span class="input-group-addon"><i class="glyphicon glyphicon-unchecked form-control-feedback"></i></span>
</div>
<span class="help-block" style="display: none;">Please enter the code displayed within the image.</span>
</div>
<span class="help-block" style="display: none;">Please enter a the security code.</span>

0 comments on commit f502b9e

Please sign in to comment.
You can’t perform that action at this time.