Skip to content

Commit

Permalink
Add Nodemailer email sending
Browse files Browse the repository at this point in the history
  • Loading branch information
Jasonlingg authored and ChinemeremChigbo committed Sep 21, 2024
1 parent 883489f commit f6865ad
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ AUTH_GOOGLE_ID=
AUTH_GOOGLE_SECRET=
AUTH_SECRET=
DATABASE_URL=
EMAIL_PASS=
EMAIL_SERVICE=
EMAIL_USER=
GDRIVE_CLIENT_EMAIL=
GDRIVE_CLIENTID=
GDRIVE_PRIVTKEY=
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"framer-motion": "^6.3.0",
"next": "^14.2.3",
"next-auth": "^5.0.0-beta.19",
"nodemailer": "^6.9.14",
"pnpm": "^9.4.0",
"prisma": "^5.15.0",
"react": "^18.2.0",
Expand Down Expand Up @@ -48,4 +49,4 @@
"npx prisma format"
]
}
}
}
48 changes: 48 additions & 0 deletions src/pages/api/sendEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { NextApiRequest, NextApiResponse } from 'next';
import nodemailer from 'nodemailer';

type Data = {
message?: string;
error?: string;
details?: string;
};

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const { to, subject, text } = req.body;

// Validate the input
if (!to || !subject || !text) {
return res.status(400).json({ error: 'Missing required fields' });
}

// Create a transporter object
try {
const transporter = nodemailer.createTransport({
service: process.env.EMAIL_SERVICE,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS, // app password
},
});

// Configure the mailOptions object
const mailOptions = {
from: process.env.EMAIL_USER,
to: to,
subject: subject,
text: text,
};

// Send the email
await transporter.sendMail(mailOptions);

res.status(200).json({ message: 'Email sent successfully' });
} catch (error: any) {
res
.status(500)
.json({ error: 'Error sending email', details: error.message });
}
}
86 changes: 86 additions & 0 deletions src/pages/email.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useState } from 'react';
import { Button, Container, Input, Text, Textarea } from '@chakra-ui/react';

const Email = () => {
const [isLoading, setIsLoading] = useState(false);
const [message, setMessage] = useState('');
const [emailText, setEmailText] = useState('');
const [subject, setSubject] = useState('');
const [emailRecipients, setEmailRecipients] = useState([]);

const handleEmailSend = async () => {
setIsLoading(true);
setMessage('');
try {
const response = await fetch('/api/sendEmail', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: emailRecipients,
subject: subject,
text: emailText,
}),
});

if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.details || 'Failed to send email');
}

const data = await response.json();
setMessage(data.message);
} catch (error: any) {
setMessage(`Error sending email: ${error.message}`);
} finally {
setIsLoading(false);
}
};

const handleEmailTextChange = (e) => {
setEmailText(e.target.value);
};

const handleSubjectChange = (e) => {
setSubject(e.target.value);
};

const handleEmailRecipientsChange = (e) => {
const recipientsString = e.target.value;
setEmailRecipients(recipientsString.split(','));
};

return (
<Container>
<Input
placeholder="Add recipients here"
onChange={handleEmailRecipientsChange}
/>
<Input placeholder="Add subject here" onChange={handleSubjectChange} />
<Textarea
placeholder="Write your email here"
value={emailText}
onChange={handleEmailTextChange}
/>
<Button
onClick={handleEmailSend}
isLoading={isLoading}
loadingText="Sending"
colorScheme="blue"
>
Send Email
</Button>
{message && (
<Text
mt={4}
color={message.startsWith('Error') ? 'red.500' : 'green.500'}
>
{message}
</Text>
)}
</Container>
);
};

export default Email;

0 comments on commit f6865ad

Please sign in to comment.