I have a node express application that I am attempting to add nodemail support. I have created a gmail account for this purpose (NOTE: the gmail account has "Less Secure App" enabled). My code is as follows:
var mailOptions = {
from: "XXXX#gmail.com",
to: YYYY#gmail.com,
subject: "Test",
generateTextFromHTML: true,
text: 'This is a test'
};
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
xoauth2: xoauth2.createXOAuth2Generator({
user: 'XXXX#gmail.com', // Your gmail address.
clientId: '123456789abcd-123456789abcdef.apps.googleusercontent.com',
clientSecret: 'XXXX-123456789',
refreshToken: '1/abcdefg',
accessToken: '123.abcdef'
})
}
});
transporter.sendMail(mailOptions, function(error, response) {
if (error) {
console.log('BAD' + error);
} else {
console.log('GOOD' + response);
}
transporter.close();
});
I am able to send e-mail some of the time. After a few successful attempts, I get the following error:
Error: connect ETIMEDOUT
I will continue to get these timeout errors and then it will work again for a few attempts.
Related
Trying to complete the Zoom API OAuth Server to Server Flow. Following this guide: https://marketplace.zoom.us/docs/guides/build/server-to-server-oauth-app/#enable-permissions
But I am getting the following response:
data: { reason: 'The application is disabled', error: 'invalid_client' }
Appears active to me:
Authentication request
let zoomAccessTokenConfig = {
headers: {
Authorization: `Basic ${Buffer.from('yXXXXXXXX:UXXXXXXXXX').toString('base64')}`,
}
}
let zoomAccessTokenResponse = await axios.post('https://zoom.us/oauth/token?grant_type=account_credentials&account_id=oXXXXXXXX', null, zoomAccessTokenConfig)
.then(response => {
console.log('response');
console.log(response);
return response?.Access_token;
})
Using Google OAUTH service to send an email using nodemailer. It works in the local environment (windows), but not in production (AlmaLinux OS).However, gave me an "504 XOAUTH2 authentication mechanism not supported" error in production environment.
Any suggestions would be greatly appreciated. Thanks
Code:
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: "test#gmail.com",
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRECT,
refreshToken: process.env.GOOGLE_REFRESH_TOKEN,
accessToken: googleToken
},
tls: {
rejectUnauthorized: true
},
})
const mailData = {
from: "test#gmail.com",
to: emailDetails.to,
subject: emailDetails.subject,
// text: emailDetails.message,
html: `<div>${emailDetails.message}</div>
`
}
// console.log(JSON.stringify(mailData));
transporter.sendMail(mailData, function (err, info) {
if(err){
console.log(err)
res.send({status: 0, message:"Error occured", errors: [{code: "", message: err}]});
} else {
console.log(info)
res.send({status: 1, message:"successfully send an email", errors: []});
}
transporter.close();
})
}).catch(error => console.log(error));
][1]
Error message output here:
enter image description here
I've sent my app for review in the Apple Store Connect, it contains a signing form in order to access its content. I’ve added a demo account credentials in order for them to review it.
Apple Team tried to connect to my app twice using 2 different credentials, they received a custom message that i made, showing that the login/password are wrong, and I’m 100% sure that the password is correct.
Important edit: The application is working correctly on real and virtual devices, and it connect normaly to the server using the form.
The server side is built using Laravel / Passport, and whenever the credentials are wrong: the server response with a 401 error:
{
error:{
error: "invalid_credentials",
message: "The user credentials were incorrect."
},
...
message: "Http failure response for https://mydomain.name/api/oauth/token: 401 Unauthorized",
name: "HttpErrorResponse",
ok: false,
status: 401,
statusText: "Unauthorized",
...
}
N.B: This response shows up on the Google Chome debug console when i try to connect with false credentials, using the Ionic Serve command
I’ve built my app using Ionic 3, and here is how i interpret the server response to show the error message:
this.userProvider.loginUser(this.email.toLowerCase().trim(),this.password).subscribe((response) => {
this.storage.set('access_token',response['access_token']);
this.storage.set('email',this.email.toLowerCase().trim());
}, (response) => {
if(response.status == 401) {
let alert = this.alertCtrl.create({
title: 'Invalid credentials',
message: 'Please check your credentials.',
buttons: ['Fermer']
});
alert.present();
}
}, () => {
....
});
export class UserProvider {
private apiUrl = 'https://mydomain.name/api';
constructor(private httpClient: HttpClient) {
}
public loginUser(email: string, password: string) {
return this.httpClient.post(this.apiUrl + '/oauth/token', {
grant_type: 'password',
client_secret: '******************************************',
client_id: *,
username: email,
password: password
}).map(response => {
return response;
});
}
}
Is it possible that the 401 response received by the Apple Team has another interpretation?
How can i solve this issue ?
I can obtain the OAuth2 token, but can't revoke it.
Reproducing the error:
let token_url = "https://api.twitter.com/oauth2/token";
let revoke_url = "https://api.twitter.com/oauth2/invalidate_token"
let auth = {
username: CLIENT_API_KEY,
password: CLIENT_API_SECRET_KEY
}
axios.post(token_url, "grant_type=client_credentials", { auth })
.then( response => {
let access_token = response.data["access_token"]
axios.post(revoke_url, `access_token=${access_token}`, { auth })
.then( response => {
console.log("REVOKE SUCCESS")
console.log(response)
})
.catch( e=> {
console.log("Failed to revoke")
console.log(e.response.data)
})
})
then I get
Failed to revoke
{ errors:
[ { code: 348,
message:
'Client application is not permitted to to invalidate this token.' } ] }
Tried googling but nothing came out of the code 348 and the message. The http error code is 401 (unauthorized).
I will never be able to revoke my OAuth2 token. Help.
I want to do what the MS Graph sample node app is doing in its integrationTests.js, but that test doesn't work. Here's what I've tried:
Followed the quick start for creating a node.js app.
Ran the app. Ensured it worked by sending an e-mail.
Modified the test Checking that the sample can send an email to use my account parameters.
Tried to run the test. It fails with 403: insufficient scope. The call to get the token returned scopes, but lacked Mail.Send.
In the post data for the call to login.microsoftonline.com, I added "scope: 'Mail.Send'"
I still receive a valid token, and the return scope includes Mail.Send, but when I try to post with that token, I get 400: cannot POST /beta/me/sendMail
I tried adding scope (Mail.Send) in the query string and as a header (thought I saw that somewhere), but it made no difference.
I added the Mail.Send permission (under "Application Permissions") for the app in the application registration portal.
I compared the token (using https://jwt.ms) from my test call to the call from the app when it works. I see no real difference. They both contain the Mail.Send scope.
Here is the code (which is only slightly different from what's in the sample):
// in graphHelper.js
function postSendMail(accessToken, message, callback) {
request
.post('https://graph.microsoft.com/beta/me/sendMail')
//.post('https://graph.microsoft.com/beta/me/sendMail?scope=Mail.Send') // nope
.send(message)
.set('Authorization', 'Bearer ' + accessToken)
.set('Content-Type', 'application/json')
.set('Content-Length', message.length)
.set('scope', 'Mail.Send') // nope
.end((err, res) => {
callback(err, res);
});
}
describe('Integration', function () { // mocha
var accessToken;
var scope;
const config = getConfig();
// My account variables in testConfig.json file
function getConfig() {
var configFilePath = path.join(__dirname, 'testConfig.json');
return JSON.parse(fs.readFileSync(configFilePath, { encoding: 'utf8' }));
}
function getAccessToken(done) {
var postData = querystring.stringify(
{
grant_type: 'password',
//grant_type: 'client_id', // not supported
//grant_type: 'authorization_code', // This assumes you've requested an auth code.
resource: 'https://graph.microsoft.com/',
scope: 'Mail.Send',
client_id: config.test_client_id_v2,
client_secret: config.test_client_secret_v2,
username: config.test_username,
password: config.test_password
}
);
var postOptions = {
host: 'login.microsoftonline.com',
port: 443,
path: '/common/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var postRequest = https.request(postOptions, function (res) {
var data = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
const response = JSON.parse(data);
accessToken = response.access_token;
scope = response.scope;
done();
});
});
postRequest.on('error', function (e) {
console.log('Error: ' + e.message);
done(e);
});
postRequest.write(postData);
postRequest.end();
}
before( // eslint-disable-line no-undef
function (done) {
getAccessToken(done);
}
);
it('Checking that the sample can send an email',
function (done) {
var postBody = emailer.generateMailBody(config.test_name, config.test_username);
graphHelper.postSendMail(
accessToken, scope,
JSON.stringify(postBody),
function (error) {
assert(error === null, `The sample failed to send an email: ${error}`);
done();
});
}
);
});