Compare commits

..

2 Commits

Author SHA1 Message Date
2b694b2198 Merge pull request 'feat: implement email functionality for contact form' (#2) from SendEmailFeature into main
Reviewed-on: #2
2026-02-25 00:03:39 -05:00
3a12c96507 feat: implement email functionality for contact form
- Add nodemailer dependency for email sending

- Create server action to handle email submissions

- Add email HTML template for formatted messages

- Update contact page to integrate email functionality
2026-02-25 00:06:54 -05:00
5 changed files with 155 additions and 6 deletions

42
package-lock.json generated
View File

@@ -9,7 +9,11 @@
"version": "0.0.1",
"dependencies": {
"astro": "^5.17.1",
"lenis": "^1.3.17"
"lenis": "^1.3.17",
"nodemailer": "^8.0.1"
},
"devDependencies": {
"@types/nodemailer": "^7.0.11"
}
},
"node_modules/@astrojs/compiler": {
@@ -1513,6 +1517,26 @@
"@types/unist": "*"
}
},
"node_modules/@types/node": {
"version": "25.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.0.tgz",
"integrity": "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/@types/nodemailer": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.11.tgz",
"integrity": "sha512-E+U4RzR2dKrx+u3N4DlsmLaDC6mMZOM/TPROxA0UAPiTgI0y4CEFBmZE+coGWTjakDriRsXG368lNk1u9Q0a2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@@ -3675,6 +3699,15 @@
"integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
"license": "MIT"
},
"node_modules/nodemailer": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.1.tgz",
"integrity": "sha512-5kcldIXmaEjZcHR6F28IKGSgpmZHaF1IXLWFTG+Xh3S+Cce4MiakLtWY+PlBU69fLbRa8HlaGIrC/QolUpHkhg==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -4495,6 +4528,13 @@
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
"license": "MIT"
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"devOptional": true,
"license": "MIT"
},
"node_modules/unified": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",

View File

@@ -10,6 +10,10 @@
},
"dependencies": {
"astro": "^5.17.1",
"lenis": "^1.3.17"
"lenis": "^1.3.17",
"nodemailer": "^8.0.1"
},
"devDependencies": {
"@types/nodemailer": "^7.0.11"
}
}

44
src/actions/index.ts Normal file
View File

@@ -0,0 +1,44 @@
import { defineAction } from "astro:actions";
import { z } from "astro:schema";
import nodemailer from "nodemailer";
import emailTemplate from "../templates/emailTemplate.html?raw";
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: import.meta.env.EMAIL_USER,
pass: import.meta.env.EMAIL_PASS,
},
});
export const server = {
sendEmail: defineAction({
input: z.object({
userName: z.string(),
companyName: z.string(),
phoneNumber: z.string(),
userEmail: z.string().email(),
}),
handler: async (input) => {
const mailOptions = {
from: '"Juan Diego" <jdcorreosvarios@gmail.com>',
to: "jdcorreosvarios@gmail.com",
subject: `Nueva persona interesada en Naliia: ${input.userName}`,
html: emailTemplate
.replace("{{userName}}", input.userName)
.replace("{{companyName}}", input.companyName)
.replace("{{phoneNumber}}", input.phoneNumber)
.replace("{{userEmail}}", input.userEmail),
};
try {
await transporter.sendMail(mailOptions);
return { success: true };
} catch (error) {
console.error("Error al enviar el correo:", error);
throw new Error("Error al enviar el correo");
}
},
}),
};

View File

@@ -103,7 +103,7 @@ import "../styles/contactpage.css";
name="contact-form"
>
<div class="form-item">
<label for="" class="item-label"
<label for="userName" class="item-label"
>Nombre de contacto</label
>
@@ -111,12 +111,16 @@ import "../styles/contactpage.css";
type="text"
class="form-input"
placeholder="Juan Carlos Garcia Velez"
name="userName"
id="userName"
required
/>
</div>
<div class="form-item">
<label for="" class="item-label"
<label
for="companyName"
class="item-label"
>Nombre de la empresa</label
>
@@ -124,12 +128,16 @@ import "../styles/contactpage.css";
type="text"
class="form-input"
placeholder="Empresa XYZ S.A.S"
name="companyName"
id="companyName"
required
/>
</div>
<div class="form-item">
<label for="" class="item-label"
<label
for="phoneNumber"
class="item-label"
>Número de celular</label
>
@@ -137,12 +145,16 @@ import "../styles/contactpage.css";
type="tel"
class="form-input"
placeholder="3104567890"
name="phoneNumber"
id="phoneNumber"
required
/>
</div>
<div class="form-item">
<label for="" class="item-label"
<label
for="userEmail"
class="item-label"
>Correo electrónico</label
>
@@ -150,6 +162,8 @@ import "../styles/contactpage.css";
type="email"
class="form-input"
placeholder="correoejemplo@gmail.com"
name="userEmail"
id="userEmail"
required
/>
</div>
@@ -170,3 +184,40 @@ import "../styles/contactpage.css";
</InitialSection>
</section>
</Layout>
<script>
import { actions } from "astro:actions";
const contactForm = document.getElementById(
"contact-form",
) as HTMLFormElement | null;
contactForm?.addEventListener("submit", async (event) => {
event.preventDefault();
const formData = new FormData(contactForm);
const parsedData = {
userName: (formData.get("userName") as string) || "",
companyName: (formData.get("companyName") as string) || "",
phoneNumber: (formData.get("phoneNumber") as string) || "",
userEmail: (formData.get("userEmail") as string) || "",
};
const { data, error } = await actions.sendEmail(parsedData);
if (!error) {
console.log("Información enviada correctamente:", data);
alert(
"¡Gracias por contactarnos! Nos pondremos en contacto contigo pronto.",
);
contactForm.reset();
} else {
console.error("Error al enviar la información:", error);
alert(
"Hubo un error al enviar tu información. Por favor, inténtalo de nuevo más tarde.",
);
}
});
</script>

View File

@@ -0,0 +1,10 @@
<h3>Hay una nueva persona interesada en los servicios de Naliia:</h3>
<p><strong>Información de contacto:</strong></p>
<ul>
<li>Nombre: {{userName}}</li>
<li>Empresa: {{companyName}}</li>
<li>Teléfono: {{phoneNumber}}</li>
<li>Email: {{userEmail}}</li>
</ul>