使用AWS亚马逊云搭建Gmail转发服务(一)
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转发服务(一)的更多相关文章
- 使用AWS亚马逊云搭建Gmail转发服务(三)
title: 使用AWS亚马逊云搭建Gmail转发服务(三) author:青南 date: 2015-01-02 15:42:22 categories: [Python] tags: [log,G ...
- 使用AWS亚马逊云搭建Gmail转发服务(二)
title: 使用AWS亚马逊云搭建Gmail转发服务(二) author:青南 date: 2014-12-31 14:44:27 categories: [Python] tags: [Pytho ...
- [转]Amazon AWS亚马逊云服务免费一年VPS主机成功申请和使用方法
今天部落将再次为大家介绍如何成功申请到来自亚马逊的Amazon AWS免费一年的VPS主机服务.亚马逊公司这个就不用介绍了,是美国最大的一家网络电子商务公司,亚马逊弹性计算云Amazon EC2更是鼎 ...
- 当 EDA 遇到 Serverless,亚马逊云科技出招了
近二三十年来,软件开发领域毫无疑问是发展最为迅速的行业之一. 在上个世纪九十年代,世界上市值最高的公司大多是资源类或者重工业类的公司,例如埃克森美孚或者通用汽车,而现在市值最高的公司中,纯粹的软件公司 ...
- AWS系列之一 亚马逊云服务概述
云计算经过这几年的发展,已经不再是是一个高大上的名词,而是已经应用到寻常百姓家的技术.每天如果你和互联网打交道,那么或多或少都会和云扯上关系.gmail.github.各种网盘.GAE.heroku等 ...
- 亚马逊云服务器AWS安装CentOS
亚马逊云服务器默认创建的实例,在停止之后再启动的情况下,IP会发生改变.所以我们最好先创建一个弹性IP,即EIP,不过我也不清楚这个费用. 1.按如图操作创建一个弹性IP,弹性IP创建之后可以随便绑定 ...
- 【AWS】亚马逊云常用服务解释
新公司使用的是亚马逊服务,刚开始的时候,对很多名词不太明白,总结了一下如下 1,EC2 这个是亚马逊的一种服务器服务,可以理解为跟vmware差不多,EC2为虚拟机提供载体,EC2上跑虚拟机服务器. ...
- 使用亚马逊云服务器EC2做深度学习(三)配置TensorFlow
这是<使用亚马逊云服务器EC2做深度学习>系列的第三篇文章. (一)申请竞价实例 (二)配置Jupyter Notebook服务器 (三)配置TensorFlow (四)配置好的系统 ...
- 亚马逊云架设WordPress博客
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 这篇文章介绍如何在亚马逊云架设WordPress博客.最强的云,加上最流行的建站工 ...
随机推荐
- 页面嵌入dom与被嵌入iframe的攻防
1.情景一:自己的页面被引入(嵌入)至别人的页面iframe中 if(window.self != window.top){ //url是自己页面的url window.top.location.hr ...
- 关于 Chrome 浏览器中 onresize 事件的 Bug
我在写插件时用到了 onresize 事件,在反复地测试后发现该事件在 Chrome 及 Opera(内核基本与 Chrome 相同,以下统称 Chrome)浏览器打开时就会执行,这种情况也许不能算作 ...
- 如何用百度MIP快速搭建体验友好的移动页面
在读这篇文章之前,请确定你已经了解MIP定义及加速原理.如果不确定的话,可以到MIP官网了解. 改造前期准备和注意事项: 你可以选择直接将原先的移动站点直接改成MIP站,也可以单独再做一套MIP站点与 ...
- sonn_game网站开发01:写在最前面
之前做的个人博客项目,日向博客现在已经进入后期完善阶段了.是时候开始打造一个新坑了. 然而改造个什么坑呢?构思了好几天,想了好多方案,都觉得没啥动手欲望.因为,我想做的是那种,自己能用得上,而且有一定 ...
- [译] C# 5.0 中的 Async 和 Await (整理中...)
C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...
- OpenCV模板匹配算法详解
1 理论介绍 模板匹配是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标.OpenCV ...
- VICA 架构设计(1)
本文记录最近完成的一个通用实时通信客户端的架构. 背景 我们公司是做税务相关的软件,有针对大客户 MIS 系统,也有针对中小客户的 SaaS 平台.这些系统虽然都是 B/S 的,但是也需要使用 A ...
- 海康网络摄像机YV12转换为BGR,由opencv Mat显示 (转)
我使用的是海康DS-2CD852MF-E, 200万,网络摄像机,已经比较老了,不过SDK在海康官网下载的,开发流程都差不多. 海康摄像机回调解码后的视频数据格式为YV12,顺便说一下YV12的数据格 ...
- css3制作旋转动画
现在的css3真是强大,之前很多动画都是用jq来实现,但是css3制作的动画要比jq实现起来简单很多,今天呢,我自己也写了一个css旋转动画和大家分享.效果如下面的图片 思路:1.制作之前呢,我们先来 ...
- Android—ListView条目背景为图片时,条目间距问题解决
ListView是android开发中使用最普遍的控件了,可有的listView条目的内容颇为丰富,甚至为了美观,背景用指定图片,如下图: