【Python】远程执行邮件指令

发布于 2015-11-13  629 次阅读


请输入图片描述
这个程序的灵感是来自开源中国网站上一位网友,因为现在手机那么普及,微信、QQ也可以发送邮件,那么我们可以把收发邮件的功能用来当作远程指令不就好了吗。
首先,程序会登录所填写的邮箱,然后读取最新一条邮件,如果邮件的标题是suoping、chongqi、guanji,那么就会执行指定的系统命令,并会发送反馈邮件到指令来源的邮箱里,让用户清楚电脑是否接收到指令,随后会删除带有指令标题的邮件,避免重复执行命令。

主要使用库:poplib、smtplib、ctypes、thread、email

【EXE打包】链接: http://pan.baidu.com/s/1nto08aP 密码: a7dr
Github://github.com/ZanwingMak/email_remote_manipulation

# -*- coding: utf-8 -*-
__author__ = 'm9Kun'
__blog__ = 'laji.blog'
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from ctypes import *
import poplib
from email.parser import Parser
from email.header import decode_header
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr,formataddr
import threading
import thread
import smtplib
import time
import os
import sys
import random
QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))
reload(sys)
sys.setdefaultencoding('utf-8')
class WorkThread1(QThread):
    trigger = pyqtSignal()
    def __int__(self):
        super(WorkThread1,self).__init__()
class YuanCheng(QDialog):
    def __init__(self,parent=None):
        super(YuanCheng,self).__init__(parent)
        self.setWindowTitle(self.tr("远程指令(锁屏、关机、重启)"))
        self.thread = Worker() ###
        mainLayout=QGridLayout(self)
        #hb1 = QHBoxLayout()
        hb1 = QVBoxLayout()
        self.shuoming_biaoti = QLabel(self)
        self.shuoming_biaoti.setText(self.tr("【说明】"))
        self.shuomingtext = QLabel(self)
        self.shuomingtext.setText(self.tr("本远程指令程序的原理是通过本地登录邮箱,检测是否接收到指令邮件,因此需要准备1个或2个邮箱账号并开启POP3、SMTP服务\n否则将无法外部操作邮箱并正常使用此程序!地址可以自动识别并帮您填写,如不正确请自行填写!"))
        self.zhilingtextlist = QLabel(self)
        self.zhilingtextlist.setText(self.tr("【支持的指令有:suoping、guanji、chongqi ,任意邮箱在邮件标题输入指令并发送到下面的邮箱即可,自己发给自己也可以】"))
        hb1.addWidget(self.shuoming_biaoti)
        hb1.addWidget(self.shuomingtext)
        hb1.addWidget(self.zhilingtextlist)
        hb2 = QHBoxLayout()
        self.zhilingjieshou_mail_label = QLabel(self)
        self.zhilingjieshou_mail_label.setText(self.tr("用来接收指令的邮箱地址:"))
        self.zhilingjieshou_mail_edit = QLineEdit()
        self.zhilingjieshoupassword_mail_label = QLabel(self)
        self.zhilingjieshoupassword_mail_label.setText(self.tr("密码:"))
        self.zhilingjieshoupassword_mail_edit = QLineEdit()
        hb2.addWidget(self.zhilingjieshou_mail_label)
        hb2.addWidget(self.zhilingjieshou_mail_edit)
        hb2.addWidget(self.zhilingjieshoupassword_mail_label)
        hb2.addWidget(self.zhilingjieshoupassword_mail_edit)
        hb3 = QHBoxLayout()
        self.zhilingjieshou_smtpaddr_label = QLabel(self)
        self.zhilingjieshou_smtpaddr_label.setText(self.tr("SMTP服务器地址:"))
        self.zhilingjieshou_smtpaddr_edit = QLineEdit()
        self.zhilingjieshou_popaddr_label = QLabel(self)
        self.zhilingjieshou_popaddr_label.setText(self.tr("POP服务器地址:"))
        self.zhilingjieshou_popaddr_edit = QLineEdit()
        self.auto_btn = QPushButton(self)
        self.auto_btn.setText(self.tr("自动识别"))
        self.auto_btn.clicked.connect(self.auto_btn_Clicked)
        hb3.addWidget(self.zhilingjieshou_smtpaddr_label)
        hb3.addWidget(self.zhilingjieshou_smtpaddr_edit)
        hb3.addWidget(self.zhilingjieshou_popaddr_label)
        hb3.addWidget(self.zhilingjieshou_popaddr_edit)
        hb3.addWidget(self.auto_btn)
        hb4 = QHBoxLayout()
        self.isSSL_checkbox = QCheckBox(u"使用SSL加密安全传输功能")
        self.isSSL_checkbox.setChecked(True)
        self.ok_btn = QPushButton(self)
        self.ok_btn.setText(self.tr("启动"))
        self.ok_btn.clicked.connect(self.ok_btn_Clicked)
        self.clear_ListWidgetContent_btn = QPushButton(self)
        self.clear_ListWidgetContent_btn.setText(self.tr("清屏"))
        self.clear_ListWidgetContent_btn.clicked.connect(self.clear_ListWidgetContent_btn_Clicked)
        self.clear_btn = QPushButton(self)
        self.clear_btn.setText(self.tr("重置"))
        self.clear_btn.clicked.connect(self.clear_btn_Clicked)
        hb4.addWidget(self.isSSL_checkbox)
        hb4.addWidget(self.ok_btn)
        hb4.addWidget(self.clear_ListWidgetContent_btn)
        hb4.addWidget(self.clear_btn)
        hb5=QVBoxLayout()
        self.ListWidgetContent1 = QListWidget(self)
        hb5.addWidget(self.ListWidgetContent1)
        mainLayout.addLayout(hb1,0,0)
        mainLayout.addLayout(hb2,1,0)
        mainLayout.addLayout(hb3,2,0)
        mainLayout.addLayout(hb4,3,0)
        mainLayout.addLayout(hb5,4,0)
    def auto_btn_Clicked(self):
        mail_check = (self.zhilingjieshou_mail_edit.text().split('@'))[-1].split('.')[0]
        self.zhilingjieshou_smtpaddr_edit.setText('smtp.%s.com' % mail_check)
        self.zhilingjieshou_popaddr_edit.setText('pop.%s.com' % mail_check)
    def ok_btn_Clicked(self):
        self.ok_btn.setDisabled(True)
        pc_address = str(self.zhilingjieshou_mail_edit.text())
        password = str(self.zhilingjieshoupassword_mail_edit.text())
        smtp_server = str(self.zhilingjieshou_smtpaddr_edit.text())
        pop_server = str(self.zhilingjieshou_popaddr_edit.text())
        if self.isSSL_checkbox.isChecked():
            ifusessl = 'yes'
        else:
            ifusessl = 'no'
        self.ListWidgetContent1.addItem(u'服务正在开启...')
        self.ListWidgetContent1.setCurrentRow(yuancheng.ListWidgetContent1.count()-1)
        self.thread.render(pc_address,password,smtp_server,pop_server,ifusessl)
    def clear_ListWidgetContent_btn_Clicked(self):
        self.ListWidgetContent1.clear()
    def clear_btn_Clicked(self):
        self.zhilingjieshou_mail_edit.setText('')
        self.zhilingjieshoupassword_mail_edit.setText('')
        self.zhilingjieshou_smtpaddr_edit.setText('')
        self.zhilingjieshou_popaddr_edit.setText('')
        self.isSSL_checkbox.setChecked(False)
    def update_msg_list(self,msg):
        self.ListWidgetContent1.addItem(msg)#.decode('utf-8')
        self.ListWidgetContent1.setCurrentRow(yuancheng.ListWidgetContent1.count()-1)
class Worker(QThread):
    def __int__(self, parent = None):
        QThread.__init__(self, parent)
    def render(self,pc_address,password,smtp_server,pop_server,ifusessl):
        self.pc_address = pc_address
        self.password = password
        self.smtp_server = smtp_server
        self.pop_server = pop_server
        self.ifusessl = ifusessl
        self.start()
    def sendMsg(self,msg):
        yuancheng.update_msg_list(msg)
    def run(self):
            def guess_charset(msg):
                # 先从msg对象获取编码:
                charset = msg.get_charset()
                # 如果获取不到,再从Content-Type字段获取:
                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()
                return charset
            #邮件的Subject或者Email中包含的名字都是经过编码后的str,要正常显示,就必须decode
            def decode_str(s):
                value, charset = decode_header(s)[0]
                if charset:
                    value = value.decode(charset)
                return value
            def get_info(msg):
                    for header in ['From','Subject']:
                            value = msg.get(header, '')
                            if value:
                                if header=='Subject':
                                    subject = decode_str(value)
                                else:
                                    hdr, from_email = parseaddr(value)
                    return from_email,subject
            def reply(text,zhilingduan_email,pc_address):
                    def format_address(s):
                        name,address = parseaddr(s)
                        return formataddr((Header(name,'utf-8').encode(),\
                                   address.encode('utf-8') if isinstance(address,unicode) else address))
                    msg = MIMEText(text,'plain','utf-8')
                    msg['From'] = format_address(u'指令接收端 <%s>'% pc_address)
                    msg['To'] = format_address(u'指令来源 <%s>' % zhilingduan_email)
                    msg['Subject'] = Header(u'电脑发来远程指令信息反馈','utf-8').encode()
                    serve_smtp = smtplib.SMTP(self.smtp_server,25)
                    serve_smtp.set_debuglevel(1)
                    serve_smtp.login(pc_address,self.password)
                    serve_smtp.sendmail(pc_address,[zhilingduan_email],msg.as_string())
                    serve_smtp.quit()
            def play(from_email,subject,pc_address):
                if from_email == pc_address:
                    count = 3
                else:
                    count = 1
                if subject == 'suoping':
                    text = u'已收到远程指令:锁屏...'
                    reply(text,from_email,pc_address)
                    self.sendMsg(text)
                    #print text
                    time.sleep(2)
                    try:
                            text = u'正在执行远程锁屏指令...'
                            reply(text,from_email,pc_address)
                            self.sendMsg(text)
                            time.sleep(2)
                            user32 = windll.LoadLibrary('user32.dll')
                            user32.LockWorkStation()
                    except:
                            text = u'远程指令执行失败,请重试...'
                            reply(text,from_email,pc_address)
                            self.sendMsg(text)
                            time.sleep(2)
                elif subject == 'guanji':
                         text = u'已收到远程指令:关机...'
                         reply(text,from_email,pc_address)
                         self.sendMsg(text)
                         time.sleep(2)
                         try:
                                text = u'正在执行远程关机指令...'
                                reply(text,from_email,pc_address)
                                self.sendMsg(text)
                                time.sleep(2)
                                os.system('shutdown -f -s -t 10 -c Closing...')
                         except:
                                text = u'远程指令执行失败,请重试...'
                                reply(text,from_email,pc_address)
                                self.sendMsg(text)
                                time.sleep(2)
                elif subject == 'chongqi':
                        text = u'已收到远程指令:重启...'
                        reply(text,from_email,pc_address)
                        self.sendMsg(text)
                        time.sleep(2)
                        try:
                                text = u'正在执行远程重启指令...'
                                reply(text,from_email,pc_address)
                                self.sendMsg(text)
                                time.sleep(2)
                                os.system('shutdown -f -r -t 10 -c Rstarting...')
                        except:
                                text = u'远程指令执行失败,请重试...'
                                self.sendMsg(text)
                                reply(text,from_email,pc_address)
                                time.sleep(2)
                else:
                    pass
                server.dele(count) #删除邮件
            while True:
                try:
                    # 连接到POP服务器:
                    self.sendMsg(u'正在连接POP服务器...')
                    if self.ifusessl == 'yes':
                        server = poplib.POP3_SSL(self.pop_server)
                        self.sendMsg(u'正在使用SSL安全加密服务...')
                    else:
                        server = poplib.POP3(self.pop_server)
                    # 身份认证:
                    self.sendMsg(u'正在认证身份...')
                    server.user(self.pc_address)
                    server.pass_(self.password)
                    self.sendMsg(u'身份认证成功...')
                    # list()返回所有邮件的编号:
                    resp, mails, octets = server.list()
                    #print resp,mails,octets
                    self.sendMsg(u'正在获取邮件...')
                    # 获取最新一封邮件, 注意索引号从1开始:
                    resp, lines, octets = server.retr(len(mails))#而len(mails)则相反方向开始,由最大长度开始,即从最新开始数
                    #print resp, lines, octets
                    self.sendMsg(u'正在解析邮件...')
                    # 解析邮件:
                    #print lines
                    msg = Parser().parsestr('\r\n'.join(lines))
                    # 获取邮件信息:
                    self.sendMsg(u'正在获取邮件信息...')
                    from_email,subject = get_info(msg)
                    #删除指令接收邮件
                    #self.sendMsg(u'正在检测并清理已使用的指令邮件...')
                    #resp, mails, octets = server.list()
                    #a = len(mails)
                    #if a>5:
                    #    b = 5
                    #else:
                    #    b = a
                    #del_list = []
                    #for i in range(b):
                    #    resp, lines, octets = server.retr(b-i)
                    #    msg = Parser().parsestr('\r\n'.join(lines))
                    #    from_email,subject = get_info(msg)
                    #    if subject in ['suoping','chongqi','guanji']:
                    #        del_list.append(i+1)
                    #for j in del_list:
                    #    server.dele(j)
                    #self.sendMsg(u'邮件检测与清理执行完毕...')
                    #执行远程命令
                    #self.sendMsg(u'准备执行远程指令...')
                    play(from_email,subject,self.pc_address)
                    # 关闭连接:
                    self.sendMsg(u'正在本次关闭连接...')
                    server.quit()
                    self.sendMsg(u'连接已关闭,正在等候下次连接(30~60s)...')
                    time.sleep(30+random.randint(0,30))
                    continue
                except Exception as e:
                    if 'Syntax' not in str(e) and 'EOF' not in str(e):
                        self.sendMsg(str(e).decode('gbk'))
                    self.sendMsg(u'正在重试,需等候下次连接(60~120s)...')
                    time.sleep(60+random.randint(0,60)) #60+n秒检测一次,最好设置成5分钟!
                    continue
app=QApplication(sys.argv)
yuancheng=YuanCheng()
yuancheng.show()
app.exec_()

❤动漫 | 音乐 | 游戏 萝莉赛高! 过膝袜赛高!