Возможно, ты уже умеешь писать простые сценарии на Python, но пробовал ли ты делать графические программы с настоящими работающими кнопочками? Поверь, это тоже крайне увлекательно и не очень сложно! Сегодня мы попрактикуемся в этом, написав на Python и Qt простой почтовик, который будет отправлять письма с аттачами.
Как написать почтовик на Python и Qt
Сразу оговоримся, что приложение будет с рядом ограничений: в частности, мы не будем даже приступать к чтению почты и не сможем выбирать почтовый сервис для отправки. К тому же письма из самопального почтовика могут чаще попадать в спам. Воспринимай это скорее как учебный пример, который поможет тебе освоить полезные навыки.
Создание интерфейса почтовика
Для начала давай создадим интерфейс будущего приложения. Для этого воспользуемся фреймворком для разработки кросс‑платформенного ПО — Qt 5. Потребуется скачать его и установить.
Откроем Qt Designer и в появившемся окне выбора поставим галочку на пункте Main Window.

Затем создадим окно при помощи готовых инструментов, а именно Label для текста, Line Edit для строк ввода, Text Edit для поля ввода текста, а также Push Button для кнопок. Разложить всё можешь так, как тебе понравится, главное — поставить все элементы, показанные на картинке, и запомнить их номера. Дальше будет понятно, зачем это.

Не забудь в поле ввода пароля поставить параметр echoMode = Password, чтобы скрыть пароль, а также выключить поля, которые могут быть активны только после правильного ввода данных. Чтобы это сделать, необходимо в поле enabled убрать галочку.
После завершения работы мое окно выглядит как на скриншоте.
Сохраняй документ, и получишь файл с расширением ui, который и будет файлом интерфейса. Я назвал его Main.ui. Теперь к коду!
Первым делом импортируем две библиотеки. Они нужны для работы с Qt 5.
1 2 |
from PyQt5.QtWidgets import * from PyQt5 import uic |
Теперь прописываем класс интерфейса и в нем все функции. У нас будет функция ввода ( login), функция прикрепления файла ( attach_sth) и функция отправки сообщений ( send_mail). Также в основе основ лежит функция вызова графического интерфейса с демонстрацией окна и активацией трех кнопок.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class MyGUI(QMainWindow): def __init__(self): super(MyGUI, self).__init__() uic.loadUi('Main.ui', self) self.show() self.pushButton.clicked.connect(self.login) self.pushButton_2.clicked.connect(self.attach_sth) self.pushButton_3.clicked.connect(self.send_mail) def login(self): pass def attach_sth(self): pass def send_mail(self): pass app = QApplication([]) windows = MyGUI() app.exec_() |
Здесь интересна функция app.exec_(). Она останавливает работу с терминалом, чтобы все взаимодействие с приложением шло только через графический интерфейс.
Код уже можно запустить! Ты увидишь окно с нарисованным тобой интерфейсом, но в нем пока что ничего не будет работать. Конечно, мы же еще не определили, как это должно происходить.
Создание основной части почтовика
Итак, задача — написать движок. Приступим.
Функция входа. В ней мы делаем две вещи: логинимся и создаем переменную msg (переменная с содержанием письма).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
def login(self): try: self.server = smtplib.SMTP(self.lineEdit_3.text(), # Обращаемся к протоколу SMTP по нужному порту self.lineEdit_4.text()) # Отправляем запрос ELHO self.server.ehlo() # TLS-соединение self.server.starttls() # Снова отправляем запрос ELHO self.server.ehlo() self.server.login(self.lineEdit.text(), # Ввод логина и пароля self.lineEdit_2.text()) # Переводим все поля входа в выключенное состояние self.lineEdit.setEnabled(False) self.lineEdit_2.setEnabled(False) self.lineEdit_3.setEnabled(False) self.lineEdit_4.setEnabled(False) self.pushButton.setEnabled(False) # Переводим все поля письма во включенное состояние self.lineEdit_5.setEnabled(True) self.lineEdit_6.setEnabled(True) self.textEdit.setEnabled(True) self.pushButton_2.setEnabled(True) self.pushButton_3.setEnabled(True) # Создание переменной msg self.msg = MIMEMultipart() # При ошибке в логине и/или пароле except smtplib.SMTPAuthenticationError: # Создать окно massage_box = QMessageBox() # Окно заполнить текстом massage_box.setText('Недопустимые данные!') # Переключиться на окно massage_box.exec() except: massage_box = QMessageBox() massage_box.setText('Не удалось выполнить вход!') massage_box.exec() |
EHLO — это глагол расширенного протокола передачи простых сообщений (ESMTP), определенный в RFC 5321. Серверы ESMTP могут объявлять о своих возможностях во время начального подключения. Среди них — максимальный допустимый размер сообщения и поддерживаемые методы проверки подлинности. HELO — это более старая команда SMTP, определенная в RFC 821. Большинство SMTP-серверов поддерживают ESMTP и EHLO. Если сервер не поддерживает EHLO, вместо него можно использовать HELO.
Далее идет функция прикрепления вложений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
def attach_sth(self): # Открываем диалоговое окно выбора файлов options = QFileDialog.Options() # Смотрим все типы файлов filenames, _ = QFileDialog.getOpenFileNames(self, 'Open File', '', 'All Files (*.*)', options=options) # Собираем файлы if filenames != []: for filename in filenames: attachment = open(filename, 'rb') filename = filename[filename.rfind('/') + 1:] # Кодируем файл по стандарту MIME p = MIMEBase('application', 'octet-stream') p.set_payload(attachment.read()) encoders.encode_base64(p) # Пишем имя файла p.add_header('Content-Disposition', f'attachment; filename={filename}') self.msg.attach(p) # Ставим запятые после первого вложения if not self.label_8.text().endswith(': '): self.label_8.setText(self.label_8.text() + ',') self.label_8.setText(self.label_8.text() + ' ' + filename) |
Создание той самой переменной msg:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
def send_mail(self): # Создаем окно с уточнением dialog = QMessageBox() dialog.setText('Вы хотите отправить сообщение?') # Выбор ответов dialog.addButton(QPushButton('Да'), QMessageBox.YesRole) dialog.addButton(QPushButton('Нет'), QMessageBox.NoRole) if dialog.exec_() == 0: try: # От кого сообщение self.msg['From'] = 'Xakep' # Кому self.msg['To'] = self.lineEdit_6.text() # Тема self.msg['Subject'] = self.lineEdit_5.text() # Собираем сообщение self.msg.attach(MIMEText(self.textEdit.toPlainText(), 'plain')) text = self.msg.as_string() # Отправляем по пути self.server.sendmail(self.lineEdit.text(), self.lineEdit_6.text(), text) # Создаем окно с подтверждением massage_box = QMessageBox() massage_box.setText('Сообщение отправлено!') massage_box.exec() except: # Создаем окно с ошибкой massage_box = QMessageBox() massage_box.setText('Не удалось отправить сообщение!') massage_box.exec() |
Весь код можешь посмотреть на GitHub.
Настройки почты
Я выбрал почту Gmail, поскольку в нем можно выключить защиту от сторонних приложений. Многие другие почтовики ставят запрет на нее, а здесь достаточно перейти по ссылке и выставить разрешение.

Адрес SMTP для Gmail — smtp.gmail.com, порт — 587. Для других почтовых клиентов можно посмотреть эти данные, просто загуглив их название со словом SMTP.
Заключение
Вот мы и написали свой базовый клиент для отправки писем с любыми вложениями. Как видишь, все, что нужно, — это нарисовать форму и написать обработчики, процесс очень простой и прямолинейный.
На всякий случай предупреждаю: можешь даже не пытаться использовать этот код без изменений в незаконных целях. Мы здесь никак не скрываем свой IP, никак не шифруем файлы и не обходим антивирусы.
РЕКОМЕНДУЕМ:
Система распознавания лиц на Python
Зато ты можешь использовать этот пример, чтобы добавить к своим приложениям удобный графический интерфейс.