Nodemailer Error: Missing credentials for "PLAIN" - firebase

Nodemailer was working a few days ago with these exact settings but new im suddenly getting this error. i don't have clientsID, accessToken or anything like that. Im just trying to run this for my school project. Please help.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const nodemailer = require("nodemailer")
const cors = require("cors")({
origin: true
});
admin.initializeApp();
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'xxxxxxxxxg#gmail.com',
pass: process.env.GMAIL_PASSWORD,
port: 587,
secure: false,
}
});
exports.emailFirma = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const { web, email } = req.body;
const mailOptions = {
from: 'noreply#gmail.com',
to: "xxxxxxxxxxxxg#gmail.com",
subject: `Mail za potvrdu registracije ${email}`,
html: `Web adresa firme: ${web}, provjeriti ispravnost e-maila: ${email}`
};
return transporter.sendMail(mailOptions, (erro) => {
if (erro) {
return res.send(erro.toString());
}
return res.send('Sent');
});
});
});
Edit: I enabled "Less secure" apps and Captcha but its still not working..

by console.log(process.env.GMAIL_PASSWORD); before admin initialize code, you may find out that it is undefined. So a quick fix would be putting your password in front of pass in single quotes like this until you find a better way to do it.
pass: 'yourpassword',

Related

Mern Stack : Passport.js google auth not working in production (heroku and firebase)

My application works as expected in localhost but when I deploy express backend to heroku and react frontend to firebase the google authentication stop working.
In heroku logs , I get the user profile from google and I get user logged from serialize and deserialize functions but when I make a request to get current user I get undefined.
For some reason the server is not setting the cookies in the browser , I can't find any session cookie when I open the cookies in storage in the browser.
I tried every possible solution I found in the internet but the problem persists.
Edit
I moved my frontend to heroku and removed domain from cookie options , this time it worked but only in private mode , any idea about why its not working in normal mode?
here is the code:
server.js
import express from "express";
import mongoose from "mongoose";
import passport from "passport";
import "./passport.js";
import routerLogin from "./routes/auth.js";
import routerUser from "./routes/user.js";
import cookieSession from "cookie-session";
import cookieParser from "cookie-parser";
import { createRequire } from "module";
const require = createRequire(import.meta.url);
require("dotenv").config();
const bodyParser = require("body-parser");
const morgan = require("morgan");
import cors from "cors";
const app = express();
app.use(cookieParser());
app.use(
cors({
origin: "https://appname-339620.firebaseapp.com",
credentials: true,
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
})
);
app.use(bodyParser.json());
// db connection
mongoose
.connect(process.env.DATABASE, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("DB Connected"))
.catch((err) => console.log("DB Connection Error: ", err));
//middlewares
app.use(morgan("dev"));
app.use(express.json());
app.set("trust proxy", 1);
app.use(
cookieSession({
name: "SocialMedia-auth-session",
secret: process.env.SESSION_SECRET,
httpOnly: true,
secure: true,
sameSite: "none",
domain: "https://appname-339620.firebaseapp.com/",
})
);
app.use(passport.initialize());
app.use(passport.session());
// routes
app.use("/", routerLogin);
app.use("/", routerUser);
const port = process.env.PORT || 8000;
app.listen(port, () => console.log(`the app listening on port ${port}!`));
passport.js
import passport from "passport";
import User from "./models/user.js";
import Google from "passport-google-oauth20";
const GoogleStrategy = Google.Strategy;
import { createRequire } from "module";
const require = createRequire(import.meta.url);
require("dotenv").config();
passport.serializeUser((user, done) => {
console.log("user from serialize", user);
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
const user = await User.findById(id).populate("bookmarks");
console.log("user from deserialize", user);
done(null, user);
});
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_APP_ID,
clientSecret: process.env.GOOGLE_APP_SECRET_KEY,
callbackURL: "/auth/google/callback",
proxy: true,
},
async (accessToken, refreshToken, profile, done) => {
console.log("profile from google =>", profile);
const user = await User.findOne({ GoogleID: profile.id });
if (!user) {
const newUser = await User.create({
GoogleID: profile.id,
name: profile.displayName,
email: profile.emails[0].value,
picture: profile.photos[0].value,
});
if (newUser) {
done(null, newUser);
}
} else {
done(null, user);
}
}
)
);
callback route in auth.js
routerLogin.get(
"/auth/google/callback",
passport.authenticate("google", {
successRedirect: "https://appname-339620.firebaseapp.com",
failureRedirect: "https://appname-339620.firebaseapp.com/error",
})
);
current user Route
routerUser.get("/auth/user", async (req, res) => {
console.log("req.user =>", req.user); // undefined in production
res.send(req.user);
});
axios call to current user
useEffect(() => {
const ourRequest = axios.CancelToken.source();
const fetchUser = async () => {
try {
const res = await axios.get(
"/auth/user",
{
withCredentials: true,
},
{ cancelToken: ourRequest.token }
);
if (res.data) {
setUser({ user: res.data, loggedIn: true });
}
}
} catch (err) {
setUser({ ...state, userError: true });
showNotification({ // I get this error notification when I try to connect in production
color: "red",
message: "failed to connect ! ",
autoClose: 5000,
disallowClose: true,
icon: <AlertOctagon size={22} strokeWidth={1} color={"white"} />,
});
}
};
fetchUser();
return () => ourRequest.cancel;
}, []);
axios default base URL in app.js
axios.defaults.baseURL = "https://nameapp.herokuapp.com";
Authorized redirect URIs in google settings
https://nameapp.herokuapp.com/auth/google/callback
My mistake was I forgot to add https:// in the url bar in normal chrome tab , normal chrome tab doesn't accept cookies when the url is not secure (http) , only incognito mode accept cookies in http.
I also removed domain from cookie option(server.js) when I moved my react app to heroku.(but I think you should keep it when hosting to firebase)
Maybe it wasn't necessary to move from firebase, I believe I was making the same mistake when my frontend was hosted on firebase .. but I'm too lazy to check it now

Nodemailer in vercel not sending email in production

I'm using Nodemailer to send emails in my serverless Next.js project, deployed in Vercel, which works perfectly in development mode. But I'm having problems in production. No error returned, everything works the same way as is development mode, except I don't receive any email.
I have another project built with React and deployed in Heroku where I send emails the same way and it works fine, development and production, so I understand the problem is with Vercel.
Yes, I enabled "Allow Less Secured Apps" in Google account and yes, I enabled Captcha.
I also read this https://vercel.com/docs/solutions/email but it doesn't really make me understand what I should do in my case. I can see it's a matter of SMTP but I don't know what exactly.
Anybody experienced this kind of problem? How can I fix this?
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
auth: {
user: myEmail#gmail.com,
pass: myEmailPass
}
});
const mailOptions = {
from: `${req.body.name} ${req.body.email}`,
to: myEmail#gmail.com,
subject: `${req.body.subject}`,
text: `Text: ${req.body.text}`
}
transporter.sendMail(mailOptions, (err, res) => {
if(err) {
console.log(err);
} else {
console.log("success");
}
});
UPDATE
I changed to SendGrid: made an account, created an API Key, and changed the code like so(instead the one above):
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: `myEmail#gmail.com`,
from: `myEmail#gmail.com`,
subject: `${req.body.subject}`,
text: `${req.body.text}`
};
sgMail
.send(msg)
.then(() => {
console.log('email sent')
})
.catch((error) => {
console.error("error", error)
});
It logs out "email sent" but I don't receive any email.
It's the same problem like with Nodemailer.
I'm confused now...
I ran into this issue and managed to fix it and keep using nodemailer by adding in promises with async/await.
const nodemailer = require("nodemailer");
export default async (req, res) => {
const { firstName, lastName, email, message } = JSON.parse(req.body);
const transporter = nodemailer.createTransport({
port: 465,
host: "smtp.gmail.com",
auth: {
user: "myEmail#gmail.com",
pass: "password",
},
secure: true,
});
await new Promise((resolve, reject) => {
// verify connection configuration
transporter.verify(function (error, success) {
if (error) {
console.log(error);
reject(error);
} else {
console.log("Server is ready to take our messages");
resolve(success);
}
});
});
const mailData = {
from: {
name: `${firstName} ${lastName}`,
address: "myEmail#gmail.com",
},
replyTo: email,
to: "recipient#gmail.com",
subject: `form message`,
text: message,
html: `${message}`,
};
await new Promise((resolve, reject) => {
// send mail
transporter.sendMail(mailData, (err, info) => {
if (err) {
console.error(err);
reject(err);
} else {
console.log(info);
resolve(info);
}
});
});
res.status(200).json({ status: "OK" });
};
This problem is really confusing indeed. I've managed to fix this by simply adding async/await. This is because streaming responses (fire-and-forget functions) are not supported by Vercel.
Source: https://vercel.com/docs/platform/limits#streaming-responses
I have already encountered the same problem, nodemailer was not working on vercel but on heroku everything worked perfectly. it is specified in the doc that vercel does not block stmp connections but according to what I have experienced, in practice stmp connections are blocked. what you can do is use an alternative to nodemailer. use sendgrid and it works fine
An article on how integrating Sendgrid with Next.js
I had a similar issue with Nodemailer but I fixed it by first adding the environment variables in Vercel then commit to the github(It will automatically be uploaded on vercel). So add the variables to vercel first for it to take effect
In my own case, wrapping my email function with async solved it for me.
eg:
const sendMessage = async(message)=>{
await transporter.sendMail({...options here})
}
Then in my API I called my function using:
await sendMessage('your message')
I tried all the async/await responses and didn't work at the beginning. Digging through the real time functions logs of the app, I noticed that there was an Error: Missing credentials for "PLAIN", so all I had to do was add the respective .env variables to vercel environment variables and it worked. Here's the complete code though:
import type { NextApiRequest, NextApiResponse } from 'next'
type Data = any
const nodemailer = require('nodemailer')
const auth = {
user: process.env.WEB_MAILER,
pass: process.env.WEB_MAILER_PASSWORD,
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const { name, email, subject, message } = req.body
const mailData = {
to: process.env.EMAIL_TO,
from: process.env.WEB_MAILER,
name: name,
subject: subject,
text: `Email: ${email}.\n\nMessage: ${message}`,
html: `<div>Email: ${email}.\n\nMessage: ${message}</div>`,
}
const transporter = nodemailer.createTransport({
host: 'smtp.titan.email',
secure: true,
port: 465,
auth: auth,
})
const server = await new Promise((resolve, reject) => {
// verify connection configuration
transporter.verify(function (error: any, success: any) {
if (success) {
resolve(success)
}
reject(error)
})
})
if (!server) {
res.status(500).json({ error: 'Error failed' })
}
const success = await new Promise((resolve, reject) => {
// send mail
transporter.sendMail(mailData).then((info: any, err: any) => {
if (info.response.includes('250')) {
resolve(true)
}
reject(err)
})
})
if (!success) {
res.status(500).json({ error: 'Error sending email' })
}
res.status(200).json({ success: success })
}

Send email via firebase functions with hostgator accounts

I am having trouble sending emails through firebase functions, the mail account is from hostgator, I have done tests locally and it sends it without problem but when I upload the function to firebase the emails do not reach the destination and in the logs there are no errors, what could be happening?
The configuration is as follows:
var transporter = nodemailer.createTransport ({
host: ‘mail.example.com’,
port: 587,
secure: false,
auth: {
user: 'info#example.com’,
pass: ‘password’
},
tls: {
ciphers: ‘SSLv3’
},
debug: true
});
I have even tried other settings.
You can try this following snipet:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
const cors = require('cors')({origin: true});
admin.initializeApp();
/**
* Here we're using Gmail to send
*/
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'yourgmailaccount#gmail.com',
pass: 'yourgmailaccpassword'
}
});
exports.sendMail = functions.https.onRequest((req, res) => {
cors(req, res, () => {
// getting dest email by query string
const dest = req.query.dest;
const mailOptions = {
from: 'Your Account Name <yourgmailaccount#gmail.com>', // Something like: Jane Doe <janedoe#gmail.com>
to: dest,
subject: 'I\'M A PICKLE!!!', // email subject
html: `<p style="font-size: 16px;">Pickle Riiiiiiiiiiiiiiiick!!</p>
<br />
<img src="https://images.prod.meredith.com/product/fc8754735c8a9b4aebb786278e7265a5/1538025388228/l/rick-and-morty-pickle-rick-sticker" />
` // email content in HTML
};
// returning result
return transporter.sendMail(mailOptions, (erro, info) => {
if(erro){
return res.send(erro.toString());
}
return res.send('Sended');
});
});
});
I have taken it from this page where you can find the whole tutorial.
Try this, you can see on the cPanel email configs:
let mailerConfig = {
service: "mail.DOMAIN.com",
host: "mail.DOMAIN.com",
secureConnection: true,
port: 465,
auth: {
user: EMAIL,
pass: PASSWORD,
},
};
let transporter = nodemailer.createTransport(mailerConfig);
Also, you can try to configure the firbase trigger:
Firebase Email Trigger

Authenticate Firebase with Auth0 using Netlify Lambda Functions

I have a web app built with Gatsby that has client-side authentication through Auth0. I want to use Firebase as a database for my project, but I need to authenticate users first before they can read/write to Firebase.
The Firebase SDK (firebase-admin) has a function called signInWithCustomToken(token) that I thought I could pass the token from Auth0 into, but this doesn't work (see: https://community.auth0.com/t/react-auth0-firebase/11392).
Instead, I need to proxy Auth0's token through an API which will use firebase-admin to issue a token. Because my Gatsby site is hosted on Netlify, I'm planning to use Netlify Lambda Functions to get proxy Auth0's token. This is where I'm getting stuck.
I've followed this tutorial on how to use Netlify Lambda Functions with Gastsby: https://www.gatsbyjs.org/blog/2018-12-17-turning-the-static-dynamic/
I then went into my Auth.js file where my Auth0 code is and dropped a fetch call in the setSession. I passed the idToken from Auth0 into the url in the fetch function. I'm not sure if this is the right thing to do. I've read in the tutorial that it would be passed in an authorization header, but I'm unclear what that means. Anyways, here's the complete auth.js file:
import auth0 from 'auth0-js';
const windowGlobal = typeof window !== 'undefined' && window;
class Auth {
auth0 = new auth0.WebAuth({
domain: process.env.Auth_Domain,
clientID: process.env.Auth_ClientId,
redirectUri: process.env.Auth_Callback,
responseType: 'token id_token',
scope: 'openid profile email',
});
constructor() {
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
this.handleAuthentication = this.handleAuthentication.bind(this);
this.isAuthenticated = this.isAuthenticated.bind(this);
}
login() {
this.auth0.authorize();
}
logout() {
// Remove the locally cached profile to avoid confusing errors.
localStorage.removeItem('access_token');
localStorage.removeItem('id_token');
localStorage.removeItem('expires_at');
localStorage.removeItem('user');
windowGlobal.window.location.replace(`https://login.skillthrive.com/v2/logout/?returnTo=http%3A%2F%2Flocalhost:8000`)
}
handleAuthentication() {
if (typeof window !== 'undefined') {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult)
} else if (err) {
console.log(err);
}
});
}
}
isAuthenticated() {
const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
return new Date().getTime() < expiresAt;
}
setSession(authResult) {
const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
localStorage.setItem('access_token', authResult.accessToken);
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('expires_at', expiresAt);
fetch(`/.netlify/functions/firebase?id=${authResult.idToken}`)
.then(response => console.log(response))
this.auth0.client.userInfo(authResult.accessToken, (err, user) => {
localStorage.setItem('user', JSON.stringify(user));
})
}
getUser() {
if (localStorage.getItem('user')) {
return JSON.parse(localStorage.getItem('user'));
}
}
getUserName() {
if (this.getUser()) {
return this.getUser().name;
}
}
}
export default Auth;
I found a tutorial called How to Authenticate Firebase and Angular with Auth0 that has a function that mints a token for Firebase:
const jwt = require('express-jwt');
const jwks = require('jwks-rsa');
const firebaseAdmin = require('firebase-admin');
// Config
const config = require('./config');
module.exports = function(app) {
// Auth0 athentication middleware
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${config.AUTH0_DOMAIN}/.well-known/jwks.json`
}),
audience: config.AUTH0_API_AUDIENCE,
issuer: `https://${config.AUTH0_DOMAIN}/`,
algorithm: 'RS256'
});
// Initialize Firebase Admin with service account
const serviceAccount = require(config.FIREBASE_KEY);
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: config.FIREBASE_DB
});
app.get('/auth/firebase', jwtCheck, (req, res) => {
// Create UID from authenticated Auth0 user
const uid = req.user.sub;
// Mint token using Firebase Admin SDK
firebaseAdmin.auth().createCustomToken(uid)
.then(customToken =>
// Response must be an object or Firebase errors
res.json({firebaseToken: customToken})
)
.catch(err =>
res.status(500).send({
message: 'Something went wrong acquiring a Firebase token.',
error: err
})
);
});
I tried to incorporate small parts at a time into my Lambda function:
var admin = require("firebase-admin");
const jwt = require('express-jwt');
const jwks = require('jwks-rsa');
// For more info, check https://www.netlify.com/docs/functions/#javascript-lambda-functions
export function handler(event, context, callback) {
console.log("queryStringParameters", event.queryStringParameters);
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${process.env.Auth_Domain}/.well-known/jwks.json`
}),
audience: process.env.Auth_Audience,
issuer: `https://${process.env.Auth_Domain}/`,
algorithm: 'RS256'
});
callback(null, {
// return null to show no errors
statusCode: 200, // http status code
body: JSON.stringify({
msg: "Hello, World! " + Math.round(Math.random() * 10),
}),
})
}
I tried checking to see what came back for jwtCheck by console logging it, but all I got was something weird { [Function: d] unless: [Function], UnauthorizedError: [Function: r] }
How should I go about incorporating this into my Lambda function?
I found a module called serverless-http that allows me to write Lambda Function as if it were written in Express. This made it easy for me to wrap my head around what was happening, so I finally got this code to return the new minted token from Firebase:
const express = require('express');
const serverless = require('serverless-http');
const cors = require('cors');
const jwt = require('express-jwt');
const jwks = require('jwks-rsa');
const firebaseAdmin = require('firebase-admin');
const app = express();
app.use(cors());
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `${process.env.Auth_Domain}/.well-known/jwks.json`
}),
audience: `${process.env.Auth_ClientId}`,
issuer: `${process.env.Auth_Domain}`,
algorithm: 'RS256'
});
const serviceAccount = require('../firebase/firebase-keys.json');
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
});
// GET object containing Firebase custom token
app.get('/firebase', jwtCheck, async (req, res) => {
const {sub: uid} = req.user;
try {
const firebaseToken = await firebaseAdmin.auth().createCustomToken(uid);
res.json({firebaseToken});
} catch (err) {
res.status(500).send({
message: 'Something went wrong acquiring a Firebase token.',
error: err
});
}
});
module.exports.handler = serverless(app);
Then on the client side I wrapped the fetch call into a function like this and used it when needed:
async setFirebaseCustomToken() {
const response = await fetch('/.netlify/functions/firebase', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('id_token')}`,
},
});
const data = await response.json();
console.log(data.firebaseToken);
}
This code is just going to console.log the new token, but now you'll have the response to do what you want with in Firebase client-side. Hope this helps!

Unable to send SMS through Twilio and Google Functions

I am attempting to send a text (a one-time pass code) using Twilio, firebase and Google Functions, and using Postman.
I have run $ npm install --save twilio#3.0.0 -rc.13 in the functions directory.
When I run $ firebase deploy, it completes. But on Postman, when I do POST, Body and feed a JSON { "phone": "555-5555" }, I get an "Error: could not handle the request."
I am able to send a text in Twilio Programmable SMS from my Twilio number to an actual outside number direct to the mobile phone. I'm using live credentials for Sid and AuthToken.
Is this an issue with Twilio, Google Functions and some configurations?
Here are the logs on Functions:
// White flag sign//
Function execution took 1452 ms, finished with status: 'crash'
//Red Warning sign//
TypeError: handler is not a function
at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:26:41)
at /var/tmp/worker/worker.js:676:7
at /var/tmp/worker/worker.js:660:9
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
Also, the google eslint forces consistent-return, which is why I put "return;" in the request-one-time-password.js. I cannot seem to turn it off by adding "consistent-return": 0 in eslintrc.
My code(with secret keys and phone numbers redacted):
//one-time-password/functions/service_account.js
has my keys copied and pasted.
//one-time-password/functions/twilio.js
const twilio = require('twilio');
const accountSid = 'redacted';
const authToken = 'redacted';
module.exports = new twilio.Twilio(accountSid, authToken);
//one-time-password/functions/request-one-time-password.js
const admin = require('firebase-admin');
const twilio = require('./twilio');
module.export = function(req, res) {
if(!req.body.phone) {
return res.status(422).send({ error: 'You must provide a phone number!'});
}
const phone = String(req.body.phone).replace(/[^\d]/g, '');
admin.auth().getUser(phone).then(userRecord => {
const code = Math.floor((Math.random() * 8999 + 1000));
// generate number between 1000 and 9999; drop off decimals
twilio.messages.create({
body: 'Your code is ' + code,
to: phone,
from: '+redacted'
}, (err) => {
if (err) { return res.status(422).send(err); }
admin.database().ref('users/' + phone).update({ code: code, codeValid: true }, () => {
res.send({ success: true });
})
});
return;
}).catch((err) => {
res.status(422).send({ error: err })
});
}
/////////////////////////////////
//one-time-password/functions/index.js
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const createUser = require('./create_user');
const serviceAccount = require('./service_account.json')
const requestOneTimePassword = require('./request_one_time_password');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://one-time-password-650d2.firebaseio.com"
});
exports.createUser = functions.https.onRequest(createUser);
exports.requestOneTimePassword =
functions.https.onRequest(requestOneTimePassword);
You have
module.exports = new twilio.Twilio(accountSid, authToken);
on one line, and further down
module.export = function(req, res) { ... }.
Try changing export to exports.
One thing that tripped me up for a long time was how twilio sent the request body to the cloud function. It sends it in a body object so to access your request body it will look something like this
req.body.body
On top of that it passed it as a JSON string so I had to JSON.parse()
Example I got working:
export const functionName= functions.https.onRequest((req, res) => {
cors(req, res, () => {
let body = JSON.parse(req.body.body);
console.log(body);
console.log(body.service_id);
res.send();
});
});
This also may depend on the Twilio service you are using. I was using their Studio HTTP Request Module.
Hope this helps a little, not sure if it was your exact problem though :(

Resources