mailgun.js
mailgun.js copied to clipboard
Fails in cloudflare-workers environment
When I try to use mailgun.js in Cloudflare worker it fails with error:
define is not defined
Full trace:
"ReferenceError: define is not defined\n at node_modules/mailgun.js/mailgun.web.js (worker.mjs:2093:5)\n at __require (worker.mjs:12:50)\n at .svelte-kit/output/server/entries/pages/contactus/_page.server.js (worker.mjs:5109:30)\n at __init (worker.mjs:9:56)\n at .svelte-kit/output/server/nodes/4.js (worker.mjs:5200:5)\n at __init (worker.mjs:9:56)\n at worker.mjs:7931:43\n at async Promise.all (index 1)\n at async respond (worker.mjs:7691:23)\n at async Object.fetch (worker.mjs:8035:15)"
Minimal code reproduction:
import formData from 'form-data';
import Mailgun from 'mailgun.js';
import { MAILGUN_API_KEY } from '$env/static/private';
const mailgun = new Mailgun(formData);
const mg = mailgun.client({
username: 'api',
url: 'https://api.mailgun.net',
key: MAILGUN_API_KEY
});
Not a solution, but for others wanting to implement a simple send fn using a native request this might save some time...
You need to define the env keys, and the message param should be an object containing from, to, subject, and text
async function mailgunSend (message) {
const {
MAILGUN_API_KEY,
MAILGUN_BASE_URL,
MAILGUN_DOMAIN
} = env
const body = new FormData()
Object.entries(message).forEach(([key, value]) => body.append(key, value))
const request = new Request(
`${MAILGUN_BASE_URL}/v3/${MAILGUN_DOMAIN}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Basic ${btoa(`api:${MAILGUN_API_KEY}`)}`,
},
body
}
)
const response = await fetch(request)
return response
}
@leviwheatcroft thanks, I came to that solution also.
But I use cloudflare workers, and there is no FormData there (node 18 not available now).
That's why I make some check, and found that you can do the same without FormData.
Mailgun supports application/x-www-form-urlencoded
If you don't need to send attachments you can write something like that:
const body = new URLSearchParams();
body.append('from', '[email protected]');
body.append('to', '[email protected]');
body.append('subject', 'mail from site');
body.append('html', `<h1>my mail</h1>`);
const res = await fetch(`https://api.mailgun.net/v3/${mg.domain}/messages`, {
method: 'POST',
body: body.toString(),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: authorization
}
});
const json = await res.json();
if (res.status !== 200) {
return fail(500, { success: false, error: json.message ?? 'unknown mail api error' });
}
this will actually work without additional dependencies in NodeJS<18. (in 18 there is native FormData implementation)
I'm using cloudflare workers also, but completely new, haven't tried this in production yet.
FormData is working in the wrangler development environment. It doesn't work in production? I had thought cloudflare workers had a browser-like environment rather than node, which would have FormData.
I use SvelteKit, and can't use workers with nodejs 17 version. SvelteKit works only with LTS versions, 16 or 18. It's possible that FormData works in NodeJS 17. But in NodeJS 16 in CloudFlare workers global FromData
was not present, it was only in request
object. That's why I found workaround with URLSearchParams
+1 running into this issue w/ Mailgun.js 8.1.0 in a Meteor.js app.
Same here, running a remix app on cloudflare workers.
Same here, running a remix app on cloudflare workers.
you may use solution form https://github.com/mailgun/mailgun.js/issues/341#issuecomment-1416505938 it works for a year in different projects. But, unfortunately, it will not work if you want to send attachments. In my case I upload attachment to 3s, and then attach link to email
I need attachments, how would you do this with attachments? Link attachments sometimes get blocked by certain email clients
It will not work with attachments, until you use FormData, that will correctly encode binary data. I've fixed that issue by uploading attachments to CloudFlare R2, and them just inserted links to them. Pretty strange solution, but it helped.