Python快速入门指南之使用POP/SMTP控制电脑(改进版)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python快速入门指南之使用POP/SMTP控制电脑(改进版)相关的知识,希望对你有一定的参考价值。


现在网上有挺多使用python控制电脑的文章,但是大多数文章里的代码都不能直接拿来使用,只是写了函数,并没有讲解具体的调用方法,因此,今天我来改进一下,给大家提供拿来即可使用的代码

我们先来看看使用Python控制电脑的原理,简单来说就是以下三点:

  1. ​​通过POP服务获取邮件​​
  2. ​​解析获取到的邮件​​
  3. ​​将解析结果通过SMTP服务返回​​
  4. ​​定时获取邮件指令​​

Python快速入门指南之使用POP/SMTP控制电脑(改进版)_python

通过POP服务获取邮件

在开始之前,我们先来配置一下POP3/SMTP服务,确保这两个服务是开启的:

Python快速入门指南之使用POP/SMTP控制电脑(改进版)_python_02


开启方法如下:

Python快速入门指南之使用POP/SMTP控制电脑(改进版)_python_03


其实就是获取授权码而已,不同类型的邮箱在设置里面都能找到的

下面我们在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)可以输出刚刚发来的邮件:

Python快速入门指南之使用POP/SMTP控制电脑(改进版)_Server_04


但是如果直接print的话会有点问题,编码不对,因此我们需要处理一下

解析获取到的邮件

为了便于控制电脑,于是我们将指令放在邮件主题里即可,这样便不用查看正文:

Python快速入门指南之使用POP/SMTP控制电脑(改进版)_python_05


这是刚刚的邮件,我们先来定义一个解码的函数:

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.郑先生_

Python3 基础快速入门(列表 循环控制语句)

划重点01List列表 主要内容
● List 列表的常规用法

将Python的不同类型的数据使用[],每个数据之间使用 , 隔开。在[]中,我们通常使用同一种数据类型,但是也可以是不同的数据类型。
操作
基本的List
squares = [1, 4, 9, 16, 25]
squares
[1, 4, 9, 16, 25]

像操作String那样,可以通过索引值访问列表中的数据
squares[0] # indexing returns the item
1
squares[-1]
25
squares[-3:] # slicing returns a new list
[9, 16, 25]

使用[:] 返回列表中的所有数据
squares[:]
[1, 4, 9, 16, 25]
List 支持连接运算
squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
与字符串不同,列表List 可以更改其中的值
cubes = [1, 8, 27, 65, 125]
4 ** 3 # 4的3次方是64,不是65
64
cubes[3] = 64 # 替换内容
cubes
[1, 8, 27, 64, 125]
使用append() 方法可以在List末尾添加数据
cubes.append(216) # 追加内容到末尾
cubes.append(7 ** 3) # 再次添加内容
cubes
[1, 8, 27, 64, 125, 216, 343]

也可以使用切片对List数据进行内容更改
letters = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’]
letters
[‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’]>>> # 替换从索引2到5处的内容>>> letters[2:5] = [‘C’, ‘D’, ‘E’]>>> letters[‘a’, ‘b’, ‘C’, ‘D’, ‘E’, ‘f’, ‘g’]>>> # 删除内容>>> letters[2:5] = []>>> letters[‘a’, ‘b’, ‘f’, ‘g’]>>> # 清空List内所有的内容 letters[:] = []>>> letters[]
内置 len() 计算List的数据长度
letters = [‘a’, ‘b’, ‘c’, ‘d’]
len(letters)
4
同样,List内也可以内嵌List, 形成多维List
a = [‘a’, ‘b’, ‘c’]
n = [1, 2, 3]
x = [a, n]
x
[[‘a’, ‘b’, ‘c’], [1, 2, 3]]
x[0]
[‘a’, ‘b’, ‘c’]
x[0][1]
‘b’
划重点02逻辑控制语句 主要内容
● if 控制
● for 循环
● range()函数
● break,continu 语句
● pass
if控制
当进行多个条件判断时,可以使用 if … elif … elif … else
elif 其它判断条件。
else 所有条件都不执行。

x = int(input("Please enter an integer: "))
Please enter an integer: 42
if x < 0:
… x = 0
… print(‘Negative changed to zero’)
… elif x == 0:
… print(‘Zero’)
… elif x == 1:
… print(‘Single’)
… else:
… print(‘More’)

More
for循环
可以对 list,string等类型进行for循环。
#List中添加一些字符串:
… words = [‘cat’, ‘window’, ‘defenestrate’]
for w in words:
… print(w, len(w))

cat 3
window 6
defenestrate 12>>> for w in words[:]: # 循环过程中可以对List中的元素进行修改
… if len(w) > 6:
… words.insert(0, w) # 将w 复制一份放到 words的第一位 【0 表示words 索引】

words
[‘defenestrate’, ‘cat’, ‘window’, ‘defenestrate’]
range() 函数

迭代生成一组数字,默认从0开始,每个累加1,到n-1 结束。
for i in range(5):
… print(i)

0
1
2
3
4

也可以指定生成。
range(5, 10) # 5开始,累加1,最后一个数字小于10
5, 6, 7, 8, 9

range(0, 10, 3) # 0开始,累加3,最后一个值小于10
0, 3, 6, 9

range(-10, -100, -30) # -10开始,累加-30,负数累加最后不能小于或等于
-100 -10, -40, -70

工作中最常与for循环一起遍历List等数据。
a = [‘Mary’, ‘had’, ‘a’, ‘little’, ‘lamb’]
for i in range(len(a)):
… print(i, a[i])

0 Mary
1 had
2 a
3 little
4 lamb

range()生成List 数据
list(range(5))
[0, 1, 2, 3, 4]break ,continue
在for循环或者while循环中,使用break 直接跳出循环,不再往下执行。
for n in range(2, 10):
… for x in range(2, n):
… if n % x == 0:
… print(n, ‘equals’, x, ‘*’, n//x)
… break
… else:
… # loop fell through without finding a factor
… print(n, ‘is a prime number’)

2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
continue 会中断当前迭代,然后继续运行下一个迭代,而不是把这个迭代全部中断
for num in range(2, 10):
… if num % 2 == 0:
… print(“Found an even number”, num)
… continue
… print(“Found a number”, num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9pass
作为占位符使用,什么不会执行
while True:
… pass # 按下快捷键 Ctrl+c (Windows 操作系统) 或 Command+c(Mac系统)终止

定义一个class时
class MyEmptyClass:
… pass…

函数中使用时
def initlog(*args):
… pass # Remember to implement this!

敲字不易,如果此文章对你有帮助的话,点个赞收个藏来个关注,给作者一个鼓励。也方便你下次能够快速查找。

以上是关于Python快速入门指南之使用POP/SMTP控制电脑(改进版)的主要内容,如果未能解决你的问题,请参考以下文章

python 是不是有一个强大的 pop3、smtp、mime 库,我可以在其中构建 web 邮件界面?

Nginx快速入门

python3通过qq邮箱发送邮件

TCP/IP协议入门

python发送email邮件

python发送email邮件