Google blocks smtp in react-native - react-native

I am having trouble with google smtp for sending emails from my app.
The app works fine in my mobile and I am able to send emails without any issue.
But When I publish the app and people start using it, I get a security email from google telling me that it has blocked a login try.
I have even enabled less secure login.
Is there any other settings I should enable?
Here is my code for sending emails
import RNSmtpMailer from 'react-native-smtp-mailer'
async sendEmail(email: string, htmlBody: string, subject: string) {
try {
var settings = await this.getAppSettings();
if (!settings)
throw "Could not find the smtp settings"
var success = await RNSmtpMailer.sendMail({
mailhost: settings.smtp,
port: settings.port,
ssl: true, // optional. if false, then TLS is enabled. Its true by default in android. In iOS TLS/SSL is determined automatically, and this field doesn't affect anything
username: settings.email,
password: settings.password,
fromName: "NovelManager", // optional
replyTo: undefined, // optional
recipients: email,
bcc: [], // optional
subject: subject,
htmlBody: htmlBody,
attachmentPaths: [], // optional
attachmentNames: [], // required in android, these are renames of original files. in ios filenames will be same as specified in path. In a ios-only application, no need to define it
});
return true;
} catch (error) {
return false;
}
}
and here is the smtp settings
{
smtp: "smtp.gmail.com",
port: "465",
email: "test#gmail.com", // not the real email
password: "test"
}

Ok at last I found a solution, And that is using app password instead of simple password.
I am posting the solution here incase anyone is intressted.

Related

Give web app permanent control of google email

I recently got a domain from Google Domain and it provides professional emails for the domain. So, I made a support#domain email to send and receive emails. Right now, I built a web app that will use this email to send email-verification to new users who sign up.
I got the code working, however, I used OAuth2.0 from Google to allow the web app to sign into the support email. This causes the Access token to expire and forces me to into my .env file and replace BOTH tokens. How tedious! If I were to publish this web app, I can't just go into my heroku vars and replace the tokens every hour. Thats extremely impractical.
I looked into service accounts by google, but they seem to STILL need OAuth anyways as a 3 legged OAuth. As I am using Express.js, I wanted to know if there was a way to set the tokens and be done with it permanently. Essentially giving the web app permanent control of the google account. What do I do? And what do I use? All advice is greatly appreciated.
Code for sending email verification:
const nodemailer = require("nodemailer")
const dotenv = require("dotenv")
const {generateVerifyToken} = require("./auth")
const { print } = require("#AlecRuin/color-logger")
dotenv.config()
let transporter = nodemailer.createTransport({
service:"gmail",
auth: {
type: 'OAuth2',
user: process.env.EMAIL,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN,
accessToken: process.env.ACCESS_TOKEN
}
})
module.exports= async function(email){
try {
let mailOptions={
from: "support#domain.us",
to:email,
subject:"Verify your email",
text:`
Thank you for signing up with redacted!!
To verify your email (and make sure you're not some kind of annoying bot), simply follow this link:
${process.env.NODE_ENV === "production"?"www.redacted.com":"localhost:3001"}/api/user/verify/?token=${generateVerifyToken(email)}
`
}
print("sending email",new Error,{isClient:false})
transporter.sendMail(mailOptions,(err,data)=>{
if (err){
console.error(err);
return err
}else{
print("Email sent!",new Error,{isClient:false})
return true
}
})
} catch (error) {
print(error,new Error, {isClient:true,severity:4})
return error
}
}

How to send encrypted/TLS emails with NodeJS from localhost using send mail

I want to be able to send emails from my local domain without using gmail or other SMTP servers.
I'm currently using SendMail:
const sendmail = require('sendmail') ({
logger: {
debug: console.log,
info: console.info,
warn: console.warn,
error: console.error
},
dkim: {
privateKey: dkimPrivateKey,
keySelector: 'default'
},
});
sendmail({
from: 'foo#mydomain.com',
to: 'mygmail#gmail.com',
subject: 'test sendmail',
html: 'Mail of test sendmail ',
}, function(err, reply) {
console.log(err && err.stack);
console.dir(reply);
});
and this DOES work, BUT when I receive the email in my Gmail account, and I view the message information, Google is marking this as 'security: No encryption'
From what I understand I need to use TLS to create a 'secure' connection. I already have a certificate and keys from LetsEncrypt and my domain is already using HTTPS. How do I encrypt/use TLS my outgoing emails?
Or is there a better package for this? I've tried using NodeMailer and my emails only get added to a 'queue' and never sent. What is the problem?

Invalid CSRF when logging in to keystone

I'm entirely new to coding. I've looked around a bit, but not found anything relevant.
When logging into keystone to view our mongoDB database I get an error message saying:
Something went wrong; please refresh your browser and try again.
Doing that does not help. Neither does deleting the browser history or attempting from another lap top.
Looking at the javascript console in the browser, the error states invalid csrf.
I think this is the relevant source code in the keystone folder:
handleSubmit (e) {
e.preventDefault();
// If either password or mail are missing, show an error
if (!this.state.email || !this.state.password) {
return this.displayError('Please enter an email address and password to sign in.');
}
xhr({
url: `${Keystone.adminPath}/api/session/signin`,
method: 'post',
json: {
email: this.state.email,
password: this.state.password,
},
headers: assign({}, Keystone.csrf.header),
}, (err, resp, body) => {
if (err || body && body.error) {
return body.error === 'invalid csrf'
? this.displayError('Something went wrong; please refresh your browser and try again.')
: this.displayError('The email and password you entered are not valid.');
} else {
// Redirect to where we came from or to the default admin path
if (Keystone.redirect) {
top.location.href = Keystone.redirect;
} else {
top.location.href = this.props.from ? this.props.from : Keystone.adminPath;
}
}
});
},
How can I go about solving this / debugging the error? Thanks for any help!
This usually happens when session affinity fails. Are you using default in-memory session management? Maybe, try using a database for maintaining session state.
If you use MongoDB, Try the following config setting
'session store': 'mongo',
See 'session store' section under http://keystonejs.com/docs/configuration/#options-database for more details.

Parse-server: Reset Password

I am trying to implement my own local parse-server with my application. Everything is working fine except for reseting password for users.
I receive the following error
(node:8729) UnhandledPromiseRejectionWarning: Unhandledpromiserejection
(rejection id: 2): Error: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title><h1>Not Found</h1><p>The requested URL was not found on
the server.</p>
<p>If you entered the URL manually please check your spelling and try again.</p>
Do you have the email adapter configured in index.js? As per documentation,
Email verification and password reset
Verifying user email addresses and enabling password reset via email requires an email adapter. As part of the parse-server package we provide an adapter for sending email through Mailgun. To use it, sign up for Mailgun, and add this to your initialization code:
var server = ParseServer({
...otherOptions,
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Parse App',
// The email adapter
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
options: {
// The address that your emails come from
fromAddress: 'parse#example.com',
// Your domain from mailgun.com
domain: 'example.com',
// Your API key from mailgun.com
apiKey: 'key-mykey',
}
},
...otherOptions
});

How to create a custom user authentication in Meteor?

I am trying to create the following authentication for an app:
User enters phone number and receives an SMS with a code generated in the server (the SMS is handled through an external service). If the user enters the right code he is logged in.
This means I must have two login stages: registering user with a phone and logging him in with the code, so this is what I think the client should look like:
Meteor.getSmsCode = function(phone, username, callback) {
Accounts.callLoginMethod({
methodName: 'getsmscode',
methodArguments: [{
getsmscode: true,
phone: phone,
username: username
}],
userCallback: callback
});
};
Meteor.loginWithCode = function(phone, code, callback) {
Accounts.callLoginMethod({
methodName: 'login',
methodArguments: [{
hascode: true,
phone: phone,
code: code
}],
userCallback: callback
});
};
But I am confused about the server side - there should be two methods:
the first should only register a user (and communicate with the SMS service) and second should log him in.
This is the server test code for now:
Meteor.users.insert({phone: '123456789', code: '123', username:'ilyo'});
Accounts.registerLoginHandler(function(loginRequest) {
var user = Meteor.users.findOne({phone: loginRequest.phone});
if(user.code !== loginRequest.code) {
return null;
}
var stampedToken = Accounts._generateStampedLoginToken();
var hashStampedToken = Accounts._hashStampedToken(stampedToken);
Meteor.users.update(userId,
{$push: {'services.resume.loginTokens': hashStampedToken}}
);
return {
id: user._id,
token: stampedToken.token
};
});
And this is what happens when I try it:
Why an I getting the 500?
Why doesn't the user have a code and phone fields?
What method should I use for the getSmsCode?
Meteor.createUser is described on How can I create users server side in Meteor?
Then, the Accounts.onCreateUser would contain business logic http://docs.meteor.com/#accounts_oncreateuser
A more exact message for the 500 would be on the server-side stdout. Probably security.
Your Login Handler must return an object as follows:
{ userId: user._id }
Sorry I don't elaborate in the whole problem, I don't agree on your full approach but looks you are in the right path to get the feature you need.
Also, this question is one year old, now there are a few packages at atmosphere that address this kind of authentication =)