Fri, 06 Dec 2019 10:26:43 GMT
parent
20ff2f745d
commit
ba1069a462
@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.formatting.provider": "yapf"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.formatting.provider": "yapf"
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
import threading
|
||||
import os
|
||||
import sys
|
||||
from socket import *
|
||||
from PyQt5.Qt import *
|
||||
from main_window_ui import Ui_MainWindow
|
||||
|
||||
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
def __init__(self):
|
||||
super(MainWindow, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.btnSend.clicked.connect(self.btnSend_onclicked)
|
||||
self.btnConnect.clicked.connect(self.btnConnect_onclicked)
|
||||
self.statusbar.showMessage("Disconnected")
|
||||
self.socket: socket = None
|
||||
self.isConnected = False
|
||||
|
||||
def closeEvent(self, event):
|
||||
if self.isConnected:
|
||||
self.btnConnect.click()
|
||||
self.close()
|
||||
|
||||
def btnConnect_onclicked(self):
|
||||
if not self.isConnected:
|
||||
server_addr = self.txtServerInput.text()
|
||||
sp = server_addr.rfind(':')
|
||||
if sp in [-1, 0, len(server_addr) - 1]:
|
||||
QMessageBox.critical(self, "Error", "Invalid address")
|
||||
return
|
||||
addr, port = server_addr[:sp], server_addr[sp + 1:]
|
||||
try:
|
||||
port = int(port)
|
||||
except:
|
||||
QMessageBox.critical(self, "Error", "Invalid port")
|
||||
return
|
||||
try:
|
||||
self.socket = socket(AF_INET, SOCK_STREAM)
|
||||
self.socket.connect((addr, port))
|
||||
except:
|
||||
QMessageBox.critical(self, "Error", "Connect failed")
|
||||
return
|
||||
self.btnConnect.setText('Disconnect')
|
||||
self.statusbar.showMessage("Connected")
|
||||
self.isConnected = True
|
||||
threading.Thread(target=self.recvmsg_loop).start()
|
||||
else:
|
||||
self.socket.close()
|
||||
self.btnConnect.setText('Connect')
|
||||
self.statusbar.showMessage("Disonnected")
|
||||
self.isConnected = False
|
||||
|
||||
def btnSend_onclicked(self):
|
||||
msg = ':'.join([self.txtIDInput.text(), self.txtNewMsg.toPlainText()])
|
||||
self.txtNewMsg.clear()
|
||||
self.socket.send(msg.encode())
|
||||
|
||||
def recvmsg_loop(self):
|
||||
while True:
|
||||
if not self.isConnected:
|
||||
return
|
||||
msg = self.socket.recv(1 << 20).decode()
|
||||
print(msg)
|
||||
sp1 = msg.find(':')
|
||||
sp2 = msg.find(':', sp1 + 1)
|
||||
msg = "{}@{}:\n{}".format(msg[sp1 + 1:sp2], msg[:sp1],
|
||||
msg[sp2 + 1:])
|
||||
self.txtList.append(msg)
|
||||
self.txtList.moveCursor(QTextCursor.End)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||
app = QApplication(sys.argv)
|
||||
mw = MainWindow()
|
||||
mw.show()
|
||||
app.exec()
|
||||
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
pushd %~dp0
|
||||
for %%i in (*.ui) do pyuic5 "%%i" -o "%%~ni_ui.py"
|
||||
@ -0,0 +1,12 @@
|
||||
import { readdir, watchFile } from "fs";
|
||||
import { extname } from 'path';
|
||||
import { exec } from 'child_process';
|
||||
readdir('.', (_, files) => {
|
||||
files.filter(file => extname(file) == '.ui').forEach(file => {
|
||||
console.log(`Setup modify hook for ${file}`);
|
||||
watchFile(file, (curr, _) => {
|
||||
console.log(`${file} modified at ${curr.mtime}.`);
|
||||
exec('compile_ui');
|
||||
});
|
||||
})
|
||||
});
|
||||
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,7,1,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Server:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtServerInput">
|
||||
<property name="text">
|
||||
<string>127.0.0.1:34567</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnConnect">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="txtList"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="txtNewMsg"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtIDInput"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSend">
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'main_window.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.13.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(800, 600)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.label = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label.setObjectName("label")
|
||||
self.horizontalLayout.addWidget(self.label)
|
||||
self.txtServerInput = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtServerInput.setObjectName("txtServerInput")
|
||||
self.horizontalLayout.addWidget(self.txtServerInput)
|
||||
self.btnConnect = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.btnConnect.setObjectName("btnConnect")
|
||||
self.horizontalLayout.addWidget(self.btnConnect)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.txtList = QtWidgets.QTextBrowser(self.centralwidget)
|
||||
self.txtList.setObjectName("txtList")
|
||||
self.verticalLayout.addWidget(self.txtList)
|
||||
self.txtNewMsg = QtWidgets.QPlainTextEdit(self.centralwidget)
|
||||
self.txtNewMsg.setObjectName("txtNewMsg")
|
||||
self.verticalLayout.addWidget(self.txtNewMsg)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.label_2 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.horizontalLayout_2.addWidget(self.label_2)
|
||||
self.txtIDInput = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtIDInput.setObjectName("txtIDInput")
|
||||
self.horizontalLayout_2.addWidget(self.txtIDInput)
|
||||
self.btnSend = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.btnSend.setObjectName("btnSend")
|
||||
self.horizontalLayout_2.addWidget(self.btnSend)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
self.verticalLayout.setStretch(1, 7)
|
||||
self.verticalLayout.setStretch(2, 1)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
|
||||
self.menubar.setObjectName("menubar")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindow.setStatusBar(self.statusbar)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||
self.label.setText(_translate("MainWindow", "Server:"))
|
||||
self.txtServerInput.setText(_translate("MainWindow", "127.0.0.1:34567"))
|
||||
self.btnConnect.setText(_translate("MainWindow", "Connect"))
|
||||
self.label_2.setText(_translate("MainWindow", "ID:"))
|
||||
self.btnSend.setText(_translate("MainWindow", "Send"))
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.formatting.provider": "yapf"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
pushd %~dp0
|
||||
for %%i in (*.ui) do pyuic5 "%%i" -o "%%~ni_ui.py"
|
||||
@ -0,0 +1,12 @@
|
||||
import { readdir, watchFile } from "fs";
|
||||
import { extname } from 'path';
|
||||
import { exec } from 'child_process';
|
||||
readdir('.', (_, files) => {
|
||||
files.filter(file => extname(file) == '.ui').forEach(file => {
|
||||
console.log(`Setup modify hook for ${file}`);
|
||||
watchFile(file, (curr, _) => {
|
||||
console.log(`${file} modified at ${curr.mtime}.`);
|
||||
exec('compile_ui');
|
||||
});
|
||||
})
|
||||
});
|
||||
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>SendLog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'log_window.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.13.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
Dialog.resize(400, 300)
|
||||
self.gridLayout = QtWidgets.QGridLayout(Dialog)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.textBrowser = QtWidgets.QTextBrowser(Dialog)
|
||||
self.textBrowser.setObjectName("textBrowser")
|
||||
self.gridLayout.addWidget(self.textBrowser, 0, 0, 1, 1)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||
|
||||
def retranslateUi(self, Dialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Dialog.setWindowTitle(_translate("Dialog", "SendLog"))
|
||||
@ -0,0 +1,90 @@
|
||||
import sys
|
||||
import re
|
||||
import threading
|
||||
from base64 import b64encode
|
||||
from typing import *
|
||||
from socket import *
|
||||
from PyQt5.Qt import *
|
||||
from main_window_ui import Ui_MainWindow
|
||||
from log_window_ui import Ui_Dialog
|
||||
|
||||
|
||||
def static_vars(**kwargs):
|
||||
def decorate(func):
|
||||
for k in kwargs:
|
||||
setattr(func, k, kwargs[k])
|
||||
return func
|
||||
|
||||
return decorate
|
||||
|
||||
|
||||
@static_vars(
|
||||
matcher=re.compile(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"))
|
||||
def validate_email(email: str):
|
||||
return validate_email.matcher.fullmatch(email)
|
||||
|
||||
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
def __init__(self):
|
||||
super(MainWindow, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.btnSendMail.clicked.connect(self.send_mail)
|
||||
self.txtFrom.textChanged.connect(self.mail_changed)
|
||||
|
||||
def mail_changed(self):
|
||||
pass
|
||||
|
||||
def send_mail(self):
|
||||
servaddr = self.txtServer.text()
|
||||
username = self.txtFrom.text()
|
||||
password = self.txtPassword.text()
|
||||
receiver = self.txtTo.text()
|
||||
subjects = self.txtSubject.text()
|
||||
contents = self.txtContent.toPlainText()
|
||||
if not validate_email(username) or not validate_email(receiver):
|
||||
QMessageBox.critical(self, "Invalid address", "Invalid From or To")
|
||||
return
|
||||
lw = LogWindow(
|
||||
(servaddr, username, password, receiver, subjects, contents))
|
||||
lw.exec()
|
||||
|
||||
|
||||
class LogWindow(QDialog, Ui_Dialog):
|
||||
def __init__(self, data):
|
||||
super(LogWindow, self).__init__()
|
||||
self.setupUi(self)
|
||||
threading.Thread(target=self.do_update_status, args=(data, )).start()
|
||||
|
||||
def do_update_status(self, data):
|
||||
(servaddr, username, password, receiver, subjects, contents) = data
|
||||
ss = socket(AF_INET, SOCK_STREAM)
|
||||
try:
|
||||
ss.connect((servaddr, 25))
|
||||
except Exception:
|
||||
QMessageBox.critical(self, "Connection Failed",
|
||||
"Failed connecting smtp server")
|
||||
return
|
||||
|
||||
def comm(msg: str):
|
||||
msg += "\r\n"
|
||||
ss.sendall(msg.encode())
|
||||
self.textBrowser.append("C: " + msg)
|
||||
self.textBrowser.append("S: " + ss.recv(1 << 20).decode())
|
||||
|
||||
comm("HELO " + servaddr)
|
||||
comm("AUTH LOGIN")
|
||||
comm(b64encode(username.encode()).decode())
|
||||
comm(b64encode(password.encode()).decode())
|
||||
comm("MAIL FROM:<{}>".format(username))
|
||||
comm("RCPT TO:<{}>".format(receiver))
|
||||
comm("DATA")
|
||||
comm('\r\n'.join(["Subject: " + subjects, "", contents, "."]))
|
||||
comm("QUIT")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||
app = QApplication(sys.argv)
|
||||
mw = MainWindow()
|
||||
mw.show()
|
||||
app.exec()
|
||||
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>SimpleMailSender</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Server:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>From:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>To:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Subject:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtServer">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtFrom">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtPassword">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::PasswordEchoOnEdit</enum>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtTo">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtSubject">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="txtContent"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSendMail">
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -0,0 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'main_window.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.13.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(800, 600)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.label_5 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.verticalLayout.addWidget(self.label_5)
|
||||
self.label = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label.setObjectName("label")
|
||||
self.verticalLayout.addWidget(self.label)
|
||||
self.label_2 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.verticalLayout.addWidget(self.label_2)
|
||||
self.label_3 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.verticalLayout.addWidget(self.label_3)
|
||||
self.label_4 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.verticalLayout.addWidget(self.label_4)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout)
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.txtServer = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtServer.setClearButtonEnabled(True)
|
||||
self.txtServer.setObjectName("txtServer")
|
||||
self.verticalLayout_2.addWidget(self.txtServer)
|
||||
self.txtFrom = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtFrom.setClearButtonEnabled(True)
|
||||
self.txtFrom.setObjectName("txtFrom")
|
||||
self.verticalLayout_2.addWidget(self.txtFrom)
|
||||
self.txtPassword = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtPassword.setEchoMode(QtWidgets.QLineEdit.PasswordEchoOnEdit)
|
||||
self.txtPassword.setClearButtonEnabled(True)
|
||||
self.txtPassword.setObjectName("txtPassword")
|
||||
self.verticalLayout_2.addWidget(self.txtPassword)
|
||||
self.txtTo = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtTo.setClearButtonEnabled(True)
|
||||
self.txtTo.setObjectName("txtTo")
|
||||
self.verticalLayout_2.addWidget(self.txtTo)
|
||||
self.txtSubject = QtWidgets.QLineEdit(self.centralwidget)
|
||||
self.txtSubject.setClearButtonEnabled(True)
|
||||
self.txtSubject.setObjectName("txtSubject")
|
||||
self.verticalLayout_2.addWidget(self.txtSubject)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_2)
|
||||
self.verticalLayout_3.addLayout(self.horizontalLayout)
|
||||
self.txtContent = QtWidgets.QPlainTextEdit(self.centralwidget)
|
||||
self.txtContent.setObjectName("txtContent")
|
||||
self.verticalLayout_3.addWidget(self.txtContent)
|
||||
self.btnSendMail = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.btnSendMail.setObjectName("btnSendMail")
|
||||
self.verticalLayout_3.addWidget(self.btnSendMail)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
|
||||
self.menubar.setObjectName("menubar")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindow.setStatusBar(self.statusbar)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "SimpleMailSender"))
|
||||
self.label_5.setText(_translate("MainWindow", "Server:"))
|
||||
self.label.setText(_translate("MainWindow", "From:"))
|
||||
self.label_2.setText(_translate("MainWindow", "Password:"))
|
||||
self.label_3.setText(_translate("MainWindow", "To:"))
|
||||
self.label_4.setText(_translate("MainWindow", "Subject:"))
|
||||
self.btnSendMail.setText(_translate("MainWindow", "Send"))
|
||||
@ -0,0 +1,38 @@
|
||||
from gevent import monkey, spawn
|
||||
monkey.patch_all()
|
||||
from socket import *
|
||||
from typing import *
|
||||
|
||||
conns: Set[Tuple[socket, Any]] = set()
|
||||
|
||||
|
||||
def boardcast(message: str):
|
||||
print(message)
|
||||
for conn, addr in conns:
|
||||
print('send to ', conn, addr)
|
||||
conn.send(message.encode())
|
||||
|
||||
|
||||
def process_connection(conn: socket, addr):
|
||||
conns.add((conn, addr))
|
||||
boardcast('server:global:{} connected.'.format(addr))
|
||||
while True:
|
||||
try:
|
||||
res_raw = conn.recv(1 << 20)
|
||||
if not res_raw:
|
||||
raise
|
||||
except Exception:
|
||||
conns.remove((conn, addr))
|
||||
boardcast('server:global:{} disconnected.'.format(addr))
|
||||
return
|
||||
res = res_raw.decode()
|
||||
boardcast('{}:{}'.format(addr, res))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
with socket(AF_INET, SOCK_STREAM) as s:
|
||||
s.bind(('0.0.0.0', 34567))
|
||||
s.listen(1 << 16)
|
||||
while True:
|
||||
conn, addr = s.accept()
|
||||
spawn(process_connection, conn, addr)
|
||||
Loading…
Reference in new issue