Отправка сообщений с помощью nodemailer и восстановление пароля по электронной почте - PullRequest
0 голосов
/ 11 февраля 2020

Я хочу отправить сброс сообщения электронной почты, используя nodemailer. На самом деле я смог отправить его с использованием необработанных данных. Вот модули / mailModule. js:

const nodemailer = require('nodemailer');

const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: "rawmail@gmail.com",
    pass: "rawpass"
  }
})

const getPasswordResetURL = (user, token) =>
  `http://localhost:3000/password/reset/${user._id}/${token}`

const resetPasswordTemplate = (user, url) => {
  console.log("this");
  console.log(process.env.EMAIL_LOGIN); // this is undefined, but I want to use it in the future
  console.log("email");
  const from = "rawmail@gmail.com"
  const to = user.email
  const subject = "Password Reset"
  const html = `
  <p>Hey ${user.name || user.email},</p>
  <p>We heard that you lost your password. Sorry about that!</p>
  <p>But don’t worry! You can use the following link to reset your password:</p>
  <a href=${url}>${url}</a>
  <p>If you don’t use this link within 1 hour, it will expire.</p>
  return { from, to, subject, html }
}

module.exports = { transporter, getPasswordResetURL, resetPasswordTemplate }

в маршрутах / api / auth. js (я не включил получение пароля, логин и другие функции, чтобы сконцентрироваться на этом)

const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const config = require('config');
const jwt = require('jsonwebtoken');
const auth = require('../../middleware/auth')
const { transporter, getPasswordResetURL, resetPasswordTemplate } = require('../../modules/mailModule');
// Item Model
const User = require('../../models/User');

    router.post('/user', (req, res) => {
      const { email } = req.body
      console.log(email);

      User.findOne({ email })
        .then(user => {
          if (!user) return res.status(400).json({ msg: 'User does not exist' });

          jwt.sign(
            { id: user.id },
            config.get('jwtSecret'),
            { expiresIn: 3600 },
            (err, token) => {
              if (err) throw err;
              res.json({
                token,
                user: {
                  id: user.id,
                  name: user.name,
                  email: user.email
                }
              });
              transporter.sendMail(resetPasswordTemplate(user, getPasswordResetURL(user, token)), (err, info) => {
                if (err) {
                  res.status(500).json("Error sending email")
                }
                // console.log(`** Email sent **`, info.response)
              })
            }
          )
        })
    });

, а также config: config / default. json

{
  "mongoURI": "linkToMyMongoDBCluster",
  "jwtSecret": "jwtSecretPassword"
}

И это самая важная часть. 1) Я пытался передать сообщение с необработанными данными на свою почту, но я получаю сообщения об ошибках:

в терминале:

_http_outgoing.js:470
   [0]     throw new ERR_HTTP_HEADERS_SENT('set');
   [0]     ^
   [0] 
   [0] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
   [0]     at ServerResponse.setHeader (_http_outgoing.js:470:11)
   [0]     at ServerResponse.header (/home/wiktor/myApp/node_modules/express/lib/response.js:771:10)
   [0]     at ServerResponse.send (/home/wiktor/myApp/node_modules/express/lib/response.js:170:12)
   [0]     at ServerResponse.json (/home/wiktor/myApp/node_modules/express/lib/response.js:267:15)
   [0]     at transporter.sendMail (/home/wiktor/myApp/routes/api/auth.js:88:31)
   [0]     at transporter.send.args (/home/wiktor/myApp/node_modules/nodemailer/lib/mailer/index.js:226:21)
   [0]     at connection.login.err (/home/wiktor/myApp/node_modules/nodemailer/lib/smtp-transport/index.js:282:36)
   [0]     at SMTPConnection._actionAUTHComplete (/home/wiktor/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:1523:20)
   [0]     at SMTPConnection._responseActions.push.str (/home/wiktor/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:550:26)
   [0]     at SMTPConnection._processResponse (/home/wiktor/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:942:20)
   [0]     at SMTPConnection._onData (/home/wiktor/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:749:14)
   [0]     at TLSSocket.SMTPConnection._onSocketData.chunk (/home/wiktor/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:195:44)
   [0]     at TLSSocket.emit (events.js:189:13)
   [0]     at addChunk (_stream_readable.js:284:12)
   [0]     at readableAddChunk (_stream_readable.js:265:11)
   [0]     at TLSSocket.Readable.push (_stream_readable.js:220:10)

на gmail:

Login attempt has been blocked

Someone just tried to sign in to your account using a non-Google application. We blocked this attempt, but we advise you to check.(translated by google translator)

2 ) Я также не могу получить этот process.env.EMAIL_LOGIN и process.env.EMAIL_PASSWORD. Где я могу установить или получить их?

А вот мои authActions и authReducer. js:

client / src / actions / authActions. js (без входа в систему, регистрации и других действия, также я не использую тип RESET_PASSWORD, потому что я еще не сделал редуктор, поэтому я использую LOGIN_SUCCESS и LOGIN_FAIL, но это скоро изменится):

import axios from 'axios';
import { returnErrors } from './errorActions';

import {
  USER_LOADED,
  USER_LOADING,
  AUTH_ERROR,
  LOGIN_SUCCESS,
  LOGIN_FAIL,
  LOGOUT_SUCCESS,
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  CHANGE_PASSWORD,
  CHANGE_PASSWORD_FAIL,
  RESET_PASSWORD
} from './types';

// reset password
export const resetPassword = (email) => (dispatch) => {
  // Headers
  console.log(email);
  const config = {
    headers: {
      'Content-Type': 'application/json'
    }
  }

  // Request body
  // const body = JSON.stringify(email)


  axios.post(`/api/auth/user`, email, config)
    .then(res => dispatch({
      type: LOGIN_SUCCESS,
      payload: res.data
    }))
    .catch(err => {
      dispatch(returnErrors(err.response.data, err.response.status, 'LOGIN_FAIL'));
      dispatch({
        type: LOGIN_FAIL
      });
    });
}

и client / src / redurs /authReducers.js

import {
  USER_LOADED,
  USER_LOADING,
  AUTH_ERROR,
  LOGIN_SUCCESS,
  LOGIN_FAIL,
  LOGOUT_SUCCESS,
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  CHANGE_PASSWORD,
  CHANGE_PASSWORD_FAIL,
  RESET_PASSWORD
} from '../actions/types';

const initialState = {
  token: localStorage.getItem('token'),
  isAuthenticated: false,
  user: null
};

export default function (state = initialState, action) {
  switch (action.type) {
    case USER_LOADING:
      return {
        ...state,
        isLoading: true
      };
    case USER_LOADED:
      return {
        ...state,
        isAuthenticated: true,
        isLoading: false,
        user: action.payload
      };
    case LOGIN_SUCCESS:
    case REGISTER_SUCCESS:
      localStorage.setItem('token', action.payload.token);
      return {
        ...state,
        ...action.payload,
        isAuthenticated: true,
        isLoading: false
      };
    case RESET_PASSWORD:
      localStorage.setItem('token', action.payload.token);
      return {
        ...state,
        ...action.payload,
        isAuthenticated: true,
        isLoading: false
      }
    case AUTH_ERROR:
    case LOGIN_FAIL:
    case LOGOUT_SUCCESS:
      localStorage.removeItem('token');
      return {
        ...state,
        token: null,
        user: null,
        isAuthenticated: false,
        isLoading: false
      };
    case REGISTER_FAIL:
      return {
        ...state
      };
    case CHANGE_PASSWORD:
      return {
        ...state,
        user: action.payload,
      };
    case CHANGE_PASSWORD_FAIL:
      return {
        ...state
      }
    default:
      return state;

  }
}
...