代码之家  ›  专栏  ›  技术社区  ›  user3896400

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

  •  1
  • user3896400  · 技术社区  · 8 年前

    我正在用express开发一个网页,当客户端点击“发送电子邮件”时,重定向到谷歌,请求允许通过客户端电子邮件发送电子邮件,在客户端给予许可后,重定向回并发送电子邮件。

    目前为止的代码:

    '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:凭据无效。但我正在传递谷歌刚刚发送给我的客户端代码授权。。。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Bertrand Martel    8 年前

    建议使用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);
        }
    });
    

    auth OAuth2 ,可以用令牌填充的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}`);
    });