现在网上有挺多使用python控制电脑的文章,但是大多数文章里的代码都不能直接拿来使用,只是写了函数,并没有讲解具体的调用方法,因此,今天我来改进一下,给大家提供拿来即可使用的代码
我们先来看看使用Python控制电脑的原理,简单来说就是以下三点:
- 通过POP服务获取邮件
- 解析获取到的邮件
- 将解析结果通过SMTP服务返回
- 定时获取邮件指令
通过POP服务获取邮件
在开始之前,我们先来配置一下POP3/SMTP服务,确保这两个服务是开启的:
开启方法如下:
其实就是获取授权码而已,不同类型的邮箱在设置里面都能找到的
下面我们在Python里调用POP服务获取对应邮箱:
def __init__(self):
# 接收邮件
email = '2733821739@qq.com' #登录的邮箱账号
password = '' # 注意这里不是邮箱密码 是要登录的邮箱的授权码
pop3_server = 'pop.qq.com'
# 连接到POP3服务器:
server = poplib.POP3_SSL(pop3_server, 995)
server.set_debuglevel(0)
server.user(email)
server.pass_(password)
resp, mails, octets = server.list()
index = len(mails)
resp, lines, octets = server.retr(index) # 这里index代表读取最后一封邮件 也就是第一封
message_content = b'\r\n'.join(lines).decode('utf-8')
message = Parser().parsestr(message_content)
# print(message)
# print("server:",server)
你可以把这一步理解为初始化的过程,print(message)可以输出刚刚发来的邮件:
但是如果直接print的话会有点问题,编码不对,因此我们需要处理一下
解析获取到的邮件
为了便于控制电脑,于是我们将指令放在邮件主题里即可,这样便不用查看正文:
这是刚刚的邮件,我们先来定义一个解码的函数:
def decode_str(self, s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
然后我们把寄件人,收件人以及邮件主题输出一下就是刚刚上面那张图了
def print_info(self, indent=0):
for header in ['From', 'To', 'Subject']:
value = self.message.get(header, '')
if value:
if header == 'Subject':
value = self.decode_str(value)
else:
hdr, addr = parseaddr(value)
name = self.decode_str(hdr)
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
当然,这里我们有个问题,如果我们一直开启这个服务的话,有可能会被一些不怀好意的人钻空子,攻击我们的电脑,因此这里我们添加一些条件判断,让程序执行制定邮箱发来的邮件:
if header == 'From':
value = self.decode_str(value)
if value != self.mail_user:
print('%s%s: %s' % (' ' * indent, header, value))
print('忽略该邮件')
return False
当然,如果发现了对应邮箱发来的邮件,那么我们便直接提取出邮件主题,并让程序往下一步去运行:
if header == 'Subject':
value = self.decode_str(value)
return value
下面运行邮件主题里的指令:
def manage_cmd(self, cmd):
print('The command is:%s' % cmd)
if 'screenshot' in cmd:
self.kind = 1
img = pyautogui.screenshot()
img.save('./screenshot.png')
if 'dos cmd' in cmd:
self.kind = 2
dos_result = ''
index = cmd.find(':')
cmd = cmd[index+1:]
if os.system(cmd):
self.result = 'command err.'
else:
info = os.popen(cmd)
for line in info:
dos_result = dos_result + line
if dos_result != '':
self.result = dos_result
如果指令是截图,那么保存图片;如果是dos命令,那就把结果存入self.result
因此,我们还需要在__init__方法里补充self.result
下面我们只要把结果通过邮件返回即可
将解析结果通过SMTP服务返回
这里我们也在__init__方法里初始化:
# 第三方 SMTP 服务 发送邮件
self.mail_host = "smtp.qq.com"
self.mail_user = "" #发送信息的邮箱
self.mail_pass = "" # 邮箱的授权码
self.sender = '' #显示给对方看的发送方地址
self.receivers = [''] #收件地址
如果是同一个邮箱,那么授权码是一样的,下面我们来看看具体要怎么写代码:
def send_result(self):
# 创建一个带附件的实例
message = MIMEMultipart()
message['From'] = self.sender
for receiver in self.receivers:
message['To'] = receiver
subject = 'reply from python'
message['Subject'] = Header(subject, 'utf-8')
if self.kind == 1: # 第一方式 反馈屏幕截图
print('Sending screenshot.')
# 邮件正文内容
message.attach(MIMEText('Hacker Server replay', 'plain', 'utf-8'))
if os.path.exists("./screenshot.png"):
# 构造附件1,传送当前目录下的 test.txt 文件
att1 = MIMEText(open('./screenshot.png', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att1["Content-Disposition"] = 'attachment; filename="screenshot.png"'
message.attach(att1)
try:
smtpObj = smtplib.SMTP_SSL(self.mail_host, 465) # 启用SSL发信, 端口一般是465
smtpObj.login(self.mail_user, self.mail_pass) # 登录验证
smtpObj.sendmail(self.sender, self.receivers, message.as_string()) # 发送
print("mail has been send successfully.")
except smtplib.SMTPException as e:
print(e)
if self.kind == 2: #第二种方式 返回dos命令结果
smtpObj = smtplib.SMTP_SSL(self.mail_host, 465)
smtpObj.login(self.mail_user, self.mail_pass)
smtpObj.sendmail(self.sender, self.receivers, message.as_string())
print("mail has been send successfully.")
定时获取邮件指令
这一步是其他文章没有展示的,不过也不是很难,主要是一些调用过程:
def main():
while True:
mailremotecontrol = MailRemoteControl()
cmd = mailremotecontrol.print_info()
if (cmd != False):
mailremotecontrol.manage_cmd(cmd)
mailremotecontrol.send_result()
time.sleep(100000)
if __name__ == '__main__':
main()
因为整个程序比较长,如果上面有哪里没讲清楚的话,可以在评论区留言
下面是程序全部代码:
import smtplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
import poplib
import pyautogui
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
import os
import time
class MailRemoteControl(object):
def __init__(self):
# 接收邮件
email = '2733821739@qq.com' #登录的邮箱账号
password = 'oycokbuorrvhddji' # 注意这里不是邮箱密码 是要登录的邮箱的授权码
pop3_server = 'pop.qq.com'
# 连接到POP3服务器:
server = poplib.POP3_SSL(pop3_server, 995)
server.set_debuglevel(0)
server.user(email)
server.pass_(password)
resp, mails, octets = server.list()
index = len(mails)
resp, lines, octets = server.retr(index) # 这里index代表读取最后一封邮件 也就是第一封
message_content = b'\r\n'.join(lines).decode('utf-8')
message = Parser().parsestr(message_content)
print(message)
# print("server:",server)
self.message = message
self.kind = 0
self.result = 'Nothing happen.'
# 第三方 SMTP 服务 发送邮件
self.mail_host = "smtp.qq.com"
self.mail_user = "2733821739@qq.com" #发送信息的邮箱
self.mail_pass = "oycokbuorrvhddji" # 邮箱的授权码
self.sender = '2733821739@qq.com' #发送方地址
self.receivers = ['2733821739@qq.com'] #收件地址
def guess_charset(self, msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get('Content-Type', '').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
print(charset)
return charset
def decode_str(self, s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
def print_info(self, indent=0):
for header in ['From', 'To', 'Subject']:
value = self.message.get(header, '')
if value:
if header == 'From':
hdr, addr = parseaddr(value)
name = self.decode_str(hdr)
value = u'%s <%s>' % (name, addr)
# print(value)
if value != "Mr.郑先生_🦁 <2733821739@qq.com>":
print('%s%s: %s' % (' ' * indent, header, value))
print('忽略该邮件')
return False
if header == 'Subject':
value = self.decode_str(value)
return value
else:
hdr, addr = parseaddr(value)
name = self.decode_str(hdr)
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
if self.message.is_multipart():
parts = self.message.get_payload()
for n, part in enumerate(parts):
print('%spart %s' % (' ' * indent, n))
print('%s--------------------' % (' ' * indent))
# return self.print_info(indent + 1)
else:
content_type = self.message.get_content_type()
if content_type=='text/plain' or content_type=='text/html':
content = self.message.get_payload(decode=True)
charset = self.guess_charset(self.message)
if charset:
content = content.decode(charset)
print('%sText: %s' % (' ' * indent, content))
return content
else:
print('%sAttachment: %s' % (' ' * indent, content_type))
def send_result(self):
# 创建一个带附件的实例
message = MIMEMultipart()
message['From'] = self.sender
for receiver in self.receivers:
message['To'] = receiver
subject = 'reply from python'
message['Subject'] = Header(subject, 'utf-8')
if self.kind == 1: # 第一方式 反馈屏幕截图
print('Sending screenshot.')
# 邮件正文内容
message.attach(MIMEText('Hacker Server replay', 'plain', 'utf-8'))
if os.path.exists("./screenshot.png"):
# 构造附件1,传送当前目录下的 test.txt 文件
att1 = MIMEText(open('./screenshot.png', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att1["Content-Disposition"] = 'attachment; filename="screenshot.png"'
message.attach(att1)
try:
smtpObj = smtplib.SMTP_SSL(self.mail_host, 465) # 启用SSL发信, 端口一般是465
smtpObj.login(self.mail_user, self.mail_pass) # 登录验证
smtpObj.sendmail(self.sender, self.receivers, message.as_string()) # 发送
print("mail has been send successfully.")
except smtplib.SMTPException as e:
print(e)
if self.kind == 2: #第二种方式 返回dos命令结果
# 邮件正文内容
message.attach(MIMEText(self.result, 'plain', 'utf-8'))
smtpObj = smtplib.SMTP_SSL(self.mail_host, 465)
smtpObj.login(self.mail_user, self.mail_pass)
smtpObj.sendmail(self.sender, self.receivers, message.as_string())
print("mail has been send successfully.")
def manage_cmd(self, cmd):
print('The command is:%s' % cmd)
if 'screenshot' in cmd:
self.kind = 1
img = pyautogui.screenshot()
img.save('./screenshot.png')
if 'dos cmd' in cmd:
self.kind = 2
dos_result = ''
index = cmd.find(':')
cmd = cmd[index+1:]
if os.system(cmd):
self.result = 'command err.'
else:
info = os.popen(cmd)
for line in info:
dos_result = dos_result + line
if dos_result != '':
self.result = dos_result
def main():
while True:
mailremotecontrol = MailRemoteControl()
cmd = mailremotecontrol.print_info()
if (cmd != False):
mailremotecontrol.manage_cmd(cmd)
mailremotecontrol.send_result()
time.sleep(100000)
if __name__ == '__main__':
main()
把__init__方法里的邮箱信息改成自己的就可以运行了,下面是效果展示:
发送指令
返回的邮件
截屏功能测试成功!下面试一下dos命令:
一个ping命令:
返回的邮件: