Nodemailer and Gmail Authorization

Hi I know there is a post about this already, but I couldn’t find any definitive answers. I was hoping if I shared my code someone could help. I followed @Logan Eldridge ( https://www.wix.com/corvid/forum/community-discussion/connecting-google-email-service-to-website-troubles )and @plomteuxquentin ( https://www.wix.com/corvid/forum/community-discussion/javascript-gmail-api )

emailSer

vice.jsw

import nodemailer from ‘nodemailer’;
import { google } from “googleapis”;
import _ from ‘lodash’;
import {emailService as CONFIG_SERVICE} from ‘backend/config.js’;
import {auth2 as CONFIG_AUTH2} from ‘backend/config.js’;
//init OAuth2
const OAuth2 = google.auth.OAuth2;
const oauth2Client = new OAuth2(
CONFIG_AUTH2.clientId,
CONFIG_AUTH2.clientSecret,
CONFIG_AUTH2.playground
);
oauth2Client.setCredentials({
refresh_token: CONFIG_AUTH2.refreshToken
});
// initialize the service by setting up the transport options (with fresh access token);
let initService = oauth2Client.refreshAccessToken().then(tokens => {
const transportOptions = _.cloneDeep(CONFIG_SERVICE.transportOptions);
transportOptions.auth.clientId = CONFIG_AUTH2.clientId;
transportOptions.auth.clientSecret = CONFIG_AUTH2.clientSecret;
transportOptions.auth.refreshToken = CONFIG_AUTH2.refreshToken;
transportOptions.auth.accessToken = tokens.credentials.access_token;
return nodemailer.createTransport(transportOptions);
}). catch (reason => {console.error(‘refresh token error’, reason)});
export function sendApprovedAddress(to, subject, text) {
const data = { from : CONFIG_SERVICE.sender, to, subject,text};
return initService.then(transporter => {
return transporter.sendMail(data);
}).then((responde) => {
console.info('email successfully sent to ', to, responde);
return responde;
}). catch (reason => {
console.error('could not send email to ’ + to, reason);
throw reason;
});
}

config.js

export const auth2 = {
clientId: " -my actual client id- ",
clientSecret: " -my actual secret key- “,
refreshToken: " -my regreshToken from oauthplayground is here -”,
playground: “OAuth 2.0 Playground
};
export const emailService = {
transportOptions:{
service: “gmail”,
auth: {
type: “OAuth2”,
user: " -my actual email address- ",
clientId: null ,
clientSecret: null ,
refreshToken: null ,
accessToken: null
}
},
emailSender: {
name: ’ -my name used on gmail account- ',
address: ’ -my-Email address: same as in User above-
}
}

page code

// For full API documentation, including code examples, visit Velo API Reference - Wix.com
import {sendApprovedAddress} from ‘backend/emailService.jsw’;
$w.onReady( function () {
});

export function button22_click(event) {
//Add your code for this event here:
sendApprovedAddress(" -i’ve tried different emails here- ",“hello”,“this is a test”);
console.log(“hello”);
}


These are there errors i've seen. 

Microsoft Edge:
Unhandled promise rejection TypeError: Cannot read property 'sendMail' of undefined

wix console in preview:

emailService.jsw
Line 39
(node:1) [google-auth-library:DEP007] DeprecationWarning: The refreshAccessToken method has been deprecated, and will be removed in the 3.0 release of google-auth-library. Please use the getRequestHeaders method instead.
could not send email to
{…}
emailService.jsw
Line 45
Invalid login: 535-5.7.8 Username and Password not accepted. Learn more at 535 5.7.8 Check Gmail through other email platforms - Gmail Help q13sm3793401pjc.4 - gsmtp

Google Chrome:

Please help me figure this out. I know the authors of the other posts seem to have figured it out but I guess I just don’t understand.

emailService.jsw is not broken up, it was an error while posting it on this forum, just so everyone knows

I think I may have found your error.

In your config.js you have your variable named “emailSender” but in your emailservice.jsw you’re calling “CONFIG_SERVICE.sender”

this should be “CONFIG_SERVICE.emailSender” to match your variable.

Wow I’m sure that was messing something up or would have messed something up, so I appreciate that, but even with that change I still get an error.

Unhandled promise rejection TypeError: Cannot read property ‘sendMail’ of undefined

@patrickoconrad Ok so heres what i can gather. Either the gmailapis npm is not installed or the refresh toke you have in your code is not correct because sendMail is part of google api and referes to transporter which is tied to initService which further up is what does the refresh token
" let initService = oauth2Client.refreshAccessToken().then(tokens => {" as well as the other token stuff.

I think you may not have your refresh token setup properly with Oath playground.

@logan Okay you’re amazing. Thanks for the help man. I reset-up my access tokens and it worked instantly. Any chance you could share exactly how I can insert const accessToken = oAuth2Client.getAccessToken();

My guess is here somewhere? let initService = oauth2Client.refreshAccessToken().then(tokens => {

but what should it look like or should it go somewhere else? I get an error again when I try and replace it.

Also you mentioned the email cap on free plans on the other post comment. Can you explain if you meant wix, google cloud or something else?

I was looking for a way to do this free. If I can ever figure out 3rd party authorization i would like to use another tutorial to create my own email marketing app too. So price is a factor.

Also if you know any example on how to make this more dynamic?

Hi Patrick I’m glad you got it working. You don’t need to replace anything. The string I gave you was just to explain that it was a token issue. If you got it working then you’re all set no need to change a thing.

The limits are gmail api limits based on on Google. So you can find it somewhere on Google by searching like Gmail app quotas or limits. However I believe for a free account it is like 500 emails sent per day.

So if your within those limits your fine. Also I implemented the Gmail app because it is very fast reliable and most of all freeeeeee. Granted I have apaid cloud platform account, I’m not paying another third party monthly just to be able to send emails.

In summary if you don’t need to send more than 500 emails per day then your gonna be fine with the free plan with Google. But please feel free to find that page and read more into it.

-Logan

@patrickoconrad as far as making it dynamic, you’ll have to learn more about passing variable to backed or using databases as far as making an email list of people’s name and email. Then you can insert these variables into your email string just like you would if you were to comcatonate strings of you want their name in the message.

@patrickoconrad The function refreshAccessToken() has been deprecated. You can use getAccessToken() instead. The code looks like this:

async function createAuthorizedClient() {
   try {
      const oAuth2Client = await createClient();
      let tokens = await getTokens();
      oAuth2Client.setCredentials(tokens);
      const accessToken = oAuth2Client.getAccessToken();
      oAuth2Client.getTokenInfo(accessToken);
      return oAuth2Client;
   } catch (err) {
      console.log("failed to refreh token" + err);
   }
}

The above code is from Example: Google Sheets NPM where you can see a full Google example complete with authentication.

@yisrael-wix Hi, recently I got this error
(node:15707) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
it showed when i clicked a button to send like 25 emails to different recipients. the error showed in the developer console on wix.
The emails did not sent wen they message showed. However i clicked the send button again and i didnt get the error the second time and the emails sent.
Does this error have to do with the nodemailer or googleapis NPM because i dont have “buffer” anywhere in my code in the back end files.

Any explination or know fixes would be great!
Thank you
sincerely,
Logan Eldridge

Thanks @yisrael-wix ! And thanks again @logan and @plomteuxquentin !