mailgun / mailgun.js

Javascript SDK for Mailgun
https://www.npmjs.com/package/mailgun.js
Apache License 2.0
521 stars 110 forks source link

Mailgun causing 500 Internal Server Error #313

Closed ehteshamshahzad closed 2 years ago

ehteshamshahzad commented 2 years ago

I am building my project in NestJS. My backend is deployed to AWS Serverless (API Gateway). I have implemented Mailgun using the API approach, and it runs perfectly fine on my local machine, even with Serverless Offline. But, when I deploy my code to AWS Serverless and call any end point, I get a 500 Internal Server Error. If I switch from API approach to SMTP approach, it works fine.

Any help with this? I would prefer to go with the API approach.

My code:

import { HttpException, HttpStatus } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as FormData from 'form-data';
import Mailgun from 'mailgun.js';
import { EmailDataDto } from '../dto/email-data.dto';

export class MailgunEmail {

    constructor(private readonly configService: ConfigService) { }

    async sendMailgun(emailDataDto: EmailDataDto) {

        const mailgun = new Mailgun(FormData);
        const client = mailgun.client({
            username: 'api',
            key: this.configService.get<string>('MAILGUN_PRIVATE_API_KEY'),
            url: 'https://api.eu.mailgun.net'
        });

        const result = await client.messages.create('youvouch.com', {
            from: `${emailDataDto.senderName ? emailDataDto.senderName : 'YouVouch'} <${this.configService.get<string>('YV_SOURCE_EMAIL')}>`, // sender address
            sender: `${this.configService.get<string>('YV_SOURCE_EMAIL')}`,
            to: `${emailDataDto.toAddresses ? emailDataDto.toAddresses.toString() : ''}`, // list of receivers
            cc: `${emailDataDto.ccAddresses ? emailDataDto.ccAddresses.toString() : ''}`,
            bcc: `${emailDataDto.bccAddresses ? emailDataDto.bccAddresses.toString() : ''}`,
            replyTo: `${emailDataDto.replyToAddresses ? emailDataDto.replyToAddresses.toString() : ''}`,
            subject: emailDataDto.subject, // Subject line
            html: `${emailDataDto.body}`, // html body
        }).then(res => {
            console.log(res.id);
            return res
        }).catch(err => {
            console.error(err);
            throw new HttpException({
                statusCode: HttpStatus.BAD_REQUEST,
                error: err
            }, HttpStatus.BAD_REQUEST);
        });

        return result;

    }
}
ehteshamshahzad commented 2 years ago

This is what AWS CloudWatch log says:

{
    "errorType": "Runtime.ImportModuleError",
    "errorMessage": "Error: Cannot find module 'form-data'\nRequire stack:\n- /var/task/dist/emails/platforms/mailgun.js\n- /var/task/dist/emails/emails.service.js\n- /var/task/dist/auth/auth.service.js\n- /var/task/dist/app.controller.js\n- /var/task/dist/app.module.js\n- /var/task/dist/serverless.js\n- /var/runtime/UserFunction.js\n- /var/runtime/Runtime.js\n- /var/runtime/index.js",
    "stack": [
        "Runtime.ImportModuleError: Error: Cannot find module 'form-data'",
        "Require stack:",
        "- /var/task/dist/emails/platforms/mailgun.js",
        "- /var/task/dist/emails/emails.service.js",
        "- /var/task/dist/auth/auth.service.js",
        "- /var/task/dist/app.controller.js",
        "- /var/task/dist/app.module.js",
        "- /var/task/dist/serverless.js",
        "- /var/runtime/UserFunction.js",
        "- /var/runtime/Runtime.js",
        "- /var/runtime/index.js",
        "    at _loadUserApp (/var/runtime/UserFunction.js:221:13)",
        "    at Object.module.exports.load (/var/runtime/UserFunction.js:279:17)",
        "    at Object.<anonymous> (/var/runtime/index.js:43:34)",
        "    at Module._compile (internal/modules/cjs/loader.js:1085:14)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)",
        "    at Module.load (internal/modules/cjs/loader.js:950:32)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:790:12)",
        "    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)",
        "    at internal/main/run_main_module.js:17:47"
    ]
}

So something related to it not being able to find 'form-data' 🧐

ehteshamshahzad commented 2 years ago

Solved it! Just run:

npm i form-data

and deploy your code.

Might be a good idea to document this, incase anyone is deploying their backend to Serverless.