-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: make the mailer work again here in this project with hcaptcha (#11)
- Loading branch information
Showing
8 changed files
with
208 additions
and
79 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ node_modules | |
dist | ||
src/_includes/css | ||
src/_includes/scripts | ||
src/posts/**/*.html | ||
|
||
# cache | ||
.cache | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import {verify} from 'hcaptcha'; | ||
import {MailerSend, EmailParams, Sender, Recipient} from 'mailersend'; | ||
import {getClientIp} from 'request-ip'; | ||
|
||
async function verifyCaptcha(localAddress, hcaptcha_response) { | ||
const hcaptcha_site_key = process.env.HCAPTCHA_SITE_KEY; | ||
const hcaptcha_secret = process.env.HCAPTCHA_SECRET; | ||
|
||
if (!hcaptcha_secret) { | ||
console.error('hcaptcha secret missing!'); | ||
return {status: 500, message: 'hcaptcha secret key missing!'}; | ||
} | ||
|
||
if (!hcaptcha_site_key) { | ||
console.error('hCaptcha site key missing!'); | ||
return {status: 500, message: 'hcaptcha site key missing!'}; | ||
} | ||
|
||
if (hcaptcha_response) { | ||
const verify_response = await verify(hcaptcha_secret, hcaptcha_response, localAddress, hcaptcha_site_key); | ||
|
||
if (verify_response?.success) { | ||
return { | ||
status: 200, | ||
message: 'hcaptcha verified user' | ||
}; | ||
} else { | ||
console.warn({verify_response}); | ||
return { | ||
status: 429, | ||
message: 'hcaptcha verification failed', | ||
error_codes: verify_response['error-codes'], | ||
hostname: verify_response.hostname | ||
}; | ||
} | ||
} else { | ||
return {status: 400, message: 'Missing hcaptchaResponse'}; | ||
} | ||
} | ||
|
||
async function sendMail(request) { | ||
const message = { | ||
from: request['contactEmail'], | ||
to: process.env.CONTACT_EMAIL, | ||
name: request['contactName'], | ||
subject: `[KABLAMO.ME] CONTACT PAGE FROM ${request['contactName']}`, | ||
body: | ||
`NAME: ${request['contactName']}\n` + | ||
`PHONE: ${request['contactPhone']}\n\n` + | ||
`${request['contactMessage']}` | ||
}; | ||
console.trace('Sending email...', {message}); | ||
const mailer = new MailerSend({ | ||
apiKey: process.env.MAILER_SEND_API_KEY | ||
}); | ||
|
||
const sentFrom = new Sender(message.from, message.name); | ||
const recipients = [new Recipient(process.env.CONTACT_EMAIL, 'Kablamo.me Admin')]; | ||
|
||
const emailParams = new EmailParams() | ||
.setFrom(sentFrom) | ||
.setTo(recipients) | ||
.setSubject(message.subject) | ||
.setText(message.body); | ||
|
||
return mailer.email.send(emailParams); | ||
} | ||
|
||
export default async function handler(request, response) { | ||
const hcaptcha_response = request?.body['hcaptchaResponse']; | ||
console.trace('Contact Request', {body: request.body}); | ||
const ipAddress = getClientIp(request); | ||
const verify_response = await verifyCaptcha(ipAddress, hcaptcha_response); | ||
|
||
if (verify_response.status === 200) { | ||
const result = await sendMail(request.body); | ||
if (result.statusCode >= 200 || result.statusCode <= 299) { | ||
console.log({info}); | ||
return response.status(200).json({body: {message: 'Email successful sent'}}); | ||
} else { | ||
console.error({request: request.body, result}); | ||
return response.status(500).json({ | ||
body: { | ||
status: response.statusCode, | ||
message: response.body | ||
} | ||
}); | ||
} | ||
} else { | ||
console.warn('hcaptcha verification failed', {verify_response}); | ||
response.status(verify_response.status).json({body: verify_response}); | ||
} | ||
} |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,19 +13,25 @@ permalink: 'contact/index.html' | |
</div> | ||
<div> | ||
<div id="contactFlash is-hidden"></div> | ||
<form method="POST" class="" id="contactForm" action="#"> | ||
<div class="contactFlash"></div> | ||
<form method="POST" class="" id="contactForm" action="/api/contact"> | ||
<div id="contactFlash"></div> | ||
<div class=""> | ||
<label for="messageName" class="block text-sm font-medium">Name</label> | ||
<input type="text" class="input form-input" placeholder="Your name..." required /> | ||
<label for="contactName" class="block text-sm font-medium">Name</label> | ||
<input id="contactName" type="text" class="input form-input" placeholder="Your name..." required /> | ||
</div> | ||
<div class="mt-m"> | ||
<label for="messageEmail" class="block text-sm font-medium">Email</label> | ||
<input type="email" class="input form-input" placeholder="[email protected]" required /> | ||
<label for="contactEmail" class="block text-sm font-medium">Email</label> | ||
<input | ||
id="contactEmail" | ||
type="email" | ||
class="input form-input" | ||
placeholder="[email protected]" | ||
required | ||
/> | ||
</div> | ||
<div class="mt-m"> | ||
<label for="messageEmail" class="block text-sm font-medium">Phone</label> | ||
<input type="tel" class="input form-input" placeholder="+1 (555) 555-5555" /> | ||
<label for="contactPhone" class="block text-sm font-medium">Phone (optional)</label> | ||
<input id="contactPhone" type="tel" class="input form-input" placeholder="+1 (555) 555-5555" /> | ||
</div> | ||
<div class="mt-m"> | ||
<label for="contactMessage" class="block text-sm font-medium">Message</label> | ||
|
@@ -53,5 +59,5 @@ permalink: 'contact/index.html' | |
</div> | ||
</custom-masonry> | ||
|
||
<script src="/assets/scripts/bundle/contact.js" async defer></script> | ||
<script src="/assets/scripts/bundle/hcaptcha/index.min.js"></script> | ||
<script src="/assets/scripts/components/contact.js" defer></script> | ||
<script src="/assets/scripts/components/hcaptcha/index.min.js"></script> |
This file was deleted.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
const showFlash = (flash, message, cssClass) => { | ||
flash.classList.add(cssClass); | ||
flash.innerHtml = message; | ||
flash.classList.remove('is-hidden'); | ||
setTimeout(() => { | ||
flash.classList.add('is-hidden'); | ||
flash.classList.remove(cssClass); | ||
}, 10000); | ||
}; | ||
|
||
document.addEventListener('DOMContentLoaded', () => { | ||
const hcaptcha = document.getElementById('h-captcha'); | ||
|
||
const submitContactForm = async () => { | ||
const form = document.getElementById('contactForm'); | ||
const flash = document.getElementById('contactFlash'); | ||
const btn = document.getElementById('contactSubmitBtn'); | ||
const hcaptchaToken = hcaptcha.getAttribute('data-token'); | ||
|
||
if (!hcaptchaToken) { | ||
flash.classList.add('is-danger'); | ||
flash.innerHTML = 'An error occurred sending message! Please try again later.'; | ||
} | ||
|
||
btn.setAttribute('disabled', ''); | ||
|
||
if (!flash) console.log('contactFlash div not found', flash); | ||
|
||
const values = new URLSearchParams(); | ||
document | ||
.querySelectorAll('#contactForm .input') | ||
.forEach(element => values.append(element.id, element.value)); | ||
values.append('hcaptchaResponse', hcaptchaToken); | ||
|
||
console.error(values); | ||
|
||
const response = await fetch(form.action, { | ||
method: form.method, | ||
body: values, | ||
headers: { | ||
'Content-Type': 'application/x-www-form-urlencoded' | ||
} | ||
}) | ||
.then(response => { | ||
console.log('Form submission response', response.body); | ||
console.log('Form json', JSON.stringify(response.body ?? {})); | ||
return response.json(); | ||
}) | ||
.catch(error => { | ||
console.error('Error:', error); | ||
}); | ||
|
||
if (response && response.status === 200) { | ||
showFlash(flash, 'Message successfully sent!', 'is-primary'); | ||
} else { | ||
setTimeout(() => { | ||
btn.removeAttribute('disabled'); | ||
}, 5000); | ||
showFlash(flash, 'An error occurred sending message! Please try again later.', 'is-danger'); | ||
} | ||
}; | ||
|
||
hcaptcha.addEventListener('verified', e => { | ||
const btn = document.getElementById('contactSubmitBtn'); | ||
hcaptcha.dataset.token = e.token; | ||
btn.removeAttribute('disabled'); | ||
}); | ||
|
||
hcaptcha.addEventListener('error', e => { | ||
console.log('error event', {error: e.error}); | ||
const btn = document.getElementById('contactSubmitBtn'); | ||
btn.setAttribute('disabled', ''); | ||
|
||
const flash = document.getElementById('contactFlash'); | ||
flash.classList.add('is-danger'); | ||
flash.innerHTML = 'An error occurred verifying your captcha! Please reload and try again later.'; | ||
}); | ||
|
||
const form = document.getElementById('contactForm'); | ||
form.addEventListener('submit', e => { | ||
e.preventDefault(); | ||
submitContactForm(); | ||
}); | ||
}); |