mailgun.js: error creating message v3 TypeError: Only absolute URLs are supported

Hello, I’m working on migrating from version 2.0.6 to 3.3.0. I do have a currently working integration using 2.0.6 and on attempts to update to v3 it has consistently thrown type errors.

I’ve followed the new configuration steps of passing in form-data.

I can get the example to work appropriately in by running it in its own file. I as soon as I move it into the helper function for use in a graphql resolver it starts throwing the type error. Even though it is the same code from the running file.

Below is the stack trace that I keep getting:

TypeError: Only absolute URLs are supported
    at getNodeRequestOptions (/.../node_modules/node-fetch/lib/index.js:1305:9)
    at /.../node_modules/node-fetch/lib/index.js:1410:19
    at new Promise (<anonymous>)
    at fetch (/.../node_modules/node-fetch/lib/index.js:1407:9)
    at /.../node_modules/isomorphic-unfetch/index.js:4:34
    at /.../node_modules/mailgun.js/dist/mailgun.js:2:33929
    at new Promise (<anonymous>)
    at w._fetch (/.../node_modules/mailgun.js/dist/mailgun.js:2:33843)
    at o (/.../node_modules/mailgun.js/dist/mailgun.js:2:31546)

Has any one else hit this and resolved it?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 9
  • Comments: 17

Most upvoted comments

The solution I found was to sign up for a competitor : )

@olexandr-mazepa im using nuxt (a vue framework) in Server Side Rendering. I created an api to send email in nuxt.

import bodyParser from 'body-parser'

export default function(){

    const config = this.options.privateRuntimeConfig.mailgun

    this.nuxt.hook('render:setupMiddleware', (app) => {

        app.use(bodyParser.json({limit: '50mb'}));
        app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
        app.use('/api/mailgun/sendmail', sendMail)
    })

    async function sendMail(req, res){
        const formData = require("form-data");
        const Mailgun = require("mailgun.js");
        const mailgun = new Mailgun(formData);

        const data = req.body; 

        const mg = mailgun.client({
          username: config.username,
          key: config.key,
          public_key: config.public_key
        });

        //adjuntos
        let attachments = [];

        Object.keys(data.files).forEach(key => {
            attachments.push(
                {
                 data: new Buffer.from(data.files[key].data, 'base64'), 
                 filename: data.files[key].filename
                },
            )
        })
      
        try{
            //enviamos email
            mg.messages.create(config.domain, {
                "from": data.usuario + " <"+data.usuarioEmail+">",
                "to": [data.toEmail],
                "subject": data.asunto + " ref: #" + data.idLead,
                "html": data.texto,
                "h:Reply-To": config.replayemail,
                "attachment": attachments
            })
            .then((msg) => {
                const dataRes = {result: msg};
                res.setHeader('Content-Type', 'application/json')
                res.end(JSON.stringify(dataRes))
            })
        }catch(error){
            console.log(error)

        }


    }
} 

then i call the api

        ...
         fetch(`${this.$config.baseURL}/api/mailgun/sendmail`, {
                method: 'POST',
                body: JSON.stringify(data),
                headers: {
                    'Content-Type': 'application/json',
                }
            }).then( async (response) => {
                  ....

In development mode it works perfect but when i build and start, it throws me the following error:

 ERROR  Only absolute URLs are supported                                                                                             16:33:18  

  at getNodeRequestOptions (node_modules\node-fetch\lib\index.js:1305:9)
  at node_modules\node-fetch\lib\index.js:1410:19
  at new Promise (<anonymous>)
  at fetch (node_modules\node-fetch\lib\index.js:1407:9)
  at node_modules\mailgun.js\dist\mailgun.js:2:38800
  at new Promise (<anonymous>)
  at Ky._fetch (node_modules\mailgun.js\dist\mailgun.js:2:38703)
  at o (node_modules\mailgun.js\dist\mailgun.js:2:36379)

@olexandr-mazepa I do not use the lib directly, but it is a dependency of https://github.com/orliesaurus/nodemailer-mailgun-transport which I do use. nodemailer-mailgun-transport is locked to version 3.3.0 of mailgun.js, and it’s author have not updated dependencies since March. At the moment it is obvious that, no matter if this bug (?) in mailgun.js was fixed or not, the author of nodemailer-mailgun-transport should have done something (maybe switched back to what was used before mailgun.js).

for anyone that is running into this, I integrated with the api directly rather than the package for this. here’s something similar to what I ended up using.

import FormData from "form-data";
import { Headers } from "node-fetch";

/**
 * helper for sending an email using mailgun
 * @param {{html: string, text: string, subject: string}} content content to ba passed along
 * @param {[string]} toAddresses array of address to send an email to
 */
 function sendEmail(content, toAddresses) {
	const to = toAddresses.join(",");

	const myHeaders = new Headers();

	const basic = Buffer.from(
		`api:${process.env.EMAIL_SENDING_API_KEY}`,
		"utf8",
	).toString("base64");
	myHeaders.append("Authorization", `Basic ${basic}`);

	const formdata = new FormData();
	formdata.append("from", `From Address <${process.env.EMAIL_SENDFROM_ADDRESS}>`);
	formdata.append("to", `${to}`);

	Object.keys(content).forEach((keyName) => {
		formdata.append(keyName, content[keyName]);
	});

	const requestOptions = {
		method: "POST",
		headers: myHeaders,
		body: formdata,
		redirect: "follow",
	};

	const resp = fetch(
		`https://api.mailgun.net/v3/${process.env.EMAIL_DOMAIN}/messages`,
		requestOptions,
	).catch((err) => {
		console.log(`failed to send email template ${content.template} to ${to}`);
		console.log(err);
		return "failed to send email";
	});

	return resp;
}