Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fails in cloudflare-workers environment #341

Open
nosovk opened this issue Jan 24, 2023 · 11 comments
Open

Fails in cloudflare-workers environment #341

nosovk opened this issue Jan 24, 2023 · 11 comments

Comments

@nosovk
Copy link

nosovk commented Jan 24, 2023

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)"

Related issues: 1, 2, 3

@nosovk nosovk changed the title Fails in cloudflare-workers example Fails in cloudflare-workers environment Jan 24, 2023
@nosovk
Copy link
Author

nosovk commented Jan 24, 2023

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
});

@leviwheatcroft
Copy link

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
		}

@nosovk
Copy link
Author

nosovk commented Feb 3, 2023

@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)

@leviwheatcroft
Copy link

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.

@nosovk
Copy link
Author

nosovk commented Feb 4, 2023

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

@allenfuller
Copy link

+1 running into this issue w/ Mailgun.js 8.1.0 in a Meteor.js app.

@Knaackee
Copy link

Knaackee commented Dec 4, 2023

Same here, running a remix app on cloudflare workers.

@nosovk
Copy link
Author

nosovk commented Dec 4, 2023

Same here, running a remix app on cloudflare workers.

you may use solution form #341 (comment) 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

@whoislewys
Copy link

whoislewys commented Mar 6, 2024

I need attachments, how would you do this with attachments? Link attachments sometimes get blocked by certain email clients

@nosovk
Copy link
Author

nosovk commented Mar 6, 2024

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.

@markusahlstrand
Copy link

How can this not have been fixed? Cloudflare is a pretty big platform and it's been an open issue for two years..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants