基于邮件系统的远程实时监控系统的实现 Python版

人生苦短,我用Python~ 界内的Python宣传标语,对Python而言,这是种标榜,实际上,Python确实是当下最好用的开发语言之一。

在相继学习了C++/C#/Java之后,接触Python,最一开始突然一片茫然,似乎是进入了新世界,所有C家族的语法,在这里都或多或少地发生了改变,方法没有大括号,喜闻乐见的格式。定义变量不需要声明,时间长了,竟爱上了这个简介明了,高效快捷的语言,当然,也是当下开发语言界内的宠儿,不可否认,Python是当下最流行的开发语言了。

【前言】

本文拟使用Python开发语言实现在任何能链接上互联网的地方,远程启动在其他地方部署的监控系统,并且实时地进行图像连拍,将实时图像以邮件形式反馈到手机邮箱,达到远程实时监控的目的。

【实现功能】

这篇文章将要介绍的主要内容如下:

1、远程发送监控命令

2、监控系统做出相应,进行图像连拍(或者是录制一段视频)

3、监控系统将处理结果以邮件形式发送到移动端

【实现思路】

远程向某邮箱服务器发送一封邮件,监控系统循环检测此邮箱最新接受的邮件,通过获取并分析邮件的信息确定是否需要执行监控功能操作。如果需要,做出响应,拍照并且将拍照结果反馈回邮件发送方。

【所需技术】

1、Python语言的熟练掌握,Python版本2.7

2、利用Python语言,实现SMTP协议以及POP3协议。已达到发送邮件和接收邮件的功能。

3、正则表达式的简单使用

4、OpenCV 图像处理,图像识别,跨平台开发库的使用

5、邮箱服务器SMTP,POP3协议的开通

【实现过程】

1、实现Python发送接收邮件代码,最后封装成Email_Helper_DG类,便于后续调用,当然本文的Python_Helper_DG还没有达到更高层次的封装,毕竟要发送图片的,适当做了一些对本系统的适应。

邮件发送接受的Email_Helper_DG代码如下:

  1 # -*- coding: UTF-8 -*-
  2 import os
  3 import poplib
  4 import smtplib
  5 from email.mime.application import MIMEApplication
  6 from email.mime.audio import MIMEAudio
  7 from email.mime.image import MIMEImage
  8 from email.mime.multipart import MIMEMultipart
  9 from email.mime.text import MIMEText
 10 from email.utils import formataddr
 11 
 12 
 13 class Mail_Helper_DG:
 14     my_smtp_server = 'smtp.sina.com'  # smtp 邮件服务地址
 15     my_pop3_server = 'pop.sina.com'  # pop3 邮件服务地址
 16     mail_type = 'html'  # 发送的邮件的格式,HTML或者Plain
 17     my_account = '******@example.com'  # 发件人邮箱账号
 18     my_pwd = '******'  # 发件人邮箱密码
 19     toAddressArray = ['xxxxx@example.com', ]  # 收件人的邮箱,可发送给多人
 20 
 21     def __init__(self):
 22         pass
 23 
 24     # 发送邮件
 25     def SendMail(self, toAddressArray, senderName, subject, content):
 26         try:
 27             server = smtplib.SMTP(self.my_smtp_server, 25)  # 发件人邮箱中的SMTP服务器,端口是25
 28 
 29             try:
 30                 msg = MIMEText(content, self.mail_type, 'utf-8')
 31                 msg['From'] = formataddr([senderName, self.my_account])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
 32                 # msg['To'] = formataddr(["FK", my_account])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
 33                 msg['Subject'] = subject  # 邮件的主题,也可以说是标题
 34 
 35                 server.login(self.my_account, self.my_pwd)  # 括号中对应的是发件人邮箱账号、邮箱密码
 36                 server.sendmail(self.my_account, toAddressArray, msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
 37             except Exception:
 38                 print(Exception)
 39                 return False
 40             finally:
 41                 server.quit()  # 关闭连接
 42             return True
 43         except Exception:
 44             print(Exception)
 45             return False
 46 
 47     # 发送邮件带附件
 48     def SendMailAttachment(self, toAddressArray, senderName, subject, content, attachment_path):
 49         try:
 50             server = smtplib.SMTP(self.my_smtp_server, 25)  # 发件人邮箱中的SMTP服务器,端口是25
 51 
 52             try:
 53                 server.login(self.my_account, self.my_pwd)  # 括号中对应的是发件人邮箱账号、邮箱密码
 54 
 55                 msg = MIMEMultipart()  # create MIMEMultipart
 56                 msg['From'] = formataddr([senderName, self.my_account])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
 57                 # msg['To'] = formataddr(["FK", my_account])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
 58                 msg['Subject'] = subject  # 邮件的主题,也可以说是标题
 59                 content2 = MIMEText(content,
 60                                     _charset='utf-8')  # add email content  ,coding is gbk, becasue chinese exist
 61                 msg.attach(content2)
 62                 for attachment_name in os.listdir(attachment_path):
 63                     attachment_file = os.path.join(attachment_path, attachment_name)
 64 
 65                     with open(attachment_file, 'rb') as attachment:
 66                         if 'application' == 'text':
 67                             attachment = MIMEText(attachment.read(), _subtype='octet-stream', _charset='GB2312')
 68                         elif 'application' == 'image':
 69                             attachment = MIMEImage(attachment.read(), _subtype='octet-stream')
 70                         elif 'application' == 'audio':
 71                             attachment = MIMEAudio(attachment.read(), _subtype='octet-stream')
 72                         else:
 73                             attachment = MIMEApplication(attachment.read(), _subtype='octet-stream')
 74 
 75                     attachment.add_header('Content-Disposition', 'attachment', filename=('gbk', '', attachment_name))
 76                     # make sure "attachment_name is chinese" right
 77                     msg.attach(attachment)
 78 
 79                 server.sendmail(self.my_account, toAddressArray, msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
 80             except Exception:
 81                 print(Exception)
 82                 return False
 83             finally:
 84                 server.quit()  # 关闭连接
 85             return True
 86         except Exception:
 87             print(Exception)
 88             return
 89 
 90     # 接收邮件
 91     def ReceiveMail(self):
 92         # 创建一个pop3对象,这个时候实际上已经连接上服务器了
 93         pp = poplib.POP3(self.my_pop3_server)
 94         # 设置调试模式,可以看到与服务器的交互信息
 95         pp.set_debuglevel(1)
 96         # 向服务器发送用户名
 97         pp.user(self.my_account)
 98         # 向服务器发送密码
 99         pp.pass_(self.my_pwd)
100         # 返回邮箱的状态,返回2元祖(消息的数量,消息的总字节)
101         # msgCount, msgSize = pp.stat()
102 
103         ret = pp.list()
104 
105         mailBody = pp.retr(len(ret[1]))
106         # 释放pp
107         pp.quit()
108 
109         return mailBody

2、主要业务逻辑代码,其中包含对POP3邮箱的实时监测,且对捕获到的命令进行分析判断,最后做出响应:

 1 # -*- coding: UTF-8 -*-
 2 import re
 3 import time
 4 import cv2
 5 
 6 from Email import Mail_Helper_DG
 7 
 8 toAddressArray = ['wd8622088@foxmail.com']  # 收件人的邮箱,可发送给多人
 9 
10 content = """
11 当前摄像头捕获的结果:
12 """
13 
14 
15 # 获取当前时间
16 def getCurrentTime():
17     return str(time.strftime('’%Y-%m-%d %X’', time.localtime(time.time())))
18 
19 
20 # 程序启动标识
21 print('QiXiao`s SHS Starting ...')
22 # 初始化邮件发送类
23 mail = Mail_Helper_DG()
24 
25 # 声明一个变量,来作为一个标记判断是否已经检测过当前这封邮件了
26 last_receiveMailDate = ''
27 # 输出显示当前扫描邮箱服务器的次数
28 scan_index = 0
29 # 设置一个循环检测邮箱的方法
30 while True:
31     time.sleep(10)  # 设置检测邮箱服务器的时间间隔
32     print(getCurrentTime() + ' : scan item >>> ' + str(scan_index))
33     scan_index += 1  # 扫描次数累加
34     try:
35         # 通过Pop3 获取到邮件的第一条
36         mailBody = mail.ReceiveMail()
37 
38         # 解析第一条邮件,并得到发件人,主题,日期
39         sender = re.search("X-Sender: (.*?)'.", str(mailBody[1]).decode(('utf-8')), re.S).group(1)
40         subject = re.search("Subject: (.*?)'.", str(mailBody[1]).decode(('utf-8')), re.S).group(1)
41         date = re.search("Date: (.*?)'.", str(mailBody[1]).decode(('utf-8')), re.S).group(1)
42 
43         # 判断解析到的参数值
44         if date != last_receiveMailDate:
45             # 对发送方进行邮箱判断,否则任何人都可以发送命令,你懂得
46             if sender == 'wd8622088@foxmail.com':
47                 # 对命令进行分析
48                 if subject.__contains__('qx_cmd:'):
49                     cmd = subject.split(':')[1]
50                     # 按cmd的命令来匹配要执行的操作:
51                     # catch-camera 捕获摄像头的操作
52                     if cmd == 'catch-camera':
53                         # 载入图像,连续捕获数张图片,间隔三秒
54                         video = cv2.VideoCapture(0)
55                         time.sleep(3)
56                         ret, img = video.read()
57                         cv2.imwrite('files\\shoot_001.jpg', img)
58 
59                         time.sleep(3)
60                         ret, img = video.read()
61                         cv2.imwrite('files\\shoot_002.jpg', img)
62 
63                         time.sleep(3)
64                         ret, img = video.read()
65                         cv2.imwrite('files\\shoot_003.jpg', img)
66 
67                         video.release()  # 关闭摄像头
68                         result = mail.SendMailAttachment(toAddressArray, "QiXiao",
69                                                          "QiXiao`s SHS (QiXiao`s Smart Home System v1.0)", content,
70                                                          "files")
71                         if result is True:
72                             print(getCurrentTime() + ' : send mail success !')
73                         else:
74                             print(getCurrentTime() + ' : send fail #')
75 
76                     # 让当前这条信息的日期赋值给标记变量,以便下次略过当前这条信息
77                     last_receiveMailDate = date
78     except Exception:
79         print(getCurrentTime() + 'Error:' + Exception)

至于代码逻辑的分析,代码内部已有适当的注释进行讲解,这里不再赘述,如有任何疑问,请留言,本人进行一一回复。

【系统测试】

首先我们启动我们的服务器,让代码跑起来。

 

每隔一段时间,服务器就会自动请求一次POP3服务器,判断是否有新的命令输入。

然后我们在任何地点进行邮件命令的发送:这里以Ios自带的Mail来进行邮件的发送(邮件客户端无所谓,微信里的也可以)

我们首先要填写好要发送的邮箱地址,以及主题(这里是约定好的执行命令)

填写好后,点击发送。

可以看到在0:00发送了一条邮件,这就是我们刚才发送的邮件。然后打开收件箱,准备进行邮件的查收。

我们可以看到,两分钟后,服务端以邮件形式返回监控的结果。打开邮箱进行查看。

我们可以看到,摄像头正对的部位被成功捕获,并且反馈到我们发送邮件的邮箱中。

通过这样的方式,我们可以在全球任意位置,向邮箱发送邮件,只要存在网络的地方,都可以实时对任意位置部署的摄像头进行监控,实时返回监控结果。

我们打开我们的接收命令的邮箱查看一下我们接受到的邮件:

没错,是我们刚才发送的邮件。

我们程序文件目录下保存的截取图片:

至此,我们的远程监控系统已经测试完毕,可见,完美达到了预期的效果!

【系统展望】

系统虽然功能已经实现,然还有很多不尽人意之处,未来将在第二版进行改进的有:

1、系统每隔一定时间间隔自动进行拍照,然后图像分析是否有区别(有物体入侵),如果有立即发送邮件推送报警信息。

2、对图片进行人脸识别,用方框圈出人连范围,以便增加提醒。

3、系统将搭建于Raspberry Pi Linux微机系统上,并且配备摄像头全天候进行跟踪拍摄。

4、未来可能搭建web服务,在网站或者App上进行此功能的使用

posted @ 2017-07-03 00:22  7tiny  阅读(1695)  评论(2编辑  收藏  举报