Juan Jose
Juan Jose

Reputation: 1

Error when trying to send emails with outlook using nodemailer

I am trying to send outlook emails with nodemailer and I am getting this error:

Error: Invalid login: 535 5.7.3 Authentication unsuccessful [BN9PR03CA0154.namprd03.prod.outlook.com 2025-02-13T18:17:02.115Z 08DD4C32F81A9E14] at SMTPConnection._formatError (/home/juanj/Proyectos/BrevortStudios/prima-mailing-api/files/api/node_modules/nodemailer/lib/smtp-connection/index.js:807:19) at SMTPConnection._actionAUTHComplete (/home/juanj/Proyectos/BrevortStudios/prima-mailing-api/files/api/node_modules/nodemailer/lib/smtp-connection/index.js:1586:34) at SMTPConnection.<anonymous> (/home/juanj/Proyectos/BrevortStudios/prima-mailing-api/files/api/node_modules/nodemailer/lib/smtp-connection/index.js:1779:22) at SMTPConnection._processResponse (/home/juanj/Proyectos/BrevortStudios/prima-mailing-api/files/api/node_modules/nodemailer/lib/smtp-connection/index.js:991:20) at SMTPConnection._onData (/home/juanj/Proyectos/BrevortStudios/prima-mailing-api/files/api/node_modules/nodemailer/lib/smtp-connection/index.js:772:14) at TLSSocket.SMTPConnection._onSocketData (/home/juanj/Proyectos/BrevortStudios/prima-mailing-api/files/api/node_modules/nodemailer/lib/smtp-connection/index.js:195:44) at TLSSocket.emit (node:events:518:28) at addChunk (node:internal/streams/readable:559:12) at readableAddChunkPushByteMode (node:internal/streams/readable:510:3) at TLSSocket.Readable.push (node:internal/streams/readable:390:5) { code: 'EAUTH', response: '535 5.7.3 Authentication unsuccessful [BN9PR03CA0154.namprd03.prod.outlook.com 2025-02-13T18:17:02.115Z 08DD4C32F81A9E14]', responseCode: 535, command: 'AUTH XOAUTH2' }

I logged in with my hotmail and went into the azure portal, created an application and set api permissions (Mail.ReadWrite, Mail.Send, offline_access and User.Read) and granted admin consent for Default Directory:

enter image description here

Also create the customer secret enter image description here

And I put the redirection URI as well. So I am generating the link to authenticate myself and if it is working well (state is the data I need):

          const oAuth2ClientOutlook = new AuthorizationCode({
            client: {
                id: global.outlookPrimaMailServiceClientId,
                secret: global.outlookPrimaMailServiceClientSecret,
            },
            auth: {
                tokenHost: "https://login.microsoftonline.com",
                authorizePath: `/${global.outlookPrimaMailServiceTenantId}/oauth2/v2.0/authorize`,
                tokenPath: `/${global.outlookPrimaMailServiceTenantId}/oauth2/v2.0/token`,
            },
          });
        
          const authUrlOutlook = oAuth2ClientOutlook.authorizeURL({
            redirect_uri: global.outlookPrimaMailServiceRedirectURI,
            scope: "https://graph.microsoft.com/Mail.Send offline_access",
            response_type: "code",
            state: encodeURIComponent(state)
          });

Once authenticated it redirects me to my callback and this is in charge of receiving the code sent by microsoft and ask for the access_token and refresh_token in this way:

try {
  
              // Intercambiar el c贸digo por tokens en Microsoft
              const tokenParams = new URLSearchParams({
                  client_id,
                  client_secret,
                  code,
                  redirect_uri,
                  grant_type: 'authorization_code'              
                });

              const response = await axios.post(
                  `https://login.microsoftonline.com/${global.outlookPrimaMailServiceTenantId}/oauth2/v2.0/token`,
                  tokenParams,
                  { headers: { "Content-Type": "application/x-www-form-urlencoded" } }
              );
              tokens = response.data;
              console.log("XXXXXXXXXXXXXX", response.data)
              // Obtener informaci贸n del usuario desde Microsoft Graph
              const userInfoResponse = await axios.get("https://graph.microsoft.com/v1.0/me", {
                  headers: { Authorization: `Bearer ${tokens.access_token}` },
              });
  
              userInfo = userInfoResponse.data;
              console.log("馃懁 Usuario autenticado:", userInfo);
            } catch (error) {
              console.error(error)
            }

Everything works fine and shows me the console.log nicely with the user data. Then I save the access_token and refresh_token in a mongo collection.

And when the user is going to send the mail I do it with nodemailer in this way:

  const accountTransport: any = {
            "host": 'smtp.office365.com',
            "port": 587,
            "secure": false, 
            "auth": {
              "type": "OAuth2",
              "user": dataFromIntegrationsTokens.userEmail(el email de la persona),
              "clientId": global.clientIdOutlook,
              "clientSecret": global.clientSecretOutlook,
              "refreshToken": dataFromIntegrationsTokens.refreshToken(el refresh_token guardado en mongo),
              "accessToken": dataFromIntegrationsTokens.token(el access_token guardado en mongo)

            }
        };

const message = {
                        from: `${getTokensByUserIdAndTenantCode.userFullName} 馃摟 <${getTokensByUserIdAndTenantCode.userEmail}>`,
                        to: sendEmailData.to,
                        subject: sendEmailData.subject,
                        html: sendEmailData.html
                    };
                    const transporter = nodemailer.createTransport(accountTransport);
                    const info = await transporter.sendMail(message);
                    return info;

And in the line const info = await transporter.sendMail(message); I get the error mentioned above.

Does anyone know how to fix this?

Upvotes: 0

Views: 43

Answers (0)

Related Questions