dword-design / nuxt-mail

Adds email sending capability to a Nuxt.js app. Adds a server route, an injected variable, and uses nodemailer to send emails.
Other
247 stars 18 forks source link

Discussion on best practices for extending the mail functionality #141

Open silverbackdan opened 1 year ago

silverbackdan commented 1 year ago

I'd like to implement recaptcha with this plugin. Currently I have to create a new plugin to use:

import { useFetch } from "#app";
import { FetchError } from "ofetch";
import SMTPTransport from "nodemailer/lib/smtp-transport";

export default defineNuxtPlugin(() => {
  const send = async (config: SMTPTransport) => {
    try {
      await useFetch("/mail-send", {
        body: config,
        method: "POST",
      });
    } catch (error) {
      if (error instanceof FetchError) {
        throw new Error(error.response?._data || "Unknown fetch error");
      }
      throw error;
    }
  };
  return {
    provide: {
      appMail: {
        send
      },
    },
  };
});

and so I can use a new server route, as my own one did not seem to override this module's. My server route looks something like

import { createError, defineEventHandler, readBody } from "h3";
import nodemailer from "nodemailer";

import options from "#mail/options.js";
import send from "#mail/send.js";
// @ts-ignore
import omit from "@dword-design/functions/dist/omit.js";

const transport = nodemailer.createTransport(options.smtp);

export default defineEventHandler(async (event) => {
  const body = await readBody(event);

  // IMPLEMENT RECAPTCHA LOGIC HERE

  try {
    await send(omit(["recaptcha"])(body), options, transport);
  } catch (error) {
    if (error instanceof Error) {
      throw createError({ statusCode: 500, statusMessage: error.message });
    }
    throw createError({
      statusCode: 500,
      statusMessage: "An unknown error occurred",
    });
  }

  return "ok";
});

I'm wondering what the best way to achieve this may be. Bdcause I still end up with a redundant server route that could be exploited as well.

It seems like it'd be good to be able to configure the middleware route path perhaps, or perhaps I would need to be able to disable it by setting to false/null.

Then perhaps there could be a simpler way to call the functionality to send the mail just by passing the event in my own middleware.

Perhaps we could post all additional data as a specific post parameter that we could omit by default.

I'm not really sure what the best way to achieve this is, so it's just a discussion on how this module could best be adapted to make it easier to implement functionality such as recaptcha, or perhaps even a user would want to save the message to a database first etc.

Any thoughts?