Using Axios to post to Mailgun within an Atlas function

I’ve been struggling a bit to implement a custom email/password auth function in Atlas. I’ve tried functions using mailgun.js, mailgun-js, and axios to post a request to Mailgun, but while they’re easy to get running in my local environment I keep getting errors in Atlas. I believe this is because Atlas’s version of Node.js is very out of date, which means a lot of dependencies need to be loaded with long out-of-date versions to run.

Currently this is the function I’m running:

exports = ({ token, tokenId, username }) => {
  const API_KEY = 'my mailgun API key';
  const DOMAIN = 'my mailgun domain';
  
  const axios = require('axios').default;
  axios({
      method: 'post',
      url: DOMAIN,
      auth: {
          username: 'api',
          password: API_KEY
      },
      params: {
          from: "Test <support@domain>",
          to: username,
          subject: "Email Confirmation",
          template: "email_confirmation",
          'h:X-Mailgun-Variables': JSON.stringify({userToken: token, userTokenId: tokenId})
      }
  }).then(
      response => {
          console.log(response)
      },
      reject => {
          console.log(reject)
      }
  )

  return { status: 'pending' };
};

And the error I’m seeing:

> ran at 1681606325251
> took 359.796052ms
> logs: 
TypeError: Invalid scheme
> result: 
{
  "status": "pending"
}
> result (JavaScript): 
EJSON.parse('{"status":"pending"}')

What is TypeError: Invalid scheme referencing? Since this same code runs on my local environment perfectly I’m not sure what it could be. I’ve also uploaded my node_modules dependencies so that I’m using the same dependencies in Atlas.

I’ve also tried it using context.http.post() with the following code in the export function, if that might be a better way to go about it:

  const API_KEY = 'my_mailgun _API_key';
  const DOMAIN = 'my_mailgun_domain';
  context.http.post({
      url: "https://api:my_mailgun _API_key@www.my_mailgun_domain",
      headers: {
        "Content-Type": [ "multipart/form-data" ]
      },
      form: {
          'from': "support@domain",
          'to': username,
          'subject': "Email Confirmation",
          'template': "email_confirmation",
          'h:X-Mailgun-Variables': JSON.stringify({userToken: token, userTokenId: tokenId})
      },
      encodeBodyAsJSON: false
    })
    .then(response => {
      // The response body is encoded as raw BSON.Binary. Parse it to JSON.
      const ejson_body = EJSON.parse(response.body.text());
      return ejson_body;
    })
    .catch( error =>  console.log(error) );

And I’m seeing the following error:

> ran at 1681612573424
> took 315.297896ms
> logs: 
FunctionError: TypeError: invalid character '<' looking for beginning of value
> result: 
{
  "status": "pending"
}
> result (JavaScript): 
EJSON.parse('{"status":"pending"}')

I’ve tried to find documentation on these errors but I haven’t been able to find anything. Am I missing something here?

Hello :wave: @Campbell_Affleck,

Welcome to the MongoDB Community forums :sparkles:

I tested the following code:

exports = ({ token, tokenId })=>{
    "use strict";
    const API_KEY = API_KEY;
    const Domain = `https://api.mailgun.net/v3/${DOMAIN_NAME}/messages`;
    const axios = require('axios').default;
    axios({
        method: 'post',
        url: Domain,
        auth: {
            username: 'api',
            password: API_KEY
        },
        params: {
            from: "Mailgun Sandbox <postmaster@Sandbox.mailgun.org>",
            to: "example@example.com",
            subject: "Email Confirmation",
            template: "testing",
            'h:X-Mailgun-Variables': JSON.stringify({userToken: token, userTokenId: tokenId})
        }
    }).then(
        response => {
            console.log(response);
            console.log('Success');

        },
        reject => {
            console.log(reject);
            console.log('Failed');
        }
    );
    return JSON.stringify({ Status: "Pending" });
};

and it worked fine for me, returning the output as follows:

> ran at 1682956544266
> took 1.095613339s
> logs:
[object Object]
Success
> result: 
"{\"Status\":\"Pending\"}"
> result (JavaScript): 
EJSON.parse('"{\"Status\":\"Pending\"}"')

I also received the email at my recipient email.

It appears that the error is occurring from the reject block. Can you ensure that you have provided all the correct credentials?

Best,
Kushagra

Hey @Kushagra_Kesav, ahhhhh you’re absolutely right. The error was in the credentials not the code, what a silly error :sweat_smile: Thank you! I’ve fixed it up and it works perfectly. I’d seen some conflicting posts on the proper DOMAIN string structure, but it looks like https://api.mailgun.net/v3/${DOMAIN_NAME}/messages; is the proper way to go.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.