MailChannels have recently announced that they will be discontinuing their free API service with Cloudflare Workers as of June 30th. You can find details here:
They also stated in the Cloudflare Discord server that:
Starting next week, you may notice a small fraction (1%) of your connections are rejected with an error message containing a link to the same announcement. Any messages that are accepted by the service will be delivered as usual and we will continue to provide support as usual until the final day of service.
So I would recommend folks migrate now!
Alternatives
I can confidently recommend both Postmark and SendGrid , and have heard good things about Resend .
The Cloudflare developer docs has great tutorials for sending with both Postmark and Resend:
11 Likes
nneil
June 14, 2024, 7:59am
2
I hate that I have to deal will a third party. Cloudflare should provide an alternative.
This is why people end up on AWS; they provide all that you need.
1 Like
maddsua
September 13, 2024, 1:47pm
3
Wow this was quite a stab in the back. I literally learned about it today when I looked at the logs and saw all those errors. At least sending a warning email in advance would be nice
2 Likes
zank
September 13, 2024, 10:12pm
4
I will leave here some prices so people can compare the services
Price per 500 0 mail/month
resend: 20$/month
postmarkapp: 15$/month
sendgrid: 20$/month
aws: ~0.5$ to $1/month (outbound + attachments)
If you end up picking aws and you are on cloudflare pages I suggest to use aws4fetch as the official ses client does not work
here’s an example
import { AwsClient } from "aws4fetch";
import { adminEmail } from "site";
const generateEmailBody = (data: Record<string, any>) => {
let htmlBody = "<h1>New Form Submission</h1><ul>";
let textBody = "New Form Submission\n\n";
for (const key in data) {
const value = data[key];
htmlBody += `<li><strong>${key}:</strong> ${value}</li>`;
textBody += `${key}: ${value}\n`;
}
htmlBody += "</ul>";
return { htmlBody, textBody };
};
const createSendEmailParams = (toAddress: string, fromAddress: string, inputData: Record<string, any>) => {
const { htmlBody, textBody } = generateEmailBody(inputData);
const params = new URLSearchParams();
params.append("Action", "SendEmail");
params.append("Version", "2010-12-01");
params.append("Source", fromAddress);
params.append("Destination.ToAddresses.member.1", toAddress);
// Subject
const subject = `xxx.com - new form submission from ${inputData?.email ?? "Unknown"}`;
params.append("Message.Subject.Data", subject);
params.append("Message.Subject.Charset", "UTF-8");
// Text Body
params.append("Message.Body.Text.Data", textBody);
params.append("Message.Body.Text.Charset", "UTF-8");
// HTML Body
params.append("Message.Body.Html.Data", htmlBody);
params.append("Message.Body.Html.Charset", "UTF-8");
// ReplyToAddresses
if (inputData?.email) {
params.append("ReplyToAddresses.member.1", inputData.email);
}
return params.toString();
};
const aws = new AwsClient({
accessKeyId: ctx.locals?.runtime?.env?.AWS_ACCESS_KEY_ID!, // replace with your environment variable
secretAccessKey: ctx.locals?.runtime?.env?.AWS_SECRET_ACCESS_KEY!, // replace with your environment variable
region: ctx.locals?.runtime?.env?.AWS_REGION || "eu-central-1", // Replace with your AWS region
service: "ses",
});
const endpoint = `https://email.${aws.region}.amazonaws.com/`;
const requestBody = createSendEmailParams(adminEmail, "[email protected] ", input);
try {
const response = await aws.fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
},
body: requestBody,
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`AWS SES SendEmail failed: ${errorText}`);
}
} catch (caught) {
if (caught instanceof Error && caught.name === "MessageRejected") {
return caught;
}
throw caught;
}
Exactly, where was the notice to customers regarding this??!?!
How many emails have I missed due to this I wonder? I’m now adding a weekly check to check the email solution actually works.
This is not good!