Updated Cloudflare Pages plugins for Static Forms and MailChannels

Published by Liam Martin

🍿 4 min. read

Email forms on Cloudflare Pages with CAPTCHA

Cloudflare Pages has been great. It offers a very similar service to Netlify but allows you to leverage the Cloudflare CDN environment for better networking, Cloudflare Workers, Turnstile CAPTCHAs and so much more. It's no secret I'm a fan of Cloudflare for it's powerful tools and ease of use. Many of my clients have benefited from it's Caching tech and the recent release of Cache Reserve has given me a quick and easy way to fix many static Wordpress pages that had awful response/load times.

That's why I was so surprised when the official plugins for Static Forms and MailChannels were broken!

Thankfully, I've produced two fixed plugins and I've upgraded them to have Turnstile compatibility. You can find them here:

  1. Cloudflare Pages - Static Forms Plugin

  2. Cloudflare Pages - MailChannels Plugin

How are the official plugins broken?

It started with the MailChannels plugin. I wanted a simple email contact form, similar to Netlify's offering, using Cloudflare Functions and this seemed to do the trick. The problem occured when I tried to add a redirect to the function:

import mailChannelsPlugin from "@cloudflare/pages-plugin-mailchannels";

export const onRequest: PagesFunction = mailChannelsPlugin({
personalizations: [
{
to: [{ name: "ACME Support", email: "[email protected]" }],
},
],
from: {
name: "ACME Support",
email: "[email protected]",
},
respondWith: () => {
return Response.redirect('https://cardiff.marketing/about/', 302)
},
});

What I got was a blank page with no redirect. Huh. Trying to narrow down the issue, I tried a basic redirect function on a route called /test:

// /functions/test.js
export function onRequest(context) {
return Response.redirect("https://cardiff.marketing/about/", 302)
}

And this was the response:

> curl --include https://cardiff.marketing/test/
HTTP/2 200
date: Thu, 15 Dec 2022 18:56:05 GMT
content-length: 0
location: https://cardiff.marketing/test/
[...]

It gave me a 200 code and didn't redirect.

What was the solution?

Eventually I tracked it down to this line in the Static Forms Plugin, on which the MailChannel Plugin was based:

return new Response([101, 204, 205, 304].includes(response.status) ? null : response.body, { …response, headers: new Headers(response.headers) });

This should be reforming the immutable Response object that is returned with all it's propertes (...response). What I found instead is it overwrote ever request with a 200 status code no matter what I did. There didn't seem to be any reason to shield the client from these codes. The expected behaviour of submitting a POST request is to get some kind of response. What is even stranger, is both Response objects are generated by handlers elsewhere. I replaced the code:

return response
> curl --include https://cardiff.marketing/test/
HTTP/2 301
date: Thu, 15 Dec 2022 18:56:05 GMT
content-length: 0
location: https://cardiff.marketing/about/
[...]

And suddenly it worked!

If anyone knows how to contact the people maintaining these packages I'd love to push an update to them. In the meantime, I've created two replacements for the official versions that also include built-in Turnstile compatibility. You can find them on Github.

  1. Cloudflare Pages - Static Forms Plugin

  2. Cloudflare Pages - MailChannels Plugin

These are my first public packages so I'd appreciate any feedback you have.