├── .gitignore ├── LICENSE.txt ├── README.md ├── icons ├── add_account.png ├── check_now.png ├── details.png ├── mailbox_empty.png ├── mailbox_error.png ├── mailbox_full.png ├── menu_quit.png ├── remove_account.png ├── rename_account.png ├── save_account.png └── settings.png ├── mail-notifier.py ├── resources.qrc ├── resources_rc.py ├── screenshots ├── details-3.0.jpg ├── no_unread_mails-3.0.jpg ├── screen1.jpg ├── screen2.jpg ├── screen3.jpg └── unread_mails-3.0.jpg ├── ui ├── about.ui ├── details.ui └── settings.ui ├── ui_about.py ├── ui_details.py └── ui_settings.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2017, Peter Svirshchevskiy 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Migration 2 | 3 | This repository is now read only, I won't update it anymore. Actual repository is here: https://git.rinaldus.ru/Rinaldus/mail-notifier 4 | 5 | ## About 6 | 7 | This is Light weight mail notifier written in PyQt5. It checks your mailbox periodically and notify you if you have new mail. 8 | 9 | ## Screenshots 10 | ### Version 3.0 11 | ![MailboxEmpty](https://raw.github.com/rinaldus/mail-notifier/master/screenshots/no_unread_mails-3.0.jpg) 12 | ![MailboxFull](https://raw.github.com/rinaldus/mail-notifier/master/screenshots/unread_mails-3.0.jpg) 13 | ![Details](https://raw.github.com/rinaldus/mail-notifier/master/screenshots/details-3.0.jpg) 14 | ### Version 1.0 15 | ![MailboxEmpty](https://raw.github.com/rinaldus/mail-notifier/master/screenshots/screen1.jpg) 16 | ![MailboxFull](https://raw.github.com/rinaldus/mail-notifier/master/screenshots/screen2.jpg) 17 | ![Settings](https://raw.github.com/rinaldus/mail-notifier/master/screenshots/screen3.jpg) 18 | 19 | ## Install 20 | 21 | You need to install PyQt5 as dependency. Then just clone this git repository or download release and copy all files where you want to store this program. No additional installation is required. 22 | *In version 0.10 you also need to edit mail-notifier.py and fill your mailbox credentials in 70-72 rows* 23 | 24 | ## Launch 25 | 26 | Give execute permission to mail-notifier.py 27 | ```sh 28 | $ chmod +x mail-notifier.py 29 | ``` 30 | 31 | ## Changelog 32 | 33 | ### Version 3.01 (release date: 10.10.17) 34 | * Added status bar in Details window 35 | * Details window now remembers its size 36 | * Some cosmetic improvements in menu 37 | 38 | ### Version 3.0 (release date: 26.07.16) 39 | * System tray icon displays count of unread mail directly on itself 40 | * Popup notification behaviour was changed: now popup notification appears only if the number of unread emails has 41 | changed since last mail check 42 | * Now you can view a short information about unread emails by click on system tray icon or choose "Details" from system tray menu 43 | 44 | ### Version 2.0 (release date: 23.03.16) 45 | * **Important! Users of Mail Notifier 1.x have to delete old configuration file located in ~/.config/mail-notifier/settings.conf before first launch of new version** 46 | * New "About" window 47 | * Added license (BSD 3-Clause) 48 | 49 | ### Version 2.0-beta1 (release date: 10.02.16) 50 | * **Important! The configuration structure was changed. Users of Mail Notifier 1.x have to delete old configuration file located in ~/.config/mail-notifier/settings.conf before first launch of new version** 51 | * Multi account support. Now the program is able to check new mails in several mailboxes. You will get the total quantity of new mails from all mailboxes in system tray 52 | 53 | ### Version 1.02 (release date: 26.01.16) 54 | * Rewrote periodical mail check function and fixed bug in OS X 55 | 56 | ### Version 1.01 (release date: 25.01.16) 57 | * New icon, that shows if you have connection problems 58 | * Fixed bug when system tray icon sometimes didn't appear after DE start 59 | 60 | ### Version 1.0 (release date: 01.11.15) 61 | * Settings window 62 | * All parameters are stored in configuration file *(~/.config/mail-notifier/settings.conf)* 63 | * Many improvements 64 | 65 | ### Version 0.10 (pre release date: 28.10.15) 66 | * Initial version 67 | * All parameters are stored right in script 68 | -------------------------------------------------------------------------------- /icons/add_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/add_account.png -------------------------------------------------------------------------------- /icons/check_now.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/check_now.png -------------------------------------------------------------------------------- /icons/details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/details.png -------------------------------------------------------------------------------- /icons/mailbox_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/mailbox_empty.png -------------------------------------------------------------------------------- /icons/mailbox_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/mailbox_error.png -------------------------------------------------------------------------------- /icons/mailbox_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/mailbox_full.png -------------------------------------------------------------------------------- /icons/menu_quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/menu_quit.png -------------------------------------------------------------------------------- /icons/remove_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/remove_account.png -------------------------------------------------------------------------------- /icons/rename_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/rename_account.png -------------------------------------------------------------------------------- /icons/save_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/save_account.png -------------------------------------------------------------------------------- /icons/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/icons/settings.png -------------------------------------------------------------------------------- /mail-notifier.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from PyQt5.QtGui import QIcon 4 | from PyQt5.QtWidgets import (QAction, QApplication, QCheckBox, QComboBox, 5 | QDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, 6 | QMessageBox, QMenu, QPushButton, QSpinBox, QStyle, QSystemTrayIcon, 7 | QTextEdit, QVBoxLayout, QInputDialog) 8 | from PyQt5.QtCore import (QThread, QTimer, QFile, QSettings) 9 | import imaplib 10 | import email 11 | imaplib._MAXLINE = 400000 12 | import subprocess 13 | import resources_rc 14 | from ui_settings import Ui_Settings 15 | from ui_about import Ui_about 16 | from ui_details import Ui_Details 17 | from PyQt5 import QtCore, QtGui, QtWidgets 18 | import os 19 | import socket 20 | import time 21 | from datetime import datetime, date, time 22 | 23 | #variables 24 | programTitle = "Mail Notifier" 25 | programVersion = "3.01-dev" 26 | settings = QSettings(os.path.expanduser("~")+"/.config/mail-notifier/settings.conf", QSettings.NativeFormat) 27 | def GlobalSettingsExist(): 28 | if ((settings.contains("CheckInterval") and settings.value("CheckInterval") != "") and 29 | (settings.contains("Notify") and settings.value("Notify") != "")): 30 | return True 31 | else: 32 | return False 33 | 34 | def AccountExist(): 35 | groups = settings.childGroups() 36 | if (len(groups)) != 0: 37 | settings.beginGroup(groups[0]) 38 | if ((settings.contains("MailServer") and settings.value("MailServer") != "") and 39 | (settings.contains("Port") and settings.value("Port") != "") and 40 | (settings.contains("Login") and settings.value("Login") != "") and 41 | (settings.contains("Password") and settings.value("Password") != "") and 42 | (settings.contains("SSL") and settings.value("SSL") != "")): 43 | n = True 44 | else: 45 | n = False 46 | settings.endGroup() 47 | else: 48 | n = False 49 | if (n): 50 | return True 51 | else: 52 | return False 53 | 54 | class Window(QDialog): 55 | def __init__(self): 56 | super(Window, self).__init__() 57 | 58 | # UI 59 | self.createActions() 60 | self.setTitle=programTitle 61 | self.createTrayIcon() 62 | # Draw system tray icon 63 | pixmap = QtGui.QPixmap(QtGui.QPixmap(":icons/mailbox_empty.png")) 64 | painter = QtGui.QPainter(pixmap) 65 | painter.setPen(QtGui.QColor(255, 0, 0)) 66 | painter.setFont(QtGui.QFont('Arial', QtGui.QFont.Bold)) 67 | painter.drawText(QtCore.QRectF(pixmap.rect()), QtCore.Qt.AlignCenter, "0") 68 | painter.end() 69 | self.trayIcon.setIcon(QtGui.QIcon(pixmap)) 70 | # End drawing system tray icon 71 | 72 | self.trayIcon.setToolTip("You have no unread letters") 73 | self.trayIcon.show() 74 | 75 | # setup settings 76 | self.ui = Ui_Settings() 77 | self.ui.setupUi(self) 78 | self.setWindowIcon(QIcon(os.path.dirname(os.path.realpath(__file__))+"/icons/mailbox_empty.png")) 79 | self.SettingsRestore() 80 | 81 | self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.btnOK_clicked) 82 | self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self.btnCancel_clicked) 83 | self.ui.btnTestConnection.clicked.connect(self.btnTestConnection_clicked) 84 | self.ui.comboAccounts.currentTextChanged.connect(self.comboAccounts_changed) 85 | self.ui.btnAddAccount.clicked.connect(self.btnAddAccount_clicked) 86 | self.ui.btnRenameAccount.clicked.connect(self.btnRenameAccount_clicked) 87 | self.ui.btnSaveAccount.clicked.connect(self.btnSaveAccount_clicked) 88 | self.ui.btnRemoveAccount.clicked.connect(self.btnRemoveAccount_clicked) 89 | 90 | # Check if account doesn't exist, it creates default one 91 | if (AccountExist() == False): 92 | self.ui.comboAccounts.addItem("Default") 93 | self.ui.comboAccounts.setCurrentText("Default") 94 | 95 | 96 | # Main timer 97 | self.timer = QTimer(self) 98 | self.timer.timeout.connect(mail_check) 99 | 100 | self.lastCheckCount = 0 # variable for prevent annoying popup notification when mail count didn't change since last check 101 | 102 | # Menu actions 103 | def createActions(self): 104 | self.detailsShow = QAction(QIcon(':icons/details.png'),"&Details...", self, triggered=self.detailsShow) 105 | self.aboutShow = QAction(QIcon(':icons/mailbox_empty.png'),"&About " + programTitle + "...", self, triggered=self.aboutShow) 106 | self.checkNow = QAction(QIcon(':icons/check_now.png'),"&Check now", self, triggered=mail_check) 107 | self.restoreAction = QAction(QIcon(":icons/settings.png"),"&Settings...", self, triggered=self.showNormal) 108 | self.quitAction = QAction(QIcon(':icons/menu_quit.png'),"&Quit", self, triggered=QApplication.instance().quit) 109 | 110 | # UI functions 111 | def createTrayIcon(self): 112 | self.trayIconMenu = QMenu(self) 113 | f = self.trayIconMenu.font() 114 | f.setBold(True) 115 | self.detailsShow.setFont(f) 116 | self.trayIconMenu.addAction(self.detailsShow) 117 | self.trayIconMenu.addSeparator() 118 | self.trayIconMenu.addAction(self.checkNow) 119 | self.trayIconMenu.addAction(self.restoreAction) 120 | self.trayIconMenu.addAction(self.aboutShow) 121 | self.trayIconMenu.addAction(self.quitAction) 122 | self.trayIcon = QSystemTrayIcon(self) 123 | self.trayIcon.setContextMenu(self.trayIconMenu) 124 | self.trayIcon.activated.connect(self.trayIconActivated) 125 | 126 | def SettingsRestore(self): 127 | if (GlobalSettingsExist() and AccountExist()): 128 | groups = settings.childGroups() 129 | self.ui.comboAccounts.clear() # Clear account items before fill them again 130 | for i in range (len(groups)): 131 | self.ui.comboAccounts.addItem(groups[i]) 132 | self.ui.comboAccounts.setCurrentText(groups[i]) 133 | settings.beginGroup(groups[i]) 134 | self.ui.txtboxMailServer.setText(settings.value("MailServer")) 135 | self.ui.txtboxPort.setText(settings.value("Port")) 136 | self.ui.txtboxLogin.setText(settings.value("Login")) 137 | self.ui.txtboxPassword.setText(settings.value("Password")) 138 | self.ui.boolifSSL.setChecked(bool(settings.value("SSL"))) 139 | settings.endGroup() 140 | if (self.ui.comboAccounts.count() == 0): 141 | self.ui.comboAccounts.addItem("Default") 142 | self.ui.comboAccounts.setCurrentText("Default") 143 | self.ui.checkFreq.setValue(int(settings.value("CheckInterval"))) 144 | self.ui.boolifNotify.setChecked(bool(settings.value("Notify"))) 145 | 146 | def SettingsSave(self,account): 147 | settings.setValue("CheckInterval",self.ui.checkFreq.value()) 148 | settings.setValue("Notify", self.ui.boolifNotify.isChecked()) 149 | settings.beginGroup(account) 150 | settings.setValue("MailServer",self.ui.txtboxMailServer.text()) 151 | settings.setValue("Port",self.ui.txtboxPort.text()) 152 | settings.setValue("Login",self.ui.txtboxLogin.text()) 153 | settings.setValue("Password",self.ui.txtboxPassword.text()) 154 | settings.setValue("SSL",self.ui.boolifSSL.isChecked()) 155 | settings.endGroup() 156 | 157 | def SettingsRemove(self,group): 158 | settings.beginGroup(group) 159 | settings.remove("") 160 | settings.endGroup() 161 | 162 | def btnOK_clicked(self): 163 | self.SettingsSave(self.ui.comboAccounts.currentText()) 164 | 165 | if (settings.value("MailServer") == "" or settings.value("Port") == "" or settings.value("Login") == "" or settings.value("Password") == ""): 166 | QMessageBox.critical(self, "Warning","You should fill all fields in IMAP settings!") 167 | self.show() 168 | mail_check() 169 | self.ui.lblTestOutput.setText("") 170 | self.stop() 171 | self.start() 172 | 173 | def btnCancel_clicked(self): 174 | self.SettingsRestore() 175 | self.ui.lblTestOutput.setText("") 176 | 177 | def btnTestConnection_clicked(self): 178 | try: 179 | if self.ui.boolifSSL.isChecked: 180 | self.imap = imaplib.IMAP4_SSL(self.ui.txtboxMailServer.text(), self.ui.txtboxPort.text()) 181 | else: 182 | self.imap = imaplib.IMAP4(self.ui.txtboxMailServer.text(), self.ui.txtboxPort.text()) 183 | self.imap.login(self.ui.txtboxLogin.text(), self.ui.txtboxPassword.text()) 184 | output = "Connection was established successfully" 185 | except: 186 | output = "Unable to establish connection to mailbox" 187 | finally: 188 | self.ui.lblTestOutput.setText(output) 189 | 190 | def btnAddAccount_clicked(self): 191 | GroupName = QInputDialog.getText(self,"Enter account name","Enter account name",QLineEdit.Normal,"") 192 | if (GroupName[0]): 193 | self.ui.comboAccounts.addItem(GroupName[0]) 194 | self.ui.comboAccounts.setCurrentText(GroupName[0]) 195 | 196 | def btnRenameAccount_clicked(self): 197 | Index = self.ui.comboAccounts.currentIndex() 198 | OldGroupName = self.ui.comboAccounts.currentText() 199 | GroupName = QInputDialog.getText(self,"Enter account name","Enter account name",QLineEdit.Normal,self.ui.comboAccounts.currentText()) 200 | if (GroupName[0]): 201 | self.SettingsSave(GroupName[0]) 202 | self.ui.comboAccounts.setItemText(Index, GroupName[0]) 203 | self.ui.comboAccounts.setCurrentText(GroupName[0]) 204 | self.SettingsRemove(OldGroupName) 205 | 206 | def btnSaveAccount_clicked(self): 207 | self.SettingsSave(self.ui.comboAccounts.currentText()) 208 | self.ui.lblTestOutput.setText("Account saved") 209 | 210 | def btnRemoveAccount_clicked(self): 211 | reply = QMessageBox.warning(self, 'Warning!', "Delete this account permanently?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) 212 | if (reply == QMessageBox.Yes): 213 | Index = self.ui.comboAccounts.currentIndex() 214 | GroupName = self.ui.comboAccounts.currentText() 215 | self.ui.comboAccounts.removeItem(Index) 216 | self.SettingsRemove(GroupName) 217 | # Check if account doesn't exist, it creates default one 218 | if (AccountExist() == False): 219 | self.ui.comboAccounts.addItem("Default") 220 | self.ui.comboAccounts.setCurrentText("Default") 221 | 222 | def comboAccounts_changed(self): 223 | self.ui.lblTestOutput.setText("") 224 | settings.beginGroup(self.ui.comboAccounts.currentText()) 225 | self.ui.txtboxMailServer.setText(settings.value("MailServer")) 226 | self.ui.txtboxPort.setText(settings.value("Port")) 227 | self.ui.txtboxLogin.setText(settings.value("Login")) 228 | self.ui.txtboxPassword.setText(settings.value("Password")) 229 | self.ui.boolifSSL.setChecked(bool(settings.value("SSL"))) 230 | settings.endGroup() 231 | 232 | def aboutShow(self): 233 | if (about.isMinimized): 234 | about.hide() 235 | about.show() 236 | about.activateWindow() 237 | 238 | def detailsShow(self): 239 | details.show() 240 | details.activateWindow() 241 | 242 | def trayIconActivated(self, reason): 243 | if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick): 244 | details.show() 245 | details.activateWindow() 246 | 247 | def start(self): 248 | if (GlobalSettingsExist() and AccountExist()): 249 | CheckInterval = 1000*60*int(settings.value("CheckInterval")) 250 | else: 251 | CheckInterval = 1000*60*5 252 | self.timer.setInterval (CheckInterval) 253 | self.timer.start() 254 | 255 | def stop (self): 256 | self.timer.stop() 257 | 258 | class About(QDialog): 259 | def __init__(self): 260 | super(About, self).__init__() 261 | 262 | self.ui = Ui_about() 263 | self.ui.setupUi(self) 264 | self.setWindowFlags(QtCore.Qt.Tool) 265 | self.setFixedSize(511,334) 266 | 267 | self.ui.lblNameVersion.setText(programTitle + " " + programVersion) 268 | 269 | f = QtCore.QFile(":/LICENSE.txt") 270 | if f.open(QtCore.QIODevice.ReadOnly | QtCore.QFile.Text): 271 | text = QtCore.QTextStream(f).readAll() 272 | f.close() 273 | self.ui.txtLicense.setPlainText(text) 274 | 275 | def closeEvent(self, event): 276 | event.ignore() 277 | self.hide() 278 | 279 | class Details(QDialog): 280 | def __init__(self): 281 | super(Details, self).__init__() 282 | 283 | self.ui = Ui_Details() 284 | self.ui.setupUi(self) 285 | self.setWindowFlags(QtCore.Qt.Window) 286 | self.ui.btnRefresh.clicked.connect(self.Refresh_clicked) 287 | if (settings.contains("Details_width") and settings.contains("Details_height")): 288 | width = int(settings.value("Details_width")) 289 | height = int(settings.value("Details_height")) 290 | self.resize(width,height) 291 | 292 | def closeEvent(self, event): 293 | event.ignore() 294 | settings.setValue("Details_width",self.width()) 295 | settings.setValue("Details_height",self.height()) 296 | self.hide() 297 | 298 | def Refresh_clicked(self): 299 | mail_check() 300 | 301 | # Common functions 302 | 303 | class Mail(): 304 | def __init__(self): 305 | socket.setdefaulttimeout(5) 306 | 307 | def login(self,mailserver,port,user,password,ssl): 308 | try: 309 | if ssl: 310 | self.imap = imaplib.IMAP4_SSL(mailserver, port) 311 | 312 | else: 313 | self.imap = imaplib.IMAP4(mailserver, port) 314 | self.imap.login(user, password) 315 | return True 316 | except: 317 | print("Login error") 318 | return False 319 | 320 | def checkMail(self): 321 | try: 322 | self.imap.select() 323 | self.unRead = self.imap.search(None, 'UNSEEN') 324 | return len(self.unRead[1][0].split()) 325 | except: 326 | print("Unable to check mail") 327 | return "ERROR" 328 | def parseMail(self,header): 329 | try: 330 | output=[] 331 | self.imap.select(readonly=True) 332 | typ, data = self.imap.search(None, 'UNSEEN') 333 | for num in data[0].split(): 334 | typ, data = self.imap.fetch(num, '(RFC822)') 335 | raw_mail = data[0][1] 336 | mail=email.message_from_bytes(raw_mail) 337 | h=email.header.decode_header(mail.get(header)) 338 | if (h[0][1] != "unknown-8bit"): 339 | msg = h[0][0].decode(h[0][1]) if h[0][1] else h[0][0] 340 | else: 341 | msg = "Unknown charset" 342 | output.append(msg) 343 | return output 344 | except: 345 | print("Unable to get mail data") 346 | return "ERROR" 347 | 348 | def mail_check(): 349 | details.ui.statusBar.setText(datetime.strftime(datetime.now(), "%d.%m.%Y %H:%M:%S")+" - Starting mail check") 350 | mail_count = 0 351 | AllFroms=[] 352 | AllSubjs=[] 353 | AllDates=[] 354 | details.ui.tableWidget.clearContents() 355 | details.ui.tableWidget.setRowCount(0) 356 | details.ui.tableWidget.setColumnCount(0) 357 | if (GlobalSettingsExist() and AccountExist()): 358 | m = Mail() 359 | groups = settings.childGroups() 360 | for i in range (len(groups)): 361 | settings.beginGroup(groups[i]) 362 | group = groups[i] 363 | user = settings.value("Login") 364 | password = settings.value("Password") 365 | mailserver = settings.value("MailServer") 366 | port = settings.value("Port") 367 | ssl = settings.value("SSL") 368 | settings.endGroup() 369 | if m.login(mailserver,port,user,password,ssl): 370 | if (mail_count == "ERROR" or m.checkMail() == "ERROR"): 371 | mail_count = "ERROR" 372 | else: 373 | mail_count += m.checkMail() 374 | AllFroms.extend(m.parseMail("From")) 375 | AllSubjs.extend(m.parseMail("Subject")) 376 | AllDates.extend(m.parseMail("Date")) 377 | else: 378 | mail_count = "CONNECTION_ERROR" 379 | else: 380 | mail_count = "CONFIGURATION_ERROR" 381 | 382 | # Parsing mail_count values 383 | 384 | if mail_count == 0: 385 | # When mailbox have not unread letters 386 | window.trayIcon.setToolTip ("You have no unread mail") 387 | # Draw text on icon 388 | pixmap = QtGui.QPixmap(QtGui.QPixmap(":icons/mailbox_empty.png")) 389 | painter = QtGui.QPainter(pixmap) 390 | painter.setPen(QtGui.QColor(255, 0, 0)) 391 | painter.setFont(QtGui.QFont('Arial', 100,QtGui.QFont.Bold)) 392 | painter.drawText(QtCore.QRectF(pixmap.rect()), QtCore.Qt.AlignCenter, "0") 393 | painter.end() 394 | # End drawing text on icon 395 | window.trayIcon.setIcon(QtGui.QIcon(pixmap)) 396 | details.ui.statusBar.setText(datetime.strftime(datetime.now(), "%d.%m.%Y %H:%M:%S")+" - Mail check completed. You have no unread letters") 397 | elif mail_count == "ERROR": 398 | window.trayIcon.setIcon(QIcon(":icons/mailbox_error.png")) 399 | window.trayIcon.setToolTip ("Error checking mail.") 400 | details.ui.statusBar.setText(datetime.strftime(datetime.now(), "%d.%m.%Y %H:%M:%S")+" - Error checking mail") 401 | elif mail_count == "CONNECTION_ERROR": 402 | window.trayIcon.setToolTip("Unable to establish connection to mailbox. Check your mail settings and make sure that you have not network problems.") 403 | notify("Unable to establish connection to mailbox. Check your mail settings and make sure that you have not network problems.") 404 | window.trayIcon.setIcon(QIcon(":icons/mailbox_error.png")) 405 | details.ui.statusBar.setText(datetime.strftime(datetime.now(), "%d.%m.%Y %H:%M:%S")+" - Unable to establish connection to mailbox. Check your mail settings and make sure that you have not network problems") 406 | elif mail_count == "CONFIGURATION_ERROR": 407 | window.trayIcon.setIcon(QIcon(":icons/mailbox_error.png")) 408 | window.trayIcon.setToolTip("Cannot find configuration file. You should give access to your mailbox") 409 | details.ui.statusBar.setText(datetime.strftime(datetime.now(), "%d.%m.%Y %H:%M:%S")+" - Cannot find configuration file. You should give access to your mailbox") 410 | else: 411 | # When mailbox has unread letters 412 | window.trayIcon.setToolTip ("You have "+ str(mail_count)+" unread letters") 413 | # Draw text on icon 414 | pixmap = QtGui.QPixmap(QtGui.QPixmap(":icons/mailbox_full.png")) 415 | painter = QtGui.QPainter(pixmap) 416 | painter.setPen(QtGui.QColor(255, 255, 255)) 417 | painter.setFont(QtGui.QFont('Arial', 100,QtGui.QFont.Bold)) 418 | painter.drawText(QtCore.QRectF(pixmap.rect()), QtCore.Qt.AlignCenter, str(mail_count)) 419 | painter.end() 420 | # End drawing text on icon 421 | window.trayIcon.setIcon(QtGui.QIcon(pixmap)) 422 | # Popup notification appears only if mail count changed since last check 423 | if (mail_count != window.lastCheckCount): 424 | notify ("You have "+ str(mail_count) +" unread letters") 425 | 426 | # Filling table 427 | data = {"From":AllFroms, 428 | "Subject":AllSubjs, 429 | "Date":AllDates,} 430 | details.ui.tableWidget.setRowCount(len(AllFroms)) 431 | details.ui.tableWidget.setColumnCount(3) 432 | #Enter data onto Table 433 | try: 434 | horHeaders = [] 435 | for n, key in enumerate(sorted(data.keys())): 436 | #print(data.keys()) 437 | horHeaders.append(key) 438 | for m, item in enumerate(data[key]): 439 | newitem = QtWidgets.QTableWidgetItem(item) 440 | details.ui.tableWidget.setItem(m, n, newitem) 441 | except: 442 | print("Unable to load some data") 443 | pass 444 | 445 | #Add Header 446 | details.ui.tableWidget.setHorizontalHeaderLabels(horHeaders) 447 | 448 | #Adjust size of Table 449 | details.ui.tableWidget.resizeColumnsToContents() 450 | details.ui.tableWidget.resizeRowsToContents() 451 | details.ui.statusBar.setText(datetime.strftime(datetime.now(), "%d.%m.%Y %H:%M:%S")+" - Mail check completed. You have "+ str(mail_count) +" unread letters") 452 | # check was successfull, lastCheckCount is updating 453 | window.lastCheckCount = mail_count 454 | def notify(message): 455 | try: 456 | if settings.value("Notify"): 457 | subprocess.Popen(['notify-send', programTitle, message]) 458 | return 459 | except: 460 | print(message) 461 | 462 | 463 | 464 | if __name__ == '__main__': 465 | import sys 466 | app = QApplication(sys.argv) 467 | systemtray_timeout = 0 468 | # Check if DE supports system tray 469 | while not QSystemTrayIcon.isSystemTrayAvailable(): 470 | systemtray_timeout += 1 471 | time.sleep (20) 472 | if systemtray_timeout == 5: 473 | QMessageBox.critical(None, "Mail notifier", 474 | "I couldn't detect any system tray on this system.") 475 | sys.exit(1) 476 | QApplication.setQuitOnLastWindowClosed(False) 477 | window = Window() 478 | about = About() 479 | details = Details() 480 | if (GlobalSettingsExist() and AccountExist()): 481 | window.hide() 482 | else: 483 | window.show() 484 | # UI started. Starting required functions after UI start 485 | mail_check() 486 | window.start() 487 | sys.exit(app.exec_()) 488 | -------------------------------------------------------------------------------- /resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/details.png 4 | LICENSE.txt 5 | icons/save_account.png 6 | icons/mailbox_empty.png 7 | icons/mailbox_full.png 8 | icons/mailbox_error.png 9 | icons/menu_quit.png 10 | icons/check_now.png 11 | icons/settings.png 12 | icons/add_account.png 13 | icons/remove_account.png 14 | icons/rename_account.png 15 | 16 | 17 | -------------------------------------------------------------------------------- /screenshots/details-3.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/screenshots/details-3.0.jpg -------------------------------------------------------------------------------- /screenshots/no_unread_mails-3.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/screenshots/no_unread_mails-3.0.jpg -------------------------------------------------------------------------------- /screenshots/screen1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/screenshots/screen1.jpg -------------------------------------------------------------------------------- /screenshots/screen2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/screenshots/screen2.jpg -------------------------------------------------------------------------------- /screenshots/screen3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/screenshots/screen3.jpg -------------------------------------------------------------------------------- /screenshots/unread_mails-3.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rinaldus/mail-notifier/f13eae9907c86a39f9782ca5793765e4f29abd03/screenshots/unread_mails-3.0.jpg -------------------------------------------------------------------------------- /ui/about.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | about 4 | 5 | 6 | 7 | 0 8 | 0 9 | 511 10 | 334 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Mail Notifier 21 | 22 | 23 | 24 | :/icons/mailbox_empty.png:/icons/mailbox_empty.png 25 | 26 | 27 | 28 | 29 | 50 30 | 120 31 | 381 32 | 201 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 50 43 | 0 44 | 131 45 | 111 46 | 47 | 48 | 49 | 50 | 51 | 52 | :/icons/mailbox_empty.png 53 | 54 | 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 200 62 | 40 63 | 291 64 | 31 65 | 66 | 67 | 68 | 69 | 203 70 | 0 71 | 72 | 73 | 74 | 75 | 20 76 | 75 77 | true 78 | 79 | 80 | 81 | Mail Notifier 82 | 83 | 84 | true 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /ui/details.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Details 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1048 10 | 619 11 | 12 | 13 | 14 | Mail Notifier 15 | 16 | 17 | 18 | :/icons/mailbox_empty.png:/icons/mailbox_empty.png 19 | 20 | 21 | 22 | 23 | 24 | 25 | 0 26 | 0 27 | 28 | 29 | 30 | Refresh 31 | 32 | 33 | 34 | :/icons/check_now.png:/icons/check_now.png 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 0 50 | 0 51 | 52 | 53 | 54 | 55 | 0 56 | 0 57 | 58 | 59 | 60 | 61 | 0 62 | 0 63 | 64 | 65 | 66 | QFrame::StyledPanel 67 | 68 | 69 | QFrame::Sunken 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /ui/settings.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Settings 4 | 5 | 6 | 7 | 0 8 | 0 9 | 586 10 | 332 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Mail Notifier - Settings 21 | 22 | 23 | 24 | ../icons/mailbox_empty.png../icons/mailbox_empty.png 25 | 26 | 27 | 28 | 29 | 20 30 | 290 31 | 341 32 | 32 33 | 34 | 35 | 36 | Qt::Horizontal 37 | 38 | 39 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 40 | 41 | 42 | 43 | 44 | 45 | 21 46 | 42 47 | 231 48 | 20 49 | 50 | 51 | 52 | Use also pop-up notification 53 | 54 | 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 20 62 | 120 63 | 541 64 | 161 65 | 66 | 67 | 68 | 69 | 0 70 | 0 71 | 72 | 73 | 74 | IMAP settings 75 | 76 | 77 | 78 | 79 | 90 80 | 30 81 | 181 82 | 22 83 | 84 | 85 | 86 | 87 | 0 88 | 0 89 | 90 | 91 | 92 | 93 | 94 | 95 | mail.example.com 96 | 97 | 98 | 99 | 100 | 101 | 310 102 | 30 103 | 31 104 | 21 105 | 106 | 107 | 108 | Port 109 | 110 | 111 | 112 | 113 | 114 | 40 115 | 60 116 | 41 117 | 21 118 | 119 | 120 | 121 | Login 122 | 123 | 124 | 125 | 126 | 127 | 280 128 | 60 129 | 61 130 | 21 131 | 132 | 133 | 134 | Password 135 | 136 | 137 | 138 | 139 | 140 | 350 141 | 60 142 | 181 143 | 22 144 | 145 | 146 | 147 | 148 | 149 | 150 | QLineEdit::Password 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 90 160 | 60 161 | 181 162 | 22 163 | 164 | 165 | 166 | 167 | 168 | 169 | name@example.com 170 | 171 | 172 | 173 | 174 | 175 | 11 176 | 31 177 | 71 178 | 21 179 | 180 | 181 | 182 | Mail server 183 | 184 | 185 | 186 | 187 | 188 | 350 189 | 30 190 | 41 191 | 22 192 | 193 | 194 | 195 | 196 | 0 197 | 0 198 | 199 | 200 | 201 | 202 | 203 | 204 | 143 205 | 206 | 207 | 208 | 209 | 210 | 10 211 | 90 212 | 161 213 | 20 214 | 215 | 216 | 217 | Use SSL connection 218 | 219 | 220 | 221 | 222 | true 223 | 224 | 225 | 226 | 10 227 | 120 228 | 121 229 | 22 230 | 231 | 232 | 233 | 234 | 235 | 236 | Test connection 237 | 238 | 239 | 240 | 241 | 242 | 150 243 | 120 244 | 371 245 | 21 246 | 247 | 248 | 249 | 250 | 251 | 252 | txtboxPort 253 | txtboxMailServer 254 | label_4 255 | label_3 256 | label_5 257 | label_6 258 | txtboxPassword 259 | txtboxLogin 260 | boolifSSL 261 | btnTestConnection 262 | lblTestOutput 263 | 264 | 265 | 266 | 267 | 20 268 | 20 269 | 181 270 | 16 271 | 272 | 273 | 274 | Check for unread mail every 275 | 276 | 277 | 278 | 279 | 280 | 200 281 | 15 282 | 52 283 | 23 284 | 285 | 286 | 287 | 1 288 | 289 | 290 | 120 291 | 292 | 293 | 15 294 | 295 | 296 | 297 | 298 | 299 | 260 300 | 20 301 | 61 302 | 16 303 | 304 | 305 | 306 | minutes 307 | 308 | 309 | 310 | 311 | 312 | 20 313 | 80 314 | 151 315 | 23 316 | 317 | 318 | 319 | QComboBox::InsertAtCurrent 320 | 321 | 322 | 323 | 324 | 325 | 180 326 | 80 327 | 31 328 | 23 329 | 330 | 331 | 332 | Add account 333 | 334 | 335 | 336 | 337 | 338 | 339 | :/icons/add_account.png 340 | 341 | 342 | 343 | 344 | 345 | 346 | 220 347 | 80 348 | 31 349 | 23 350 | 351 | 352 | 353 | Rename account 354 | 355 | 356 | 357 | 358 | 359 | 360 | :/icons/rename_account.png 361 | 362 | 363 | 364 | 365 | 366 | 367 | 300 368 | 80 369 | 31 370 | 23 371 | 372 | 373 | 374 | Remove account 375 | 376 | 377 | 378 | 379 | 380 | 381 | :/icons/remove_account.png 382 | 383 | 384 | 385 | 386 | 387 | 388 | 260 389 | 80 390 | 31 391 | 23 392 | 393 | 394 | 395 | Save account 396 | 397 | 398 | 399 | 400 | 401 | 402 | :/icons/save_account.png 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | buttonBox 413 | accepted() 414 | Settings 415 | accept() 416 | 417 | 418 | 248 419 | 254 420 | 421 | 422 | 157 423 | 274 424 | 425 | 426 | 427 | 428 | buttonBox 429 | rejected() 430 | Settings 431 | reject() 432 | 433 | 434 | 316 435 | 260 436 | 437 | 438 | 286 439 | 274 440 | 441 | 442 | 443 | 444 | 445 | -------------------------------------------------------------------------------- /ui_about.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/about.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.8.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_about(object): 12 | def setupUi(self, about): 13 | about.setObjectName("about") 14 | about.resize(511, 334) 15 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 16 | sizePolicy.setHorizontalStretch(0) 17 | sizePolicy.setVerticalStretch(0) 18 | sizePolicy.setHeightForWidth(about.sizePolicy().hasHeightForWidth()) 19 | about.setSizePolicy(sizePolicy) 20 | icon = QtGui.QIcon() 21 | icon.addPixmap(QtGui.QPixmap(":/icons/mailbox_empty.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 22 | about.setWindowIcon(icon) 23 | self.txtLicense = QtWidgets.QPlainTextEdit(about) 24 | self.txtLicense.setGeometry(QtCore.QRect(50, 120, 381, 201)) 25 | self.txtLicense.setPlainText("") 26 | self.txtLicense.setObjectName("txtLicense") 27 | self.lblLogo = QtWidgets.QLabel(about) 28 | self.lblLogo.setGeometry(QtCore.QRect(50, 0, 131, 111)) 29 | self.lblLogo.setText("") 30 | self.lblLogo.setPixmap(QtGui.QPixmap(":/icons/mailbox_empty.png")) 31 | self.lblLogo.setScaledContents(True) 32 | self.lblLogo.setObjectName("lblLogo") 33 | self.lblNameVersion = QtWidgets.QLabel(about) 34 | self.lblNameVersion.setGeometry(QtCore.QRect(200, 40, 291, 31)) 35 | self.lblNameVersion.setMinimumSize(QtCore.QSize(203, 0)) 36 | font = QtGui.QFont() 37 | font.setPointSize(20) 38 | font.setBold(True) 39 | font.setWeight(75) 40 | self.lblNameVersion.setFont(font) 41 | self.lblNameVersion.setScaledContents(True) 42 | self.lblNameVersion.setObjectName("lblNameVersion") 43 | 44 | self.retranslateUi(about) 45 | QtCore.QMetaObject.connectSlotsByName(about) 46 | 47 | def retranslateUi(self, about): 48 | _translate = QtCore.QCoreApplication.translate 49 | about.setWindowTitle(_translate("about", "Mail Notifier")) 50 | self.lblNameVersion.setText(_translate("about", "Mail Notifier")) 51 | 52 | import resources_rc 53 | -------------------------------------------------------------------------------- /ui_details.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/details.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.6.1.dev1604271126 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_Details(object): 12 | def setupUi(self, Details): 13 | Details.setObjectName("Details") 14 | Details.resize(1048, 619) 15 | icon = QtGui.QIcon() 16 | icon.addPixmap(QtGui.QPixmap(":/icons/mailbox_empty.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 17 | Details.setWindowIcon(icon) 18 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(Details) 19 | self.verticalLayout_2.setObjectName("verticalLayout_2") 20 | self.btnRefresh = QtWidgets.QPushButton(Details) 21 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 22 | sizePolicy.setHorizontalStretch(0) 23 | sizePolicy.setVerticalStretch(0) 24 | sizePolicy.setHeightForWidth(self.btnRefresh.sizePolicy().hasHeightForWidth()) 25 | self.btnRefresh.setSizePolicy(sizePolicy) 26 | icon1 = QtGui.QIcon() 27 | icon1.addPixmap(QtGui.QPixmap(":/icons/check_now.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 28 | self.btnRefresh.setIcon(icon1) 29 | self.btnRefresh.setObjectName("btnRefresh") 30 | self.verticalLayout_2.addWidget(self.btnRefresh) 31 | self.horizontalLayout = QtWidgets.QHBoxLayout() 32 | self.horizontalLayout.setObjectName("horizontalLayout") 33 | self.tableWidget = QtWidgets.QTableWidget(Details) 34 | self.tableWidget.setObjectName("tableWidget") 35 | self.tableWidget.setColumnCount(0) 36 | self.tableWidget.setRowCount(0) 37 | self.horizontalLayout.addWidget(self.tableWidget) 38 | self.verticalLayout_2.addLayout(self.horizontalLayout) 39 | self.statusBar = QtWidgets.QLabel(Details) 40 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 41 | sizePolicy.setHorizontalStretch(0) 42 | sizePolicy.setVerticalStretch(0) 43 | sizePolicy.setHeightForWidth(self.statusBar.sizePolicy().hasHeightForWidth()) 44 | self.statusBar.setSizePolicy(sizePolicy) 45 | self.statusBar.setMinimumSize(QtCore.QSize(0, 0)) 46 | self.statusBar.setBaseSize(QtCore.QSize(0, 0)) 47 | self.statusBar.setFrameShape(QtWidgets.QFrame.StyledPanel) 48 | self.statusBar.setFrameShadow(QtWidgets.QFrame.Sunken) 49 | self.statusBar.setText("") 50 | self.statusBar.setObjectName("statusBar") 51 | self.verticalLayout_2.addWidget(self.statusBar) 52 | 53 | self.retranslateUi(Details) 54 | QtCore.QMetaObject.connectSlotsByName(Details) 55 | 56 | def retranslateUi(self, Details): 57 | _translate = QtCore.QCoreApplication.translate 58 | Details.setWindowTitle(_translate("Details", "Mail Notifier")) 59 | self.btnRefresh.setText(_translate("Details", "Refresh")) 60 | 61 | import resources_rc 62 | -------------------------------------------------------------------------------- /ui_settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/settings.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.5.1 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_Settings(object): 12 | def setupUi(self, Settings): 13 | Settings.setObjectName("Settings") 14 | Settings.resize(586, 332) 15 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 16 | sizePolicy.setHorizontalStretch(0) 17 | sizePolicy.setVerticalStretch(0) 18 | sizePolicy.setHeightForWidth(Settings.sizePolicy().hasHeightForWidth()) 19 | Settings.setSizePolicy(sizePolicy) 20 | icon = QtGui.QIcon() 21 | icon.addPixmap(QtGui.QPixmap("../icons/mailbox_empty.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 22 | Settings.setWindowIcon(icon) 23 | self.buttonBox = QtWidgets.QDialogButtonBox(Settings) 24 | self.buttonBox.setGeometry(QtCore.QRect(20, 290, 341, 32)) 25 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 26 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 27 | self.buttonBox.setObjectName("buttonBox") 28 | self.boolifNotify = QtWidgets.QCheckBox(Settings) 29 | self.boolifNotify.setGeometry(QtCore.QRect(21, 42, 231, 20)) 30 | self.boolifNotify.setChecked(True) 31 | self.boolifNotify.setObjectName("boolifNotify") 32 | self.groupBox = QtWidgets.QGroupBox(Settings) 33 | self.groupBox.setGeometry(QtCore.QRect(20, 120, 541, 161)) 34 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) 35 | sizePolicy.setHorizontalStretch(0) 36 | sizePolicy.setVerticalStretch(0) 37 | sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth()) 38 | self.groupBox.setSizePolicy(sizePolicy) 39 | self.groupBox.setObjectName("groupBox") 40 | self.txtboxMailServer = QtWidgets.QLineEdit(self.groupBox) 41 | self.txtboxMailServer.setGeometry(QtCore.QRect(90, 30, 181, 22)) 42 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) 43 | sizePolicy.setHorizontalStretch(0) 44 | sizePolicy.setVerticalStretch(0) 45 | sizePolicy.setHeightForWidth(self.txtboxMailServer.sizePolicy().hasHeightForWidth()) 46 | self.txtboxMailServer.setSizePolicy(sizePolicy) 47 | self.txtboxMailServer.setText("") 48 | self.txtboxMailServer.setObjectName("txtboxMailServer") 49 | self.label_4 = QtWidgets.QLabel(self.groupBox) 50 | self.label_4.setGeometry(QtCore.QRect(310, 30, 31, 21)) 51 | self.label_4.setObjectName("label_4") 52 | self.label_5 = QtWidgets.QLabel(self.groupBox) 53 | self.label_5.setGeometry(QtCore.QRect(40, 60, 41, 21)) 54 | self.label_5.setObjectName("label_5") 55 | self.label_6 = QtWidgets.QLabel(self.groupBox) 56 | self.label_6.setGeometry(QtCore.QRect(280, 60, 61, 21)) 57 | self.label_6.setObjectName("label_6") 58 | self.txtboxPassword = QtWidgets.QLineEdit(self.groupBox) 59 | self.txtboxPassword.setGeometry(QtCore.QRect(350, 60, 181, 22)) 60 | self.txtboxPassword.setText("") 61 | self.txtboxPassword.setEchoMode(QtWidgets.QLineEdit.Password) 62 | self.txtboxPassword.setPlaceholderText("") 63 | self.txtboxPassword.setObjectName("txtboxPassword") 64 | self.txtboxLogin = QtWidgets.QLineEdit(self.groupBox) 65 | self.txtboxLogin.setGeometry(QtCore.QRect(90, 60, 181, 22)) 66 | self.txtboxLogin.setText("") 67 | self.txtboxLogin.setObjectName("txtboxLogin") 68 | self.label_3 = QtWidgets.QLabel(self.groupBox) 69 | self.label_3.setGeometry(QtCore.QRect(11, 31, 71, 21)) 70 | self.label_3.setObjectName("label_3") 71 | self.txtboxPort = QtWidgets.QLineEdit(self.groupBox) 72 | self.txtboxPort.setGeometry(QtCore.QRect(350, 30, 41, 22)) 73 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 74 | sizePolicy.setHorizontalStretch(0) 75 | sizePolicy.setVerticalStretch(0) 76 | sizePolicy.setHeightForWidth(self.txtboxPort.sizePolicy().hasHeightForWidth()) 77 | self.txtboxPort.setSizePolicy(sizePolicy) 78 | self.txtboxPort.setText("") 79 | self.txtboxPort.setObjectName("txtboxPort") 80 | self.boolifSSL = QtWidgets.QCheckBox(self.groupBox) 81 | self.boolifSSL.setGeometry(QtCore.QRect(10, 90, 161, 20)) 82 | self.boolifSSL.setObjectName("boolifSSL") 83 | self.btnTestConnection = QtWidgets.QPushButton(self.groupBox) 84 | self.btnTestConnection.setEnabled(True) 85 | self.btnTestConnection.setGeometry(QtCore.QRect(10, 120, 121, 22)) 86 | self.btnTestConnection.setToolTip("") 87 | self.btnTestConnection.setObjectName("btnTestConnection") 88 | self.lblTestOutput = QtWidgets.QLabel(self.groupBox) 89 | self.lblTestOutput.setGeometry(QtCore.QRect(150, 120, 371, 21)) 90 | self.lblTestOutput.setText("") 91 | self.lblTestOutput.setObjectName("lblTestOutput") 92 | self.txtboxPort.raise_() 93 | self.txtboxMailServer.raise_() 94 | self.label_4.raise_() 95 | self.label_3.raise_() 96 | self.label_5.raise_() 97 | self.label_6.raise_() 98 | self.txtboxPassword.raise_() 99 | self.txtboxLogin.raise_() 100 | self.boolifSSL.raise_() 101 | self.btnTestConnection.raise_() 102 | self.lblTestOutput.raise_() 103 | self.label = QtWidgets.QLabel(Settings) 104 | self.label.setGeometry(QtCore.QRect(20, 20, 181, 16)) 105 | self.label.setObjectName("label") 106 | self.checkFreq = QtWidgets.QSpinBox(Settings) 107 | self.checkFreq.setGeometry(QtCore.QRect(200, 15, 52, 23)) 108 | self.checkFreq.setMinimum(1) 109 | self.checkFreq.setMaximum(120) 110 | self.checkFreq.setProperty("value", 15) 111 | self.checkFreq.setObjectName("checkFreq") 112 | self.label_2 = QtWidgets.QLabel(Settings) 113 | self.label_2.setGeometry(QtCore.QRect(260, 20, 61, 16)) 114 | self.label_2.setObjectName("label_2") 115 | self.comboAccounts = QtWidgets.QComboBox(Settings) 116 | self.comboAccounts.setGeometry(QtCore.QRect(20, 80, 151, 23)) 117 | self.comboAccounts.setInsertPolicy(QtWidgets.QComboBox.InsertAtCurrent) 118 | self.comboAccounts.setObjectName("comboAccounts") 119 | self.btnAddAccount = QtWidgets.QPushButton(Settings) 120 | self.btnAddAccount.setGeometry(QtCore.QRect(180, 80, 31, 23)) 121 | self.btnAddAccount.setText("") 122 | icon1 = QtGui.QIcon() 123 | icon1.addPixmap(QtGui.QPixmap(":/icons/add_account.png"), QtGui.QIcon.Normal, QtGui.QIcon.On) 124 | self.btnAddAccount.setIcon(icon1) 125 | self.btnAddAccount.setObjectName("btnAddAccount") 126 | self.btnRenameAccount = QtWidgets.QPushButton(Settings) 127 | self.btnRenameAccount.setGeometry(QtCore.QRect(220, 80, 31, 23)) 128 | self.btnRenameAccount.setText("") 129 | icon2 = QtGui.QIcon() 130 | icon2.addPixmap(QtGui.QPixmap(":/icons/rename_account.png"), QtGui.QIcon.Normal, QtGui.QIcon.On) 131 | self.btnRenameAccount.setIcon(icon2) 132 | self.btnRenameAccount.setObjectName("btnRenameAccount") 133 | self.btnRemoveAccount = QtWidgets.QPushButton(Settings) 134 | self.btnRemoveAccount.setGeometry(QtCore.QRect(300, 80, 31, 23)) 135 | self.btnRemoveAccount.setText("") 136 | icon3 = QtGui.QIcon() 137 | icon3.addPixmap(QtGui.QPixmap(":/icons/remove_account.png"), QtGui.QIcon.Normal, QtGui.QIcon.On) 138 | self.btnRemoveAccount.setIcon(icon3) 139 | self.btnRemoveAccount.setObjectName("btnRemoveAccount") 140 | self.btnSaveAccount = QtWidgets.QPushButton(Settings) 141 | self.btnSaveAccount.setGeometry(QtCore.QRect(260, 80, 31, 23)) 142 | self.btnSaveAccount.setText("") 143 | icon4 = QtGui.QIcon() 144 | icon4.addPixmap(QtGui.QPixmap(":/icons/save_account.png"), QtGui.QIcon.Normal, QtGui.QIcon.On) 145 | self.btnSaveAccount.setIcon(icon4) 146 | self.btnSaveAccount.setObjectName("btnSaveAccount") 147 | 148 | self.retranslateUi(Settings) 149 | self.buttonBox.accepted.connect(Settings.accept) 150 | self.buttonBox.rejected.connect(Settings.reject) 151 | QtCore.QMetaObject.connectSlotsByName(Settings) 152 | 153 | def retranslateUi(self, Settings): 154 | _translate = QtCore.QCoreApplication.translate 155 | Settings.setWindowTitle(_translate("Settings", "Mail Notifier - Settings")) 156 | self.boolifNotify.setText(_translate("Settings", "Use also pop-up notification")) 157 | self.groupBox.setTitle(_translate("Settings", "IMAP settings")) 158 | self.txtboxMailServer.setPlaceholderText(_translate("Settings", "mail.example.com")) 159 | self.label_4.setText(_translate("Settings", "Port")) 160 | self.label_5.setText(_translate("Settings", "Login")) 161 | self.label_6.setText(_translate("Settings", "Password")) 162 | self.txtboxLogin.setPlaceholderText(_translate("Settings", "name@example.com")) 163 | self.label_3.setText(_translate("Settings", "Mail server")) 164 | self.txtboxPort.setPlaceholderText(_translate("Settings", "143")) 165 | self.boolifSSL.setText(_translate("Settings", "Use SSL connection")) 166 | self.btnTestConnection.setText(_translate("Settings", "Test connection")) 167 | self.label.setText(_translate("Settings", "Check for unread mail every")) 168 | self.label_2.setText(_translate("Settings", "minutes")) 169 | self.btnAddAccount.setToolTip(_translate("Settings", "Add account")) 170 | self.btnRenameAccount.setToolTip(_translate("Settings", "Rename account")) 171 | self.btnRemoveAccount.setToolTip(_translate("Settings", "Remove account")) 172 | self.btnSaveAccount.setToolTip(_translate("Settings", "Save account")) 173 | 174 | import resources_rc 175 | --------------------------------------------------------------------------------