Kingname

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

在上一篇文章使用AWS亚马逊云搭建Gmail转发服务(一)中,我们介绍了如何在亚马逊AWS的免费主机EC2中使用Gmai API从而接收邮件的操作。在这篇文章中,将要讲解如何制作一个邮件转发服务。

我之前有写一篇文章,使用微信控制你的电脑其中有讲解如何使用Python的smtplib库实现发送邮件。于是Gmail邮件转发的思路就出来了:

程序定期检查Gmail邮箱,如果发现有新的邮件,就将新邮件的标题,发送人,还有邮件正文提取出来,并使用 MIMEText构造一个邮件的object 然后再用国内邮箱发送给自己的主邮箱。

这里涉及到三个邮箱:Gmail,国内邮箱一(发送),国内邮箱二(接收)。其中国内邮箱二是我的常用邮箱,我将它和微信绑定,因此一旦有新邮件,就会收到提醒。国内邮箱一是一个备胎邮箱,他的作用就是一个转发而已。

可能有人会问为什么不用Gmail直接转发?因为我觉得很有可能不久以后,Gmail发送的邮件,国内邮箱收不到。

那么我们将使用微信控制你的电脑这篇文章中涉及到的auto.py进行修改,编写一个ghelper_sender.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#-*-coding:utf-8 -*-
import smtplib
import sys
from email.mime.text import MIMEText
reload(sys)
sys.setdefaultencoding('utf-8')
username = "[email protected]"# 接收邮箱
password = "123abc"# 接收邮箱密码
mailbox = "[email protected]" #国内邮箱二
def send_mail(subject,body='Success'):
msg = MIMEText(body,'plain','utf-8')#中文需参数‘utf-8’,单字节字符不需要
msg['Subject'] = subject
msg['from'] = username
handle = smtplib.SMTP('smtp.sina.com', 25)
handle.login(username,password)
handle.sendmail(username,mailbox, msg.as_string())
handle.close()

这里需要注意,msg[‘from’] 的值必须是国内邮箱一,而不是发邮件到Gmail邮箱的那个地址,否则会报错。

现在打开上一篇文章中的ghelper_api.py,在最开头添加:

1
from ghelper_sender import send_mail

导入send_mail函数。

由于ghelper_api.py 中,上一篇文章中通过

1
2
a = ListMessagesWithLabels(gmail_service,'me')[0]['id']
b = GetMessage(gmail_service,'me',a)

获得你邮件的正文和发件人,现在再获取邮件的标题:

1
subject = b['payload']['headers'][12]['value']

这里我把发件人和邮件正文添加到一起,于是得到以下代码:

1
2
3
4
5
6
7
8
9
10
a = ListMessagesWithLabels(gmail_service,'me')[0]['id']
b = GetMessage(gmail_service,'me',a)
content = b['snippet']
sender = b['payload']['headers'][3]['value']
subject = b['payload']['headers'][12]['value']
body = sender + '\n' + content
send_mail(subject,body)
print subject
print body
print '============================'

这样就能发送一次邮件了。接收到的效果如图:


但是这显然不是我们需要的效果。我们希望这个程序能够自动运行,自动查看邮箱。于是,编写一个函数isnew()来检测是否有新的邮件发送过来,如果有就获取新邮件并发送。

设定一个全局变量last_email用于保存已读的最后一封邮件,令他的初始化为当前邮箱里面最新的一封邮件的id.接下来每过一段时间,程序就检查邮箱里面邮件的id,如果和last_email相同,就什么都不做;如果不相同,则程序就读取邮件,直到读取到某一封邮件的id和last_email相同为止。再令last_email的值为当前最新的id.代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def init():
global last_email
last_email = ListMessagesWithLabels(gmail_service,'me')[0]['id']
def isnew():
global last_email
themail = ListMessagesWithLabels(gmail_service,'me')
for each in themail:
if each['id'] != last_email:
tosend(each['id'])
else:
break
last_email = themail[0]['id']
def tosend(id):
b = GetMessage(gmail_service,'me',id)
content = b['snippet']
sender = b['payload']['headers'][3]['value']
subject = b['payload']['headers'][12]['value']
body = sender + '\n' + content
send_mail(subject,body)
print subject
print body
print '============================'

设定一个主函数,并把上面的代码放在主函数里面,并循环执行:

1
2
3
4
5
if __name__=='__main__':
init()
while 1:
time.sleep(3600) #每一小时检查一次邮箱
isnew()

完整的代码我放在了Github上面,请戳->https://github.com/kingname/MCC/tree/master/ghelper

在下一篇文章中,将介绍Python的logging库,并将每次的发送记录通过日志记录下来。同时用Flask搭建一个网站,从而方便直观的检查这个程序的运行情况。

Kingname wechat
第一时间获取最新文章更新,请订阅我的微信公众号:未闻Code