Gmail API发送电子邮件错误401:凭据无效

时间:2017-06-30 05:04:37

标签: javascript node.js gmail-api google-api-nodejs-client

我正在开发一个网页,当客户点击"发送电子邮件"重定向到谷歌,要求获得通过客户端电子邮件发送电子邮件的权限,并在客户端重新定向权限后重新定向并发送电子邮件。

到目前为止的代码:

'use strict';

const express = require('express');
const googleAuth = require('google-auth-library');
const request = require('request');

let router = express.Router();
let app = express();

const SCOPES = [
    'https://mail.google.com/'
    ,'https://www.googleapis.com/auth/gmail.modify'
    ,'https://www.googleapis.com/auth/gmail.compose'
    ,'https://www.googleapis.com/auth/gmail.send'
];
const clientSecret = '***********';
const clientId = '**************'; 
const redirectUrl = 'http://localhost:8080/access-granted';
const auth = new googleAuth();
const oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
const authUrl = oauth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES
});

function sendEmail(auth, content, to , from, subject) {
    let encodedMail = new Buffer(
        `Content-Type: text/plain; charset="UTF-8"\n` +
        `MIME-Version: 1.0\n` +
        `Content-Transfer-Encoding: 7bit\n` +
        `to: ${to}\n` +
        `from: ${from}\n` +
        `subject: ${subject}\n\n` +

        content
    )
    .toString(`base64`)
    .replace(/\+/g, '-')
    .replace(/\//g, '_');

    request({
        method: "POST",
        uri: `https://www.googleapis.com/gmail/v1/users/me/messages/send`,
        headers: {
            "Authorization": `Bearer ${auth}`,
            "Content-Type": "application/json"
        },
        body: JSON.stringify({
            "raw": encodedMail
        })
    },
    function(err, response, body) {
        if(err){
            console.log(err); // Failure
        } else {
            console.log(body); // Success!
        }
    });

}

app.use('/static', express.static('./www'));
app.use(router)

router.get('/access-granted', (req, res) => {
    sendEmail(req.query.code, 'teste email', 'teste@gmail.com', 'teste@gmail.com', 'teste');
    res.sendfile('/www/html/index.html', {root: __dirname})
})

router.get('/request-access', (req, res) => {
    res.redirect(authUrl);
});

router.get('/', (req, res) => {
    res.sendFile('/www/html/index.html', { root: __dirname });
});

const port = process.env.PORT || 8080;
app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

module.exports = app;

每次尝试发送简单的电子邮件时,都会收到错误401:凭据无效。但我在授权中传递了google发送给我的客户端代码身份验证...

1 个答案:

答案 0 :(得分:1)

使用Google API的推荐方法是使用Google API nodejs client,它还提供Google OAuth流程。然后,您可以使用google.gmail('v1').users.messages.send发送电子邮件:

const gmail = google.gmail('v1');

gmail.users.messages.send({
    auth: oauth2Client,
    userId: 'me',
    resource: {
        raw: encodedMail
    }
}, function(err, req) {
    if (err) {
        console.log(err);
    } else {
        console.log(req);
    }
});

authOAuth2,OAuth对象可以使用您的令牌填充。您可以在express session

中获取令牌
var oauth2Client = getOAuthClient();
oauth2Client.setCredentials(req.session["tokens"]);
您已存储在OAuth回调端点中的

var oauth2Client = getOAuthClient();
var session = req.session;
var code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
    // Now tokens contains an access_token and an optional refresh_token. Save them.
    if (!err) {
        oauth2Client.setCredentials(tokens);
        session["tokens"] = tokens;
        res.send(`<html><body><h1>Login successfull</h1><a href=/send-mail>send mail</a></body></html>`);
    } else {
        res.send(`<html><body><h1>Login failed</h1></body></html>`);
    }
});

这是一个受this google API oauth for node.js example启发的完整示例:

'use strict';

const express = require('express');
const google = require('googleapis');
const request = require('request');
const OAuth2 = google.auth.OAuth2;
const session = require('express-session');
const http = require('http');

let app = express();

app.use(session({
    secret: 'some-secret',
    resave: true,
    saveUninitialized: true
}));

const gmail = google.gmail('v1');

const SCOPES = [
    'https://mail.google.com/',
    'https://www.googleapis.com/auth/gmail.modify',
    'https://www.googleapis.com/auth/gmail.compose',
    'https://www.googleapis.com/auth/gmail.send'
];

const clientSecret = 'CLIENT_SECRET';
const clientId = 'CLIENT_ID';
const redirectUrl = 'http://localhost:8080/access-granted';

const mailContent = "test";
const mailFrom = "someemail@gmail.com";
const mailTo = "someemail@gmail.com";
const mailSubject = "subject";

function getOAuthClient() {
    return new OAuth2(clientId, clientSecret, redirectUrl);
}

function getAuthUrl() {
    let oauth2Client = getOAuthClient();

    let url = oauth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: SCOPES,
        //use this below to force approval (will generate refresh_token)
        //approval_prompt : 'force'
    });
    return url;
}

function sendEmail(auth, content, to, from, subject, cb) {
    let encodedMail = new Buffer(
            `Content-Type: text/plain; charset="UTF-8"\n` +
            `MIME-Version: 1.0\n` +
            `Content-Transfer-Encoding: 7bit\n` +
            `to: ${to}\n` +
            `from: ${from}\n` +
            `subject: ${subject}\n\n` +
            content
        )
        .toString(`base64`)
        .replace(/\+/g, '-')
        .replace(/\//g, '_');

    gmail.users.messages.send({
        auth: auth,
        userId: 'me',
        resource: {
            raw: encodedMail
        }
    }, cb);
}

app.use('/send-mail', (req, res) => {
    let oauth2Client = getOAuthClient();
    oauth2Client.setCredentials(req.session["tokens"]);
    sendEmail(oauth2Client, mailContent, mailTo, mailFrom, mailSubject, function(err, response) {
        if (err) {
            console.log(err);
            res.send(`<html><body><h1>Error</h1><a href=/send-mail>send mail</a></body></html>`);
        } else {
            res.send(`<html><body><h1>Send mail successfull</h1><a href=/send-mail>send mail</a></body></html>`);
        }
    });
});

app.use('/access-granted', (req, res) => {

    let oauth2Client = getOAuthClient();
    let session = req.session;
    let code = req.query.code;
    oauth2Client.getToken(code, function(err, tokens) {
        // Now tokens contains an access_token and an optional refresh_token. Save them.
        if (!err) {
            oauth2Client.setCredentials(tokens);
            session["tokens"] = tokens;
            res.send(`<html><body><h1>Login successfull</h1><a href=/send-mail>send mail</a></body></html>`);
        } else {
            res.send(`<html><body><h1>Login failed</h1></body></html>`);
        }
    });
})

app.use('/', (req, res) => {
    let url = getAuthUrl();
    res.send(`<html><body><h1>Authentication using google oAuth</h1><a href=${url}>Login</a></body></html>`)
});

let port = process.env.PORT || 8080;
let server = http.createServer(app);
server.listen(port);
server.on('listening', function() {
    console.log(`listening to ${port}`);
});