приложение для отправки данных формы в мой почтовый ящик некорректно работает в Firebase

Думаю, мне здесь не хватает чего-то очень простого. У меня есть простое одностраничное приложение node.js, которое использует nodemailer для отправки любых данных формы в мой почтовый ящик.

Мой файл index.js:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var nodemailer = require('nodemailer');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

var transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
        user: '[email protected]',
        pass: 'mypassword'
    }
});

app.use(express.static('public')); //public folder with my html files
app.get('', function (req, res) {
    res.sendFile(__dirname + "/");
})

app.post('/', function (req, res) {
    response = {
        name: req.body.name,
        email: req.body.email,
        message: req.body.message
    };
    var mailClient = {
        from: '[email protected]',
        to: '[email protected]',
        subject: `Message from ${response.name}`,
        text: 'MyMessage'
    };
    transporter.sendMail(mailClient, function (error, info) {
        if (error) {
            console.log(error); //not happening
        } else {
            res.redirect("/success.html"); //also not happening
        }
    });
})

var server = app.listen(80, function () {
    var host = server.address().address
    var port = server.address().port
    console.log("App listening at http://%s:%s", host, port)
})

Когда я запускаю это на своем локальном компьютере, используя npm start в корневом каталоге, приложение отлично работает на localhost. Nodemailer работает правильно; когда я отправляю, мои данные формы отправляются мне по электронной почте, и я перенаправляюсь на свою страницу успеха.

Однако, когда я развертываю это в Firebase, кажется, что часть nodemailer не работает. Страница загружается с моими статическими файлами, но когда я пытаюсь отправить что-либо через форму, страница просто обновляется (например, когда у вас есть кнопка отправки с пустым HTML), вместо того, чтобы перенаправлять меня на мою страницу успеха и отправлять данные по электронной почте.

Есть ли что-то, что мне нужно изменить в моем коде, чтобы он работал с firebase?

Изменить - без журналов:  введите описание изображения здесь


person user7548189    schedule 09.12.2017    source источник
comment
Что вы находите в логах в консоли? Какой тарифный план у вашего проекта?   -  person Doug Stevenson    schedule 09.12.2017
comment
Если вы говорите о консоли моего сайта, у меня нет ошибок. Я использую бесплатный тарифный план (искра),   -  person user7548189    schedule 09.12.2017
comment
Какая у вас конфигурация nodemailer? И я говорю о журналах функций вашего проекта Firebase, которые видны в консоли Firebase.   -  person Doug Stevenson    schedule 09.12.2017
comment
Поскольку console.log(error) выполняется в облачных функциях на сервере, журнал будет отображаться в панель ведения журнала Cloud Functions на консоли Firebase.   -  person Frank van Puffelen    schedule 09.12.2017
comment
У меня нет журналов в консоли firebase. У меня есть последний nodemailer, указанный в моем package.json.   -  person user7548189    schedule 09.12.2017
comment
Как установить и настроить transporter? Трудно помочь, не увидев минимального полного кода, воспроизводящего проблему. Но я предполагаю, что вы пытаетесь связаться с почтовым сервером, который не находится в домене Google. Подключение к внешним сервисам разрешено только на платных планах. См. А.о. stackoverflow.com/questions/44259405/   -  person Frank van Puffelen    schedule 11.12.2017
comment
Я вставил свой файл index.js (сам по себе минимальный, если честно). Я использую Gmail для nodemailer - возможно, есть еще одна внешняя служба, к которой я пытаюсь подключиться?   -  person user7548189    schedule 11.12.2017
comment
Если у вас вообще нет журналов, это означает, что ваша функция не вызывается. Попробуйте запустить сценарий с помощью локального средства выполнения облачных функций firebase serve --only functions и посмотрите, сможете ли вы запустить его таким образом.   -  person Frank van Puffelen    schedule 15.12.2017
comment
Когда я бегу firebase serve --only functions, я получаю ! functions: Cannot start emulator. Error: Cannot find module 'C:\Users\me\AppData\Roaming\npm\node_modules\firebase-tools\node_modules\grpc\src\node\extension_binary\node-v48-win32-x64-unknown\grpc_node.node'   -  person user7548189    schedule 17.12.2017


Ответы (2)


Google требует платную учетную запись, чтобы использовать "Outbound Networking". Уровень бесплатного пользования не позволяет совершать исходящие звонки. Это будет включать отправку почты на удаленный почтовый сервер (например, отправку электронной почты на учетную запись Yahoo, Gmail или Outlook).

Дополнительную информацию см. на странице их цен.

Ищите «Исходящая сеть».

Если вы хотите использовать API Gmail, вы все равно сможете использовать nodemailer с функциями firebase и достичь того, что ищете, и оставаться на уровне бесплатного пользования. Полностью рабочий пример уже доступно в firebase-samples репозитории! Я хотел бы выделить то, что упоминается в связанном руководстве, а именно, что Gmail имеет квота на отправку писем, о которой вам следует знать.

person Swivel    schedule 11.12.2017
comment
Я заметил, что уровень бесплатного пользования позволяет вам совершать исходящие звонки в сервисы Google (я думаю, что не отправляет в другой почтовый ящик на основе вашего ответа). Есть ли обходной путь без перехода на платный уровень? - person user7548189; 11.12.2017
comment
@ user7548189 Только что обновил ответ! firebase-samples содержит пример использования Gmail для отправки почты через firebase-functions и nodemailer. Как уже отмечалось, существует квота на отправку, но она должна работать, поскольку Gmail API не следует рассматривать как внешнюю службу! Надеюсь, это поможет! - person Swivel; 12.12.2017
comment
Я проверил ваш обновленный ответ, а также попытался перейти на платный план (платите по мере использования). К сожалению, оба варианта не повлияли. Знаете ли вы что-нибудь еще, что могло вызвать проблему? - person user7548189; 13.12.2017

Я попытался выяснить проблему в вашем коде, но не нашел, у меня также есть функция для отправки электронной почты с кодом подтверждения для аутентификации / проверки идентификатора электронной почты. Для этого я создал один идентификатор Gmail и дал этот идентификатор / пароль для отправки почты. Письма отправляются с этого идентификатора gmail с помощью node.js, когда когда-либо пользователь регистрируется с помощью идентификатора электронной почты, мы отправляем электронное письмо с кодом проверки. Мой код такой:

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
var bodyParser = require('body-parser');
var users = require('./users/route');

const app = express();
const nodemailer = require('nodemailer');
// Configure the email transport using the default SMTP transport and a GMail account.
// For other types of transports such as Sendgrid see https://nodemailer.com/transports/
// TODO: Configure the `gmail.email` and `gmail.password` Google Cloud environment variables.
const gmailEmail = '[email protected]';
const gmailPassword = 'password';
const gcm = require('node-gcm');
const mailTransport = nodemailer.createTransport(
        `smtps://${gmailEmail}:${gmailPassword}@smtp.gmail.com`);

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://myapp.firebaseio.com"
});
//admin.initializeApp(functions.config().firebase);

// Express middleware that validates Firebase ID Tokens passed in the Authorization HTTP header.
// The Firebase ID token needs to be passed as a Bearer token in the Authorization HTTP header like this:
// `Authorization: Bearer <Firebase ID Token>`.
// when decoded successfully, the ID Token content will be added as `req.user`.
const authenticate = (req, res, next) => {
    if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer')) {
        res.status(403).send('Unauthorized');
        return;
    }
    const idToken = req.headers.authorization.split('Bearer ')[1];
    admin.auth().verifyIdToken(idToken).then(decodedIdToken => {
        req.user = decodedIdToken;
        next();
    }).catch(error => {
        res.status(403).send('Unauthorized');
    });
};

app.get("/token", (req, res) => {

    res.status(200).send(admin.auth().applicationDefault());
    admin.auth().createCustomToken(req.query.uid)
            .then(function (customToken) {
                res.status(200).send(customToken);
            })
            .catch(function (error) {
                console.log("Error creating custom token:", error);
            });

});


// GET /api/verifyEmail?code="1234"
app.get('/verifyEmail', (req, res) => {

    // Get the one-time code from the query parameter.
    var verificationCode = req.query.code;
    var displayName = req.query.displayName;
    var email = req.query.email; //If GET request
    const mailOptions = {
        from: `Linkuni <[email protected]>`,
        to: email
    };

    // The user subscribed to the newsletter.
    mailOptions.subject = `Welcome to Linkuni`;
    mailOptions.text = `Hi ${displayName || ''}\n\n Welcome to Linkuni. We hope you will enjoy our service. Please enter this code:${verificationCode} into the app.\n\nThank you,\nLinkuni Team`;

    return mailTransport.sendMail(mailOptions).then(() => {
        console.log('Verification email sent to:', email);
    });
});

Надеюсь это поможет!! :)

person sschunara    schedule 17.12.2017