Hi, first of all I dont´now if I established categories of this discussion well, but I´m going to try it here.
Im trying to send emails from my react web application via netlify functions and I can not trigger the handler of my sendmail.js which is in my functions folder. I´m always getting the same error http:localhost:8080/(here I tried a lot of routes like “.netlify/functions/sendemail”) error 404 not found.
here are my folders, as you can see functions folder is now inside of src folder, but I tried to place it in the root directory and anything the console gives me the same error.
here is a screenshot of the error
I´m trying to send values after a captcha is validated, I made a form with formik and I add all the atribbutes as the documentAtion says
here is my index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" href="favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"
integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
crossorigin=""></script>
<title>Clínica Pal Dental</title>
</head>
<body>
<form method="POST" name="contact-form" data-netlify="true" netlify-honeypot="bot-field" hidden>
<input type="text" name="NameSurname" />
<input type="text" name="Phone" />
<input type="text" name="Email" />
<textarea name="Comment"></textarea>
<input type="checkbox" name="LegalConsent" />
<input name="bot-field" type="hidden" />
</form>
<div id="root"></div>
</body>
</html>
heres is the formik with the useEffect after the captcha is validated
useEffect(() =>{
async function sendEmailNetlify(){
await fetch(`/.netlify/functions/sendmail`,
{
method : "POST",
data : formValues
})
.then(({ response }) =>{
debugger;
alert(JSON.stringify(response))
})
.catch(error =>{
console.log(JSON.parse(error))
})
}
if(isCaptchaSent){
sendEmailNetlify();
}
}, [formValues, isCaptchaSent]);
return(
<div className="modal fade" id="ContactModal" tabIndex="-1" aria-labelledby="ContactModalLabel" aria-hidden="true">
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-header justify-content-end">
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<Formik
initialValues={initialContactFormValues}
validationSchema={validationSchema}
onSubmit={handleSubmitValues}>
{({ resetForm }) => {
return(
<Form
id="contactForm"
name="contact-form"
data-netlify="true"
data-netlify-honeypot="bot-field"
data-netlify-recaptcha="true"
noValidate
>
<Field type="hidden" name="bot-field" />
<Field type="hidden" name="form-name" />
<div className="modal-body d-flex flex-column justify-content-start align-items-center mt-n4">
<h5 className="modal-title" id="ContactModalLabel">Contacto</h5>
<h3>Introduce tus datos</h3>
<div className="form-group">
<label className="form-group__label" htmlFor="NameSurname">
Nombre y apellidos <span className="mandatory">*</span>
</label>
<Field id="NameSurnameInput" name="NameSurname" className="form-group__input"/>
<ErrorMessage name="NameSurname" className="form-group__error" component="span"/>
</div>
<div className="form-group">
<label className="form-group__label" htmlFor="Phone">
Teléfono <span className="mandatory">*</span>
</label>
<div className="input-group flex-nowrap">
<Field id="phoneInput" name="Phone" className="form-group__input"/>
<i className="input-group-text icon icon-info" data-bs-toggle="tooltip" data-bs-placement="bottom" title="El teléfono no puede contener espacios, tampoco es necesario el prefijo" data-bs-custom-class="custom-tooltip"></i>
</div>
<ErrorMessage name="Phone" className="form-group__error" component="span"/>
</div>
<div className="form-group">
<label className="form-group__label" htmlFor="Email">
Email <span className="mandatory">*</span>
</label>
<Field id="emailInput" name="Email" className="form-group__input"/>
<ErrorMessage name="Email" className="form-group__error" component="span"/>
</div>
<div className="form-group">
<label className="form-group__label" htmlFor="Comment">
Comentario <span className="mandatory">*</span>
</label>
<div className="comment">
<Field as="textarea" id="commentInput" name="Comment" className="form-group__input" rows="5"/>
</div>
<ErrorMessage name="Comment" className="form-group__error" component="span" />
</div>
<div className="form-group__legal px-3">
<div className="legal__container">
<Field type="checkbox" id="legalConsentInput" name="LegalConsent" />
<p>He leido y acepto las condiciones de <Link to="/terminos-legales" target="_blank">Aviso Legal</Link> y <Link to="/terminos-legales" target="_blank">Política de privacidad</Link></p>
</div>
<ErrorMessage name="LegalConsent" className="form-group__error ps-0" component="span"/>
</div>
<Reaptcha
ref={rcRef}
sitekey={process.env.RECAPTCHA_SITE_KEY}
data-netlify-recaptcha="true"
onError={onError}
onExpire={onExpire}
onVerify={onVerify}
onLoad={() => onLoad(() => resetForm)}
size="invisible"
/>
</div>
<div className="modal-footer justify-content-center">
{renderSubmitButtonState(isSubmitting, executing, verified)}
</div>
</Form>
)
}}
</Formik>
</div>
</div>
</div>
)
heres is my netlify.toml
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[dev]
command = "npm start"
port = 8080
targetPort = 3000
publish = "./src/bundles"
functions = "./src/functions"
[build]
publish = "./src/bundles"
functions = "./src/functions"
[functions]
# Directory with serverless functions, including background
# functions, to deploy. This is relative to the base directory
# if one has been set, or the root directory if
# a base hasn’t been set.
directory = "./src/functions"
node_bundler = "esbuild"
here is my sendmail.js
const client = require('@sendgrid/mail');
const {
SENDGRID_API_KEY,
SENDGRID_TO_EMAIL,
SENDGRID_FROM_EMAIL,
} = process.env;
exports.handler = async function (event, context, callback) {
debugger;
const { message, senderEmail, senderName } = JSON.parse(event.body);
client.setApiKey(SENDGRID_API_KEY);
const data = {
to: SENDGRID_TO_EMAIL,
from: SENDGRID_FROM_EMAIL,
subject: `New message from ${senderName} (${senderEmail})`,
html: message,
};
try {
await client.send(data);
return {
statusCode: 200,
body: 'Message sent',
};
} catch (err) {
return {
statusCode: err.code,
body: JSON.stringify({ msg: err.message }),
};
}
};