Form-to-Email Handler
Three methods for routing contact form submissions to any email address — no server required. Choose the approach that suits your hosting setup.
Formspree — Recommended for Most Clients
Free up to 50 submissions/month. No code, no server. Just change the action URL. Takes 5 minutes to set up.
💡 Best for: Static HTML sites on any host. Krystal, Netlify, GitHub Pages, or any shared hosting. Free tier is sufficient for most SA clients.
1
Create a free Formspree account
Go to formspree.io → Sign up → Create New Form → enter the client's email address as the recipient.
2
Copy your form endpoint URL
Formspree gives you a URL like https://formspree.io/f/xabcdefg — paste it into the form's action attribute below.
3
Add this HTML to the client's website
Replace YOUR_FORMSPREE_ID with the ID from step 2. The form is ready.
<!-- Formspree contact form — replace YOUR_FORMSPREE_ID --> <form action="https://formspree.io/f/YOUR_FORMSPREE_ID" method="POST" id="contactForm"> <input type="hidden" name="_subject" value="New Enquiry from Website"> <input type="hidden" name="_next" value="https://yourwebsite.co.uk/thank-you"> <input type="text" name="_gotcha" style="display:none"> <!-- honeypot --> <input type="text" name="name" placeholder="Your Name" required> <input type="email" name="email" placeholder="Email Address" required> <input type="tel" name="phone" placeholder="Phone Number"> <textarea name="message" placeholder="How can we help?" required></textarea> <button type="submit">Send Enquiry</button> </form> <!-- Optional: AJAX submission for no-redirect experience --> <script> document.getElementById('contactForm').addEventListener('submit', async function(e) { e.preventDefault(); const data = new FormData(this); const res = await fetch(this.action, { method: 'POST', body: data, headers: { 'Accept': 'application/json' } }); if (res.ok) { this.innerHTML = '<p style="color:green">✓ Message sent! We\'ll be in touch shortly.</p>'; } else { this.innerHTML += '<p style="color:red">Error sending — please email us directly.</p>'; } }); </script>
EmailJS — No Form Action, Pure JavaScript
200 free emails/month. Works entirely client-side. Good when you can't use a form action attribute (e.g. single-page apps or complex layouts).
⚠️ Note: Your EmailJS public key is visible in the HTML source. This is normal and safe — it only allows sending, not reading. Do not use your private key here.
1
Create EmailJS account at emailjs.com
Add an Email Service (Gmail, Outlook, or custom SMTP). Create an Email Template. Note your Service ID, Template ID, and Public Key.
2
Set up your template variables
In the EmailJS template editor, use {{from_name}}, {{from_email}}, {{message}} as placeholders. These match the JS below.
3
Add this to the client's website
Replace the three placeholder values with your EmailJS credentials.
<!-- Add to <head> --> <script src="https://cdn.jsdelivr.net/npm/@emailjs/browser@4/dist/email.min.js"></script> <script>emailjs.init('YOUR_PUBLIC_KEY');</script> <!-- Form HTML (no action needed) --> <form id="ejsForm"> <input type="text" name="from_name" placeholder="Name" required> <input type="email" name="from_email" placeholder="Email" required> <input type="tel" name="phone" placeholder="Phone"> <textarea name="message" placeholder="Message" required></textarea> <button type="submit">Send</button> <p id="ejsStatus"></p> </form> <script> document.getElementById('ejsForm').addEventListener('submit', function(e) { e.preventDefault(); const btn = this.querySelector('button'); btn.textContent = 'Sending...'; btn.disabled = true; emailjs.sendForm( 'YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', this ).then(() => { document.getElementById('ejsStatus').textContent = '✓ Message sent — we\'ll be in touch soon.'; document.getElementById('ejsStatus').style.color = 'green'; this.reset(); }, (err) => { document.getElementById('ejsStatus').textContent = 'Error: ' + JSON.stringify(err); document.getElementById('ejsStatus').style.color = 'red'; }).finally(() => { btn.textContent = 'Send'; btn.disabled = false; }); }); </script>
Netlify Forms — Zero Config if Already on Netlify
Free up to 100 submissions/month. If the client's site is hosted on Netlify, this requires adding just two attributes. No external service needed.
💡 Best for: Clients whose sites are deployed on Netlify. If they're on Krystal shared hosting, use Formspree instead.
1
Add netlify attribute to the form tag
Netlify detects the netlify attribute at build time and automatically sets up the submission handler.
2
Deploy — Netlify handles the rest
Submissions appear in the Netlify dashboard under Forms. Set up email notifications in Site Settings → Forms → Notifications.
<!-- Netlify Forms — just add netlify attribute --> <form name="contact" method="POST" data-netlify="true" data-netlify-honeypot="bot-field" action="/thank-you"> <input type="hidden" name="form-name" value="contact"> <p style="display:none"> <label>Don't fill: <input name="bot-field"></label> </p> <input type="text" name="name" placeholder="Full Name" required> <input type="email" name="email" placeholder="Email Address" required> <input type="tel" name="phone" placeholder="Phone Number"> <select name="service"> <option>Company Formation</option> <option>Compliance & Filing</option> <option>Credit Building</option> <option>Finance Proposal</option> <option>Other</option> </select> <textarea name="message" placeholder="Tell us about your situation" required></textarea> <button type="submit">Send Enquiry</button> </form>
Quick Form Builder
Configure and preview a contact form for any client. Generates ready-to-paste HTML with Formspree integration.