Gmail API 发送电子邮件错误 401:Invalid 凭据
Gmail API sending email error 401:Invalid Credentials
我正在用 express 开发一个网页,当客户点击 "Send E-mail" 重定向到 google 请求允许通过客户电子邮件发送电子邮件,并在客户给予许可重定向后返回并发送电子邮件。
目前的代码:
'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 发送给我的客户端代码授权...
使用 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}`);
});
我正在用 express 开发一个网页,当客户点击 "Send E-mail" 重定向到 google 请求允许通过客户电子邮件发送电子邮件,并在客户给予许可重定向后返回并发送电子邮件。
目前的代码:
'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 发送给我的客户端代码授权...
使用 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}`);
});