N
Nuxt5mo ago
Yassaaa

Need help with creating mail templates with dynamic data and sending it

Summary: My goal is to send order confirmation emails using Nodemailer and Vue for email templates. I have successfully managed to: 1. Send emails using Nodemailer with SMTP. 2. Create email templates using Vue-mail but I did not use nuxt components? im not sure I am new to this nuxt module. Though I was able to use Tailwind in the email template. However, I am encountering issues when trying to combine these functionalities.
3 Replies
Yassaaa
YassaaaOP5mo ago
What I have tried: 1. Sending Emails with Nodemailer: I have a working implementation that sends emails using Nodemailer. Here is the relevant code:
<template>
<button @click="placeOrder" class="btn btn-circle">
Send Mail
</button>
</template>

<script setup lang="ts">
async function placeOrder() {
const orderDetails = {
senderEmail: '[email protected]',
recepient: '[email protected]',
subject: 'New Order Received',
name: 'TEST ORDER NOT REAL', // Replace with actual data
address: '123 Main St', // Replace with actual data
items: ['item1', 'item2'], // Replace with actual data
coupon: 'SAVE20' // Replace with actual data
};

try {
const response = await $fetch('/api/send-email', {
method: 'POST',
body: orderDetails,
});
alert('Email sent successfully!');
} catch (error) {
alert('An error occurred while sending the email. Please try again later.');
}
}

</script>
<template>
<button @click="placeOrder" class="btn btn-circle">
Send Mail
</button>
</template>

<script setup lang="ts">
async function placeOrder() {
const orderDetails = {
senderEmail: '[email protected]',
recepient: '[email protected]',
subject: 'New Order Received',
name: 'TEST ORDER NOT REAL', // Replace with actual data
address: '123 Main St', // Replace with actual data
items: ['item1', 'item2'], // Replace with actual data
coupon: 'SAVE20' // Replace with actual data
};

try {
const response = await $fetch('/api/send-email', {
method: 'POST',
body: orderDetails,
});
alert('Email sent successfully!');
} catch (error) {
alert('An error occurred while sending the email. Please try again later.');
}
}

</script>
Yassaaa
YassaaaOP5mo ago
2. Creating Email Templates with Vue: I have created a template using Vue components and props. Here is the template:
Yassaaa
YassaaaOP5mo ago
3. Combining Both: I tried to combine both functionalities by creating an API endpoint that generates the email HTML and sends the email. Here is the code:
import { defineEventHandler } from 'h3'
import { useShoppingCartStore } from '~/stores/shoppingCartStore'
import { useCheckoutStore } from '~/stores/checkoutStore'
import OrderConfirmationEmail from '~/emails/Order_Confirmation.vue'
import { renderToString } from '@vue/server-renderer'
import { createSSRApp, h } from 'vue'

export default defineEventHandler(async () => {
const shoppingCartStore = useShoppingCartStore()
const checkoutStore = useCheckoutStore()

const emailData = {
items: shoppingCartStore.items.map(item => ({
id: item._uid,
name: item.product_title.length > 32 ? item.product_title.slice(0, 31) + '...' : item.product_title,
quantity: item.item_count,
price: item.price,
image: item.product_image[0].filename || '/icon.svg'
})),
subtotal: shoppingCartStore.subtotal,
discount: shoppingCartStore.discount,
totalItems: shoppingCartStore.totalItems,
orderTotal: shoppingCartStore.total,
orderDate: new Date().toLocaleDateString(),
savings: shoppingCartStore.discount.toFixed(2),
shippingName: checkoutStore.formData.name,
shippingEmail: checkoutStore.formData.email,
shippingPhone: checkoutStore.formData.phone,
shippingAddress: checkoutStore.formData.address,
shippingCity: checkoutStore.formData.city,
shippingState: checkoutStore.formData.country
}

const app = createSSRApp({
render: () => h(OrderConfirmationEmail, { ...emailData })
})

const emailHtml = await renderToString(app)

return {
html: emailHtml
}
})
import { defineEventHandler } from 'h3'
import { useShoppingCartStore } from '~/stores/shoppingCartStore'
import { useCheckoutStore } from '~/stores/checkoutStore'
import OrderConfirmationEmail from '~/emails/Order_Confirmation.vue'
import { renderToString } from '@vue/server-renderer'
import { createSSRApp, h } from 'vue'

export default defineEventHandler(async () => {
const shoppingCartStore = useShoppingCartStore()
const checkoutStore = useCheckoutStore()

const emailData = {
items: shoppingCartStore.items.map(item => ({
id: item._uid,
name: item.product_title.length > 32 ? item.product_title.slice(0, 31) + '...' : item.product_title,
quantity: item.item_count,
price: item.price,
image: item.product_image[0].filename || '/icon.svg'
})),
subtotal: shoppingCartStore.subtotal,
discount: shoppingCartStore.discount,
totalItems: shoppingCartStore.totalItems,
orderTotal: shoppingCartStore.total,
orderDate: new Date().toLocaleDateString(),
savings: shoppingCartStore.discount.toFixed(2),
shippingName: checkoutStore.formData.name,
shippingEmail: checkoutStore.formData.email,
shippingPhone: checkoutStore.formData.phone,
shippingAddress: checkoutStore.formData.address,
shippingCity: checkoutStore.formData.city,
shippingState: checkoutStore.formData.country
}

const app = createSSRApp({
render: () => h(OrderConfirmationEmail, { ...emailData })
})

const emailHtml = await renderToString(app)

return {
html: emailHtml
}
})
Issues Encountered: 1. When trying to display the email HTML in the page's body, I get warnings like "missing required prop". 2. In the server console, I get the following error:
WARN [plugin inject] emails/Order_Confirmation.vue: rollup-plugin-inject: [...]. Consider restricting the plugin to particular files via options.include

ERROR RollupError: emails/Order_Confirmation.vue (1:0): Expression expected (Note that you need plugins to import files that are not JavaScript) nitro 10:56:21


1: <script setup lang="ts">
^
2: import {
3: Html,
WARN [plugin inject] emails/Order_Confirmation.vue: rollup-plugin-inject: [...]. Consider restricting the plugin to particular files via options.include

ERROR RollupError: emails/Order_Confirmation.vue (1:0): Expression expected (Note that you need plugins to import files that are not JavaScript) nitro 10:56:21


1: <script setup lang="ts">
^
2: import {
3: Html,
I am using Pinia for state management and want to pass the data from the Pinia states to the email template and send it with Nodemailer. The checkout store has a formData state that contains all the relevant data about the customer like name, email, phone, address, etc. I would appreciate any guidance or suggestions on how to resolve these issues and successfully combine sending emails with Nodemailer and creating email templates with Vue-Mail. I did use Claude and Github Copilot for help.
Want results from more Discord servers?
Add your server