1

I have to send some emails and I simply want to re-use as much code/knowledge as possible (just because), for this I want to render a React component to raw HTML with inline classes.

I have managed to render a React component to static markup via:

const TestMail = () => {
  return (
    <div>
      <h1 className="text-xl font-bold border-b">You have a new Test Email on Productlane</h1>
      <p className="border-b">Something something</p>
      <a href="https://productlane.io/feedback" className="bg-purple-600">
        Open
      </a>
    </div>
  )
}

export function testMailer({ to }: IParams) {
  const emailHtml = ReactDOMServer.renderToStaticMarkup(<TestMail />)
  const processedHtml = juice(emailHtml, {
    webResources: {
      // relativeTo: "app/core/styles/index.css",
    },
  })

  return {
    async send() {
      console.warn("trying to SEND")
      console.warn(processedHtml)
    },
  }
}

This outputs the raw html string without the styles, so I figured I really need to pass the compiled css for the inliner to do its job

<div><h1 class="text-xl font-bold border-b">You have a new Test Email on Productlane</h1><p class="border-b">Something something</p><a href="https://productlane.io/feedback" class="bg-purple-600">Open</a></div>

You can see from the snippet I'm trying to use Juice to inline the styles, however, I can seem to get the classes to be rendered in the html, any idea how to achieve this?

Oscar Franco
  • 5,691
  • 5
  • 34
  • 56
  • have you considered using nextjs and rendering as static html. it'll export everything perfectly for you. – sao Jan 06 '22 at 19:50
  • This looks useful as well: https://github.com/maizzle/maizzle – Dave Jan 06 '22 at 20:01
  • See my other comment. The trick here is to inline the CSS into the head. I recommend you use NextJS. With the CSS on the head Juice will work with no issues. – Sigex Oct 22 '22 at 00:10

1 Answers1

0

Right I’ve been doing some digging and this is my plan for handling emails.

  • Transpile down styles sheets to style attribute using Juice, abstract HTML4 tables as react components to allow full email client support.
  • Support {{ parameters }} leave them in your outputted HTML and pass it through Handlebars to replace them just before sending the email.

Option 1:

  • Use NextJS static html export to generate HTML files from said React components.
  • Configure build command to run custom Juice script on outputted files.
  • Reference the exported files using handlebars to apply the per user context e.g. { name: “David” }. I’m doing this in my sendEmail() function.

Option 2

  • Use NextJS server endpoint to compile the handlebars template with the per user context. See this article for reference.

You could also replace custom Juice script with this CLI tool or this npm package. Optionally you can even use Inky to abstract away HTML4 tables.

Alternatively if you only want partial email client support NextJS can inline the CSS into the head with this experimental flag discusses here. For full support you will need CSS in style attribute.

I have a lambda function sendEmail(email: string, templateName: string, context: Record<unknown, any>) which has the hubs template files bundle inside it. When the email is sent it then process the context using handlebars compile().

Sigex
  • 2,834
  • 2
  • 24
  • 25