I'm putting together a contact form using Svelte and SendGrid. Here is a basic app.svelte:
<script>
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(import.meta.env.VITE_SENDGRID);
function submitForm() {
const msg = {
to: 'test@example.com',
from: 'test@example.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>'
};
console.log('Form submitted');
sgMail.send(msg);
}
</script>
<form on:submit|preventDefault={submitForm}>
<button type="submit">Submit</button>
</form>
The code above does not send an email after the user selects submit
on the form, despite the function being called (it logs Form submitted
in the console). When I move all code from submitForm()
outside the function, the code executes on page load, so I know it's not an issue with my API key.
Any suggestions what I am missing?
Svelte is a frontend environment only. The Sendgrid package is desinged for a server side / node.js environment. In your example, your Sendgrid API key would be exposed because you're trying to use it on the frontend / client side.
A solution may be to look at SvelteKit, which has the concept of 'endpoints' which always run on the server side. Or you can create an express server to handle the sending of email to Sendgrid.
EDIT: The solution is to use Sveltekit endpoints. Endpoints always run on the server. Your final solution may look something like this:
File: /src/routes/api/sendmail.ts or /src/api/sendmail.js
import sgMail from "@sendgrid/mail";
sgMail.setApiKey(import.meta.env.VITE_SENDGRID);
export async function get(page) {
const msg = {
to: "test@example.com",
from: "test@example.com",
subject: "Sending with SendGrid is Fun",
text: "and easy to do anywhere, even with Node.js",
html: "<strong>and easy to do anywhere, even with Node.js</strong>",
};
console.log("Form submitted");
const output = await sgMail.send(msg);
return {
body: output,
};
}
File /src/routes/index.svelte
<script>
function submitForm() {
fetch("/api/sendmail");
}
</script>
<form on:submit|preventDefault={submitForm}>
<button type="submit">Submit</button>
</form>