在本文中,我们将使用Gmail RESTful API构建基本的Gmail收件箱和邮件查看应用程序。 本文的目的是为您提供一个很好的起点,让您使用此API创建自己的超酷新JavaScript应用。 我们将使用jQuery和Bootstrap减轻代码基础的负担,因此我们可以专注于使某些事情快速工作,而不必担心跨浏览器的JavaScript不一致和基本样式。
与以往一样,可以在我们的GitHub存储库中找到本文的完整代码。
在您的Google帐户上启用Gmail API
首先,我们需要启用Gmail API访问权限以获取我们的API凭据。 为此,我们需要使用我们最喜欢的网络浏览器访问Google的开发者控制台 。 从那里,我们需要创建一个项目(或选择一个现有的项目)并转到API部分。 在Google Apps API部分下选择“ Gmail API”,然后单击“启用API”按钮。
现在,我们需要创建两套凭据,一套用于Web应用程序的OAuth 2.0客户端ID,另一套用于创建浏览器API密钥。 可以在Google Developer Console的凭据部分中单击“添加凭据”按钮来完成此操作。
对于浏览器API密钥,我们只需要填写“名称”字段。 但是,对于生产环境,我建议添加HTTP引荐来源网址(这将防止滥用我们的API密钥来自非授权域)。 对于OAuth 2.0客户端ID,我们必须至少输入一个授权的JavaScript来源。 对于本地开发环境,它可能是http://localhost
或类似名称。 我们不需要输入授权的重定向URI。
填写必要的字段后,我们应该能够在“凭据”部分中看到我们的凭据。 在浏览器选项卡中将此信息保持打开状态,以便以后使用。
连接到Gmail API
即使Gmail API是使用OAuth 2.0的标准REST API,我们还是建议您使用Google自己的JavaScript库来连接到任何由Google授权的API并使用它们。 这是因为Google已经将身份验证逻辑和所需的依赖关系打包到一个包含文件中-对我们来说工作量就更少了!
因此,首先要做的是-设置我们将用作应用程序基础的HTML文件。 为了这个应用程序的目的,我们将所有代码都包含在一个HTML文件中。 在生产环境中,Id建议将HTML,CSS和JavaScript分成单独的文件。
<!doctype html>
<html>
<head>
<title>Gmail API demo</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<style>
.hidden{ display: none; }
</style>
</head>
<body>
<div class="container">
<h1>Gmail API demo</h1>
<button id="authorize-button" class="btn btn-primary hidden">Authorize</button>
<table class="table table-striped table-inbox hidden">
<thead>
<tr>
<th>From</th>
<th>Subject</th>
<th>Date/Time</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript">
var clientId = 'xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com';
var apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
var scopes = 'https://www.googleapis.com/auth/gmail.readonly';
</script>
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
</body>
</html>
在底部(在</body>
标记上方)的底部,我们包含Google的JavaScript客户端库。 注意最后的查询字符串,其中包含回调函数,脚本加载后将执行该回调函数-我们将在稍后使用它来初始化应用程序。 在定义API凭据的上方,我们需要从Google Developer Console凭据部分粘贴这些凭据。 我们还定义了我们需要从用户那里获得哪些权限,这些权限称为scopes 。 就此应用而言,我们仅需要只读的Gmail访问权限。 最好从用户那里请求尽可能少的权限-这使用户放心,我们不会做恶毒的事情,例如在他们不知情的情况下代表他们发送电子邮件。
除此之外,我们还有一个按钮,该按钮将允许用户授权我们访问他们的Gmail帐户,并且我们还存根了一个表格来保存我们的收件箱数据。 而且,如前所述,我们已经包括了jQuery和Bootstrap所需的文件。
验证用户
现在,我们将为用户提供一种对我们进行身份验证以访问其Gmail帐户的机制。 如上所述,我们需要构建一个名为handleClientLoad()
的函数,该函数将在Google的JavaScript客户端库加载到页面中后自动调用。 然后,此函数将调用其他函数链,最终将导致我们获取其收件箱。
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth, 1);
}
function checkAuth() {
gapi.auth.authorize({
client_id: clientId,
scope: scopes,
immediate: true
}, handleAuthResult);
}
function handleAuthClick() {
gapi.auth.authorize({
client_id: clientId,
scope: scopes,
immediate: false
}, handleAuthResult);
return false;
}
function handleAuthResult(authResult) {
if(authResult && !authResult.error) {
loadGmailApi();
$('#authorize-button').remove();
$('.table-inbox').removeClass("hidden");
} else {
$('#authorize-button').removeClass("hidden");
$('#authorize-button').on('click', function(){
handleAuthClick();
});
}
}
function loadGmailApi() {
gapi.client.load('gmail', 'v1', displayInbox);
}
我们应该在同一SCRIPT块中,在设置API凭据的下方直接插入此代码。
总结一下此函数调用链的过程:
-
handleClientLoad()
只需设置API密钥,并在1毫秒后传递给checkAuth()
。 -
checkAuth()
检查用户先前是否已通过Google验证了我们的应用程序。 在此处将immediate
参数设置为true
意味着,如果用户未通过身份验证,则我们不会使用登录/权限模式提示用户。 然后,我们将身份验证结果传递给handleAuthResult()
。 - 然后,
handleAuthResult()
执行以下两项操作之一; 如果用户已经通过身份验证,则将使用loadGmailApi()
加载Gmail API,或者在用户界面上显示授权按钮,并向其附加click事件,这将触发handleAuthClick()
-
handleAuthClick()
简单地执行相同的认证功能checkAuth()
但将用户呈现登录/权限模态。 一旦用户认证了与之前相同的handleAuthResult()
函数,便会被触发。 - 一旦执行了这些系列的功能并且用户已通过身份验证,我们就应该始终在
loadGmailApi()
函数中找到自己。 这只是从Google的JavaScript客户端库中加载Gmail API功能,然后调用我们的displayInbox()
函数。
提示 :您可以在以下页面上检查(并撤消)哪些应用程序可以访问您的Gmail帐户: https : //security.google.com/settings/security/permissions 。 测试时可以派上用场。
提取和显示用户的收件箱
现在,我们已经对用户进行了身份验证,可以继续使用displayInbox()
函数显示其某些数据。 我们需要使用以下组件来构建该功能;
首先,我们需要从Gmail获取邮件列表。 为此,我们需要调用Users.messages:list endpoint 。 就此应用而言,我们将请求标记为INBOX
的最后十条消息:
function displayInbox() {
var request = gapi.client.gmail.users.messages.list({
'userId': 'me',
'labelIds': 'INBOX',
'maxResults': 10
});
request.execute(function(response) {
$.each(response.messages, function() {
var messageRequest = gapi.client.gmail.users.messages.get({
'userId': 'me',
'id': this.id
});
messageRequest.execute(appendMessageRow);
});
});
}
这将返回一个JSON对象,其中包含经过身份验证的用户收到的最后十条消息的ID,以及一些我们不需要的其他外围数据。 请注意,我们可以使用me
的特殊userId
来指示当前经过身份验证的用户。 与使用Google的库发出的所有API请求一样,应将请求分配给变量,然后应调用execute()
函数实际发出请求。 此函数将回调函数作为参数,并允许您指定参数以将响应保存到该参数。
不幸的是,我们实际上在这里发出了两个API请求,列表API端点仅返回消息ID,而不返回实际消息数据。 因此,在回调函数内部,我们需要遍历每条消息并请求更多特定于该消息的数据。 为此,我们需要调用User.messages:获取端点以通过其ID提取一条消息,并将响应传递给另一个函数appendMessageRow()
。
现在,我们已经获得了消息数据,我们终于可以修改DOM并向用户显示一些信息了!
function appendMessageRow(message) {
$('.table-inbox tbody').append(
'<tr>\
<td>'+getHeader(message.payload.headers, 'From')+'</td>\
<td>'+getHeader(message.payload.headers, 'Subject')+'</td>\
<td>'+getHeader(message.payload.headers, 'Date')+'</td>\
</tr>'
);
}
我们在这里利用jQuery的append()函数将包含消息数据的行追加到我们之前存根的HTML表中。 这应该使我们拥有一个可以运行的应用程序,该应用程序可以向用户显示收件箱中的最后十条消息! 但是,如果您实际上无法阅读电子邮件,则用处不大,对吧?
注意 :如果您按照本教程进行操作,则还需要getHeader()
实用程序函数来使代码在此时起作用。 您可以在文章末尾阅读有关实用程序功能的信息 。
显示电子邮件内容
由于我们已经从Users.messages: get
请求中获得了消息内容,因此无需再进行任何API请求来显示此数据。 我们只需要在现有代码中构建一种机制,以方便显示我们先前获取的现有数据。
为此,我们需要通过添加一种启动消息内容查看器的方法来开始。 因此,我们将从上方修改appendMessageRow()
代码,以添加到主题表单元格的链接。
function appendMessageRow(message) {
$('.table-inbox tbody').append(
'<tr>\
<td>'+getHeader(message.payload.headers, 'From')+'</td>\
<td>\
<a href="#message-modal-' + message.id +
'" data-toggle="modal" id="message-link-' + message.id+'">' +
getHeader(message.payload.headers, 'Subject') +
'</a>\
</td>\
<td>'+getHeader(message.payload.headers, 'Date')+'</td>\
</tr>'
);
}
单击链接时,这将利用Bootstrap的模态功能来启动预定义的模态窗口。 因此,现在我们需要对代码进行另一种修改,以便在每次将消息摘要插入表中时也在DOM中构建模式窗口容器。 因此,我们只需在先前的append()
代码片段下添加此代码片段。
$('body').append(
'<div class="modal fade" id="message-modal-' + message.id +
'" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">\
<div class="modal-dialog modal-lg">\
<div class="modal-content">\
<div class="modal-header">\
<button type="button"\
class="close"\
data-dismiss="modal"\
aria-label="Close">\
<span aria-hidden="true">×</span></button>\
<h4 class="modal-title" id="myModalLabel">' +
getHeader(message.payload.headers, 'Subject') +
'</h4>\
</div>\
<div class="modal-body">\
<iframe id="message-iframe-'+message.id+'" srcdoc="<p>Loading...</p>">\
</iframe>\
</div>\
</div>\
</div>\
</div>'
);
请注意,我们仅在此处显示消息内容面板,而这是在iframe中进行的。 之所以使用iframe,是因为如果我们仅将消息内容直接插入DOM中,就可能以多种方式破坏我们自己的应用程序。 任何将脚趾浸入HTML电子邮件构建的晦涩环境中的人都可以告诉您,破旧的HTML和内联的,超越CSS的情况很常见,因此,如果我们将代码直接插入DOM,则可能会破坏我们的应用程序。
由于某些原因,我们也不想在构建模式时将HTML直接插入iframe中。 一个是浏览器不兼容,另一个是如果我们在页面加载时在后台获取并渲染十个外部HTML页面(带有图像),这可能会影响我们应用的初始化速度。
因此,现在我们有了一个消息详细信息表和一个带有空白内容面板的模式窗口,因此是时候实现实际的消息内容显示机制了。 在相同的函数内部,我们需要将on click事件附加到主题单元链接上,以在请求消息模态后呈现iframe的内容。
$('#message-link-'+message.id).on('click', function(){
var ifrm = $('#message-iframe-'+message.id)[0].contentWindow.document;
$('body', ifrm).html(getBody(message.payload));
});
这只是访问iframe(它已经存在于DOM中)并将我们的消息HTML注入其<body>
元素中。 为了实现此功能,需要一个小的解决方法 。
实用功能
现在,您可能一直在问我们在前面的几段代码中使用的那些功能; 即getBody()
, getHeader()
和getHTMLPart()
。 这些是我们定义的实用程序函数,用于从使用Gmail API消息资源中提取一些细微差别,该Gmail API消息资源以不一致的格式(嵌套部分)返回多部分电子邮件,以及base64和UTF-8的消息正文编码。 (这些功能的完整源代码可在我们的GitHub repo上找到 )。
一点造型
要舍入我们的应用程序,请将此CSS添加到HTML页面的<head>
部分:
iframe {
width: 100%;
border: 0;
min-height: 80%;
height: 600px;
display: flex;
}
闭幕致辞
现在,我们应该有一个可以正常运行的应用程序,它可以显示最近的消息摘要列表以及完整的HTML格式的电子邮件。
显然,此应用程序还有很多改进的空间,尤其是:
- 使用JavaScript的Date对象更好的日期格式
- Mustache或Handlebars HTML模板(将HTML排除在JavaScript之外)
- 消息的正确日期排序(当前显示不正确,因为各个消息数据请求是异步的,因此先返回的是第一个进入表)
- 能够提取10条以上的消息并分页结果
- Ajax自动更新消息(带有新消息的浏览器通知)
我还想看看为该应用程序添加更多功能,显而易见的下一步可能是:
- 添加更多电子邮件功能,例如撰写,回复,转发等(将需要其他权限请求)
- 将UI与Gmail已提供的功能区分开
如果您还有其他改进或建议,请随时在评论中添加它们。
完整的源代码可通过我们的GitHub存储库获取 。
From: https://www.sitepoint.com/mastering-your-inbox-with-gmail-javascript-api/