title: 使用AWS亚马逊云搭建Gmail转发服务(一)

author:青南

date: 2014-12-30 15:41:35

categories: Python

tags: [Gmail,AWS,API,Flask]

故事背景

2014年12月28号开始,Gmail被伟大的墙从协议上封禁,POP3、SMTP、IAMP全部阵亡。于是不仅网页不能打开Gmail,连邮件客服端都不能使用Gmail收发邮件了。

Gmail在国内的用户相当的广泛,难道就真的不用了吗?当然不是。虽然使用VPN可以翻出长城,但是开着VPN做其他事情又不太方便。于是,一种Gmail的转发服务变得重要起来。

这篇文章将详细介绍如何使用亚马逊云AWS的免费主机EC2,配合Gmail的API来编写一个Gmail的转发程序。程序在设定时间内访问Gmail收件箱,发现新邮件以后,就通过另一个邮箱转发到国内邮箱中。每一次转发记录到一个日志文件中,并使用Flask搭建网站来,从而直观的检查接收发送记录。

AWS的免费主机EC2的申请不是本文的重点,网上有很多教程,故略去不讲。

Flask环境的搭建不是本文重点,网上有很多教程,故略去不讲。

本篇先讲解Gmail API的使用,下一篇讲解如何制作转发程序。

授权之路

既然要是用Gmail的API,那就要开通Gmail的授权。Google的官方英文教程请戳->Run a Gmail App in Python

打开Gmail API

访问https://console.developers.google.com/project,单击“建立档案”选项,新建一个项目。我这里新建的项目叫做“gmail”,如下图:

单击新建的档案“gmail”,在左侧点击“API和验证”,选择“API”,然后再右侧中间搜索框中输入Gmail,找到后打开。如下图:

然后点击左侧“凭证”,选择“建立新的用户端ID”

这个时候注意一定要选择第三项,才能正确生成json文件。选择第三项,并填写完一些信息后,做如下选择,并点击“建立用户端ID”

接下来,下载json文件。

验证机器

在服务器上新建ghelper文件夹:

mkdir ghelper
cd ghelper

然后安装Google API Python Client库。建议使用pip安装而不是easy_install,因为pip安装的库文件可以卸载,而easy_install安装的库文件不能卸载。

sudo pip install --upgrade google-api-python-client

为了使代码中的run.tools()能够正常执行,还需要安装gflags:

sudo pip install python-gflags

将json文件上传到AWS服务器上,我放在了~/wwwproject/ghelper目录下面,并且重命名为client_secret.json,这样代码就不需要进行修改了。同时在本目录下面新建ghelper_api.py文件,文件内容为官方指南中的验证机器的代码,如下:

import httplib2

from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run # Path to the client_secret.json file downloaded from the Developer Console
CLIENT_SECRET_FILE = 'client_secret.json' # Check https://developers.google.com/gmail/api/auth/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly' # Location of the credentials storage file
STORAGE = Storage('gmail.storage') # Start the OAuth flow to retrieve credentials
flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http() # Try to retrieve credentials from storage or run the flow to generate them
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
credentials = run(flow, STORAGE, http=http) # Authorize the httplib2.Http object with our credentials
http = credentials.authorize(http) # Build the Gmail service from discovery
gmail_service = build('gmail', 'v1', http=http) # Retrieve a page of threads
threads = gmail_service.users().threads().list(userId='me').execute() # Print ID for each thread
if threads['threads']:
for thread in threads['threads']:
print 'Thread ID: %s' % (thread['id'])

运行ghelper_api.py,进入Google验证阶段。

python ghelper_api.py

在红线处按回车键就可以进入输入模式。输入gmail和密码以后,移动光标到“Sign in”回车,然后进入如下页面:

输入你的信息,验证通过以后会让你进入开启浏览器的javascript功能。可是Linux服务器哪来的浏览器?这个时候按键盘的Ctrl + Z来取消。

继续输入:

python ghelper_api.py --noauth_local_webserver

会提示离线验证,如果仍然失败的话,就继续Ctrl+Z然后再输入上面的代码,很快就会让你离线验证:

复制他给出的网址,并在自己电脑上登录后,复制他给出的代码并粘贴回服务器上。验证通过。

使用API

打开API Reference,查看Gmail API的用法。

这里用Users.messages的list和get方法来演示API的使用。

先查看list的说明:

Lists the messages in the user's mailbox.

列出邮箱里的信息。这里实际上列出来的是每一封邮件的id,于是,使用这个id,通过get就能获得邮件的内容。

通过查看list和get的使用范例:

list:

https://developers.google.com/gmail/api/v1/reference/users/messages/list

get:

https://developers.google.com/gmail/api/v1/reference/users/messages/get

构造出以下的完整代码:

#-*-coding:utf-8 -*-
import httplib2 from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run
from apiclient import errors
import base64
import email # Path to the client_secret.json file downloaded from the Developer Console
CLIENT_SECRET_FILE = 'client_secret.json' # Check https://developers.google.com/gmail/api/auth/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly' # Location of the credentials storage file
STORAGE = Storage('gmail.storage') # Start the OAuth flow to retrieve credentials
flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http() # Try to retrieve credentials from storage or run the flow to generate them
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
credentials = run(flow, STORAGE, http=http) # Authorize the httplib2.Http object with our credentials
http = credentials.authorize(http) # Build the Gmail service from discovery
gmail_service = build('gmail', 'v1', http=http) # Retrieve a page of threads
# threads = gmail_service.users().threads().list(userId='me').execute() # # Print ID for each thread
# if threads['threads']:
# for thread in threads['threads']:
# print 'Thread ID: %s' % (thread['id']) def ListMessagesWithLabels(service, user_id, label_ids=[]):
"""List all Messages of the user's mailbox with label_ids applied. Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
label_ids: Only return Messages with these labelIds applied. Returns:
List of Messages that have all required Labels applied. Note that the
returned list contains Message IDs, you must use get with the
appropriate id to get the details of a Message.
"""
try:
response = service.users().messages().list(userId=user_id,
labelIds=label_ids).execute()
messages = []
if 'messages' in response:
messages.extend(response['messages']) while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = service.users().messages().list(userId=user_id,
labelIds=label_ids,
pageToken=page_token).execute()
messages.extend(response['messages']) return messages
except errors.HttpError, error:
print 'An error occurred: %s' % error def GetMessage(service, user_id, msg_id):
"""Get a Message with given ID. Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
msg_id: The ID of the Message required. Returns:
A Message.
"""
try:
message = service.users().messages().get(userId=user_id, id=msg_id).execute() print 'Message snippet: %s' % message['snippet'] return message
except errors.HttpError, error:
print 'An error occurred: %s' % error a = ListMessagesWithLabels(gmail_service,'me')[0]['id']
b = GetMessage(gmail_service,'me',a)
print b['snippet']
print b['payload']['headers'][3]['value']

通过观察GetMessage返回的数据,可以看到,返回的是一个字典dict,邮件的内容在key为snippet的里面。发件人在['payload']['headers'][3]['value']里面,如图:



代码在服务器上运行效果如图:

至此,Gmail API在AWS服务器上的部署完成。下一篇文章将会介绍如何使用Python轮询Gmail的收件箱,并在有新邮件的时候转发到国内邮箱。

使用AWS亚马逊云搭建Gmail转发服务(一)的更多相关文章

  1. 使用AWS亚马逊云搭建Gmail转发服务(三)

    title: 使用AWS亚马逊云搭建Gmail转发服务(三) author:青南 date: 2015-01-02 15:42:22 categories: [Python] tags: [log,G ...

  2. 使用AWS亚马逊云搭建Gmail转发服务(二)

    title: 使用AWS亚马逊云搭建Gmail转发服务(二) author:青南 date: 2014-12-31 14:44:27 categories: [Python] tags: [Pytho ...

  3. [转]Amazon AWS亚马逊云服务免费一年VPS主机成功申请和使用方法

    今天部落将再次为大家介绍如何成功申请到来自亚马逊的Amazon AWS免费一年的VPS主机服务.亚马逊公司这个就不用介绍了,是美国最大的一家网络电子商务公司,亚马逊弹性计算云Amazon EC2更是鼎 ...

  4. 当 EDA 遇到 Serverless,亚马逊云科技出招了

    近二三十年来,软件开发领域毫无疑问是发展最为迅速的行业之一. 在上个世纪九十年代,世界上市值最高的公司大多是资源类或者重工业类的公司,例如埃克森美孚或者通用汽车,而现在市值最高的公司中,纯粹的软件公司 ...

  5. AWS系列之一 亚马逊云服务概述

    云计算经过这几年的发展,已经不再是是一个高大上的名词,而是已经应用到寻常百姓家的技术.每天如果你和互联网打交道,那么或多或少都会和云扯上关系.gmail.github.各种网盘.GAE.heroku等 ...

  6. 亚马逊云服务器AWS安装CentOS

    亚马逊云服务器默认创建的实例,在停止之后再启动的情况下,IP会发生改变.所以我们最好先创建一个弹性IP,即EIP,不过我也不清楚这个费用. 1.按如图操作创建一个弹性IP,弹性IP创建之后可以随便绑定 ...

  7. 【AWS】亚马逊云常用服务解释

    新公司使用的是亚马逊服务,刚开始的时候,对很多名词不太明白,总结了一下如下 1,EC2 这个是亚马逊的一种服务器服务,可以理解为跟vmware差不多,EC2为虚拟机提供载体,EC2上跑虚拟机服务器. ...

  8. 使用亚马逊云服务器EC2做深度学习(三)配置TensorFlow

    这是<使用亚马逊云服务器EC2做深度学习>系列的第三篇文章. (一)申请竞价实例  (二)配置Jupyter Notebook服务器  (三)配置TensorFlow  (四)配置好的系统 ...

  9. 亚马逊云架设WordPress博客

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 这篇文章介绍如何在亚马逊云架设WordPress博客.最强的云,加上最流行的建站工 ...

随机推荐

  1. 页面嵌入dom与被嵌入iframe的攻防

    1.情景一:自己的页面被引入(嵌入)至别人的页面iframe中 if(window.self != window.top){ //url是自己页面的url window.top.location.hr ...

  2. 关于 Chrome 浏览器中 onresize 事件的 Bug

    我在写插件时用到了 onresize 事件,在反复地测试后发现该事件在 Chrome 及 Opera(内核基本与 Chrome 相同,以下统称 Chrome)浏览器打开时就会执行,这种情况也许不能算作 ...

  3. 如何用百度MIP快速搭建体验友好的移动页面

    在读这篇文章之前,请确定你已经了解MIP定义及加速原理.如果不确定的话,可以到MIP官网了解. 改造前期准备和注意事项: 你可以选择直接将原先的移动站点直接改成MIP站,也可以单独再做一套MIP站点与 ...

  4. sonn_game网站开发01:写在最前面

    之前做的个人博客项目,日向博客现在已经进入后期完善阶段了.是时候开始打造一个新坑了. 然而改造个什么坑呢?构思了好几天,想了好多方案,都觉得没啥动手欲望.因为,我想做的是那种,自己能用得上,而且有一定 ...

  5. [译] C# 5.0 中的 Async 和 Await (整理中...)

    C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...

  6. OpenCV模板匹配算法详解

    1 理论介绍 模板匹配是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标.OpenCV ...

  7. VICA 架构设计(1)

    本文记录最近完成的一个通用实时通信客户端的架构.   背景 我们公司是做税务相关的软件,有针对大客户 MIS 系统,也有针对中小客户的 SaaS 平台.这些系统虽然都是 B/S 的,但是也需要使用 A ...

  8. 海康网络摄像机YV12转换为BGR,由opencv Mat显示 (转)

    我使用的是海康DS-2CD852MF-E, 200万,网络摄像机,已经比较老了,不过SDK在海康官网下载的,开发流程都差不多. 海康摄像机回调解码后的视频数据格式为YV12,顺便说一下YV12的数据格 ...

  9. css3制作旋转动画

    现在的css3真是强大,之前很多动画都是用jq来实现,但是css3制作的动画要比jq实现起来简单很多,今天呢,我自己也写了一个css旋转动画和大家分享.效果如下面的图片 思路:1.制作之前呢,我们先来 ...

  10. Android—ListView条目背景为图片时,条目间距问题解决

    ListView是android开发中使用最普遍的控件了,可有的listView条目的内容颇为丰富,甚至为了美观,背景用指定图片,如下图: