I’m trying to send out an email using the Gmail API, but I keep getting an error stating that I am not specifying a recipient to my email, even though I am inside of the email constant. I have tried using a hard-coded email address that I know exists, but it has not worked successfully. I am unsure as to why this is occuring. I will list both the API route in Node.js as well as the handleSubmit function that’s calling the API route.
sendGmail.js API Route
export default async (req, res) => {
try {
if (req.method === 'POST') {
const {
alertType,
alertLocationData,
alertSubject,
alertDetails,
userEmail,
distributionEmail,
alertStartDate,
alertEndDate,
attachments,
} = req.body;
const locationNames = []
const locationCodes = []
const servicesAffected = []
alertLocationData.forEach(item => {
const location = item['Location Name']
const code = item['Code']
const services = item['Services']
locationNames.push(location)
locationCodes.push(code)
servicesAffected.push(services)
});
const emailContent = ReactDOMServer.renderToStaticMarkup(
<EmailTemplate
alertType={alertType}
alertStartDate={alertStartDate}
alertEndDate={alertEndDate}
alertLocations={locationNames}
alertLocationCodes={locationCodes}
servicesAffected={servicesAffected}
alertDetails={alertDetails}
/>
)
const session = await getServerSession(req, res, authOptions)
const token = await getToken({ req })
if (!session || !token || !token.accessToken) {
return res.status(401).json({ error: 'Unauthorized' })
}
const oauth2Client = new google.auth.OAuth2({})
oauth2Client.setCredentials({
access_token: token.accessToken,
refresh_token: token.refreshToken,
});
const gmail = google.gmail({ version: 'v1', auth: oauth2Client })
const sendEmail = async () => {
try {
const email = `
From: <${userEmail}>
To: <HARD-CODED EMAIL>
Subject: ${alertSubject}
Content-Type: text/html; charset=utf-8
${emailContent}
`;
const base64EncodedEmail = Buffer.from(email).toString('base64')
const response = await gmail.users.messages.send({
userId: session.user.email,
requestBody: {
raw: base64EncodedEmail,
},
})
console.log(`Email Sent: ${response.data}`)
return res.status(200).json({ success: true })
} catch (error) {
console.error(`Error sending email: ${error}`)
res.status(500).json({ error: 'Failed to send email' })
}
};
await sendEmail();
}
} catch (error) {
console.error(`An error has occurred: ${error}`);
return res.status(500).json({ error: 'Internal Server Error' })
}
};
Here is my handleSubmit function that is calling the API route:
const handleSubmit = async () => {
try {
if (alertType == '' || alertLocationData == '' || alertSubject == '' || alertDetails == '' || userEmail == '' || distributionEmail == '') {
setSnackbarOpen(true)
handleOpenSnackbar('error', 'Please Fill Out All Form Fields')
} else {
setLoading(true)
const payload = {
alertType,
alertLocationData,
alertSubject,
alertDetails,
userEmail,
distributionEmail,
alertStartDate: alertStartDate.format(),
alertEndDate: alertEndDate.format(),
attachments,
alertActive,
}
const res = await fetch('/api/alertHandling/postAlertData', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
})
if (res.ok) {
console.log('Data succesfully saved')
const res2 = await fetch('/api/google/sendGmail', {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
})
setLoading(false)
if (dataFetchCallback) {
dataFetchCallback
}
props.onClose()
initValues()
} else {
setLoading(false)
throw new Error(`Error: ${res.status}`)
}
}
} catch (error) {
console.error(`Error submitting data: ${error}`)
}
}
As a note: I feel like this is not best practice, but right now it’s just to get something to work appropriately, however any advice on how to improve the handleSubmit function is appreciated.
>Solution :
The spacing is critical. You need:
const email = `From: <${userEmail}>
To: <HARD-CODED EMAIL>
Subject: ${alertSubject}
Content-Type: text/html; charset=utf-8
${emailContent}`;