Ejemplo n.º 1
0
 def ok(event=None):
     with open(os.path.join(LOCAL_PATH, '.pwd')) as fich:
         cryptedpwd = fich.read()
     old = oldpwd.get()
     pwd = newpwd.get()
     pwd2 = confpwd.get()
     if crypt.crypt(old, cryptedpwd) == cryptedpwd:
         # passwords match
         if pwd == pwd2:
             # new passwords match
             cryptedpwd = crypt.crypt(pwd,
                                      crypt.mksalt(crypt.METHOD_SHA512))
             with open(os.path.join(LOCAL_PATH, '.pwd'), "w") as fich:
                 fich.write(cryptedpwd)
             mailboxes = CONFIG.get(
                 "Mailboxes", "active").split(", ") + CONFIG.get(
                     "Mailboxes", "inactive").split(", ")
             while "" in mailboxes:
                 mailboxes.remove("")
             for mailbox in mailboxes:
                 server, login, password, folder = decrypt(mailbox, old)
                 if server is not None:
                     encrypt(mailbox, pwd, server, login, password,
                             folder)
             self.pwd = pwd
             top.destroy()
             logging.info('Password changed')
             return pwd
         else:
             showerror(_('Error'), _('Passwords do not match!'))
     else:
         showerror(_('Error'), _('Incorrect password!'))
Ejemplo n.º 2
0
    def save(self, event=None):
        self.name = name = self.name_entry.get().strip()
        if name != self.mailbox:
            # change name of mailbox
            os.remove(os.path.join(LOCAL_PATH, self.mailbox))

            active = CONFIG.get("Mailboxes", "active").split(", ")
            inactive = CONFIG.get("Mailboxes", "inactive").split(", ")
            while "" in active:
                active.remove("")
            while "" in inactive:
                inactive.remove("")
            if self.mailbox in active:
                active.remove(self.mailbox)
                active.append(name)
            elif self.mailbox in inactive:
                inactive.remove(self.mailbox)
                inactive.append(name)
            CONFIG.set("Mailboxes", "active", ", ".join(active))
            CONFIG.set("Mailboxes", "inactive", ", ".join(inactive))
            save_config()

        encrypt(name, self.pwd, self.server_entry.get().strip(),
                self.login_entry.get().strip(), self.password_entry.get().strip(),
                self.folder_entry.get().strip())

        self.destroy()
Ejemplo n.º 3
0
    def __init__(self, master, pwd):
        """Create the mailbox manager dialog."""
        Toplevel.__init__(self, master, class_="CheckMails")
        self.title(_("Mailbox Manager"))
        self.minsize(200, 10)
        self.pwd = pwd
        self.resizable(False, False)
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self.im_add = PhotoImage(master=self, file=ADD)
        self.im_del = PhotoImage(master=self, file=DEL)
        self.im_edit = PhotoImage(master=self, file=EDIT)
        self.mailboxes = {}
        active = CONFIG.get("Mailboxes", "active").split(", ")
        inactive = CONFIG.get("Mailboxes", "inactive").split(", ")
        while "" in active:
            active.remove("")
        while "" in inactive:
            inactive.remove("")
        active.sort()
        inactive.sort()
        self.frame = Frame(self)
        self.columnconfigure(0, weight=1)
        self.frame.columnconfigure(1, weight=1)
        self.frame.grid(row=0, column=0, padx=10, pady=10, sticky="eswn")
        i = -1
        for i, box in enumerate(active):
            c = Checkbutton(self.frame)
            c.state(('selected',))
            c.grid(row=i, column=0, pady=4, padx=(4, 0))
            l = Label(self.frame, text=box)
            l.grid(row=i, column=1, padx=4, pady=4)
            b_edit = Button(self.frame, image=self.im_edit, width=1,
                            command=lambda m=box: self.mailbox_info(m))
            b_edit.grid(row=i, column=2, padx=4, pady=4)
            b_del = Button(self.frame, image=self.im_del, width=1,
                           command=lambda m=box: self.del_mailbox(m))
            b_del.grid(row=i, column=3, padx=4, pady=4)
            self.mailboxes[box] = [c, l, b_edit, b_del]
        for box in inactive:
            i += 1
            c = Checkbutton(self.frame)
            c.grid(row=i, column=0, pady=4, padx=(4, 0))
            l = Label(self.frame, text=box)
            l.grid(row=i, column=1, padx=4, pady=4)
            b_edit = Button(self.frame, image=self.im_edit, width=1,
                            command=lambda m=box: self.mailbox_info(m))
            b_edit.grid(row=i, column=2, padx=4, pady=4)
            b_del = Button(self.frame, image=self.im_del, width=1,
                           command=lambda m=box: self.del_mailbox(m))
            b_del.grid(row=i, column=3, padx=4, pady=4)
            self.mailboxes[box] = [c, l, b_edit, b_del]

        self.b_add = Button(self.frame, image=self.im_add, command=self.mailbox_info, width=1)
        self.b_add.grid(row=i + 1, column=0, columnspan=4, pady=4, padx=4, sticky='w')
Ejemplo n.º 4
0
 def launch_check(self, force_notify=False):
     """
     Check every 20 s if the login to all the mailboxes is done.
     Once it is the case, launch the unread mail check.
     """
     b = [
         self.threads_connect[box].is_alive()
         for box in self.threads_connect
     ]
     if len(b) < len(self.info_conn) or True in b:
         logging.info("Waiting for connexion ...")
         try:
             self.after_cancel(self.check_id)
         except ValueError:
             pass
         self.check_id = self.after(20000, self.launch_check, force_notify)
     else:
         logging.info("Launching check")
         if not self.login_err_queue.empty():
             correct = False
             while not self.login_err_queue.empty():
                 box = self.login_err_queue.get()
                 action = show_failed_auth_msg(self, box)
                 if action == 'correct':
                     dialog = EditMailbox(self, self.pwd, box)
                     self.wait_window(dialog)
                     self.connect(box)
                     correct = dialog.name or correct
                 else:
                     # remove box from the active mailboxes
                     del (self.boxes[box])
                     active = CONFIG.get("Mailboxes", "active").split(", ")
                     inactive = CONFIG.get("Mailboxes",
                                           "inactive").split(", ")
                     while "" in active:
                         active.remove("")
                     while "" in inactive:
                         inactive.remove("")
                     active.remove(box)
                     inactive.append(box)
                     CONFIG.set("Mailboxes", "active", ", ".join(active))
                     CONFIG.set("Mailboxes", "inactive",
                                ", ".join(inactive))
             if correct:
                 self.after_cancel(self.check_id)
                 self.check_id = self.after(20000, self.launch_check,
                                            force_notify)
             else:
                 self.check_mails(force_notify)
         else:
             self.check_mails(force_notify)
Ejemplo n.º 5
0
 def reset_password(self):
     """
     Reset the master password and delete all the mailboxes config files
     since they cannot be decrypted without the password.
     """
     rep = askokcancel(
         _("Confirmation"),
         _("The reset of the password will erase all the stored mailbox connection information"
           ),
         icon="warning")
     if rep:
         mailboxes = CONFIG.get("Mailboxes",
                                "active").split(", ") + CONFIG.get(
                                    "Mailboxes", "inactive").split(", ")
         while "" in mailboxes:
             mailboxes.remove("")
         CONFIG.set("Mailboxes", "active", "")
         CONFIG.set("Mailboxes", "inactive", "")
         save_config()
         for mailbox in mailboxes:
             os.remove(os.path.join(LOCAL_PATH, mailbox))
         logging.info('Reset')
         self.set_password()
Ejemplo n.º 6
0
 def change_icon(self, nbmail):
     """Display the number of unread mails nbmail in the system tray icon."""
     nb = "%i" % nbmail
     im = Image.open(IMAGE)
     W, H = im.size
     draw = ImageDraw.Draw(im)
     font_path = TTF_FONTS[CONFIG.get("General", "font")]
     try:
         font = ImageFont.truetype(font_path, FONTSIZE)
         w, h = draw.textsize(nb, font=font)
         draw.text(((W - w) / 2, (H - h) / 2),
                   nb,
                   fill=(255, 0, 0),
                   font=font)
     except OSError:
         w, h = draw.textsize(nb)
         draw.text(((W - w) / 2, (H - h) / 2), nb, fill=(255, 0, 0))
     im.save(ICON)
     self.icon.change_icon(ICON, "checkmails %s" % nb)
Ejemplo n.º 7
0
    def get_info_conn(self):
        """
        Retrieve connection information from the encrypted files and
        launch checks (if they are noit suspended).
        """
        mailboxes = CONFIG.get("Mailboxes", "active").split(", ")
        while "" in mailboxes:
            mailboxes.remove("")
        self.info_conn = {}
        if self.pwd is None:
            if not os.path.exists(os.path.join(LOCAL_PATH, ".pwd")):
                self.set_password()
            else:
                self.ask_password()
        if self.pwd is not None:
            for box in mailboxes:
                server, login, password, folder = decrypt(box, self.pwd)
                if server is not None:
                    self.info_conn[box] = (server, (login, password), folder)

        if not self.info_conn:
            self.notif = _("No active mailbox")
            run([
                "notify-send", "-i", IMAGE2,
                _("No active mailbox"),
                _("Use the mailbox manager to configure a mailbox.")
            ])
        elif self.icon.get_item_label(3) == _("Suspend"):
            self.notif = ""
            for box in self.info_conn:
                self.connect(box)
            try:
                self.after_cancel(self.check_id)
            except ValueError:
                pass
            self.check_id = self.after(20000, self.launch_check, False)
Ejemplo n.º 8
0
    def __init__(self, master):
        Toplevel.__init__(self, master, class_="CheckMails")
        self.title(_("Preferences"))

        style = Style(self)
        style.map("TCombobox",
                  fieldbackground=[('readonly', 'white')],
                  selectbackground=[('readonly', 'white')],
                  selectforeground=[('readonly', 'black')],
                  foreground=[('readonly', 'black')])

        # validation of the entries : only numbers are allowed
        self._validate_entry_nb = self.register(self.validate_entry_nb)

        # --- Times
        Label(self,
              text=_("Time between two checks")).grid(row=0, column=0,
                                                      padx=(10, 4), pady=(10, 4),
                                                      sticky="e")
        Label(self, justify="right",
              text=_("Maximum time allowed for login or check\n\
(then the connection is reset)")).grid(row=1, column=0, padx=(10, 4), pady=4, sticky="e")
        self.time_entry = Entry(self, width=5, justify="center",
                                validate="key",
                                validatecommand=(self._validate_entry_nb, "%P"))
        self.time_entry.grid(row=0, column=1, padx=(4, 0), pady=(10, 4))
        self.time_entry.insert(0, "%g" % (CONFIG.getint("General", "time") / 60000))
        self.timeout_entry = Entry(self, width=5, justify="center",
                                   validate="key",
                                   validatecommand=(self._validate_entry_nb, "%P"))
        self.timeout_entry.grid(row=1, column=1, padx=(4, 0), pady=4)
        self.timeout_entry.insert(0, "%g" % (CONFIG.getint("General", "timeout") / 60000))
        Label(self, text="min").grid(row=0, column=2, padx=(0, 10), pady=(10, 4))
        Label(self, text="min").grid(row=1, column=2, padx=(0, 10), pady=4)

        frame = Frame(self)
        frame.grid(row=2, columnspan=3, padx=6, pady=(0, 6))

        # --- Language
        Label(frame, text=_("Language")).grid(row=0, column=0,
                                              padx=8, pady=4, sticky="e")
        lang = {"fr": "Français", "en": "English"}
        self.lang = StringVar(self, lang[CONFIG.get("General", "language")])
        menu_lang = Menu(frame, tearoff=False)
        Menubutton(frame, menu=menu_lang, width=9,
                   textvariable=self.lang).grid(row=0, column=1,
                                                padx=8, pady=4, sticky="w")
        menu_lang.add_radiobutton(label="English", value="English",
                                  variable=self.lang, command=self.translate)
        menu_lang.add_radiobutton(label="Français", value="Français",
                                  variable=self.lang, command=self.translate)
        # --- gui toolkit
        Label(frame,
              text=_("GUI Toolkit for the system tray icon")).grid(row=1, column=0,
                                                                   padx=8, pady=4,
                                                                   sticky="e")
        self.gui = StringVar(self, CONFIG.get("General", "trayicon").capitalize())
        menu_gui = Menu(frame, tearoff=False)
        Menubutton(frame, menu=menu_gui, width=9,
                   textvariable=self.gui).grid(row=1, column=1,
                                               padx=8, pady=4, sticky="w")
        for toolkit, b in TOOLKITS.items():
            if b:
                menu_gui.add_radiobutton(label=toolkit.capitalize(),
                                         value=toolkit.capitalize(),
                                         variable=self.gui,
                                         command=self.change_gui)
        # --- Font
        self.preview_path = tempfile.mktemp(".png", "checkmails_preview")
        w = max([len(f) for f in TTF_FONTS])
        self.fonts = sorted(TTF_FONTS)
        self.font = Combobox(frame, values=self.fonts, width=(w * 2) // 3,
                             exportselection=False, state="readonly")
        current_font = CONFIG.get("General", "font")
        if current_font in self.fonts:
            i = self.fonts.index(current_font)
        else:
            i = 0
        self.font.current(i)
        self.img_prev = PhotoImage(master=self, file=IMAGE)
        Label(frame, text=_("Font")).grid(row=2, column=0,
                                          padx=8, pady=4, sticky="e")
        self.font.grid(row=2, column=1, padx=8, pady=4, sticky="w")
        self.prev = Label(frame, image=self.img_prev)
        self.prev.grid(row=2, column=2, padx=8, pady=4)
        self.update_preview()
        self.font.bind('<<ComboboxSelected>>', self.update_preview)
        self.font.bind_class("ComboboxListbox", '<KeyPress>', self.key_nav)

        # --- Ok/Cancel
        frame_button = Frame(self)
        frame_button.grid(row=3, columnspan=3, padx=6, pady=(0, 6))
        Button(frame_button, text="Ok",
               command=self.ok).grid(row=2, column=0, padx=8, pady=4)
        Button(frame_button, text=_("Cancel"),
               command=self.destroy).grid(row=2, column=1, padx=4, pady=4)
Ejemplo n.º 9
0
    def connect_mailbox(self, box):
        """Connect to the mailbox box and select the folder."""
        try:
            logging.info("Connecting to %s" % box)
            serveur, loginfo, folder = self.info_conn[box]
            # reinitialize the connection if it takes too long
            timeout_id = self.after(self.timeout, self.timed_out, box, False,
                                    True)
            self.boxes[box] = IMAP4_SSL(serveur)
            self.boxes[box].login(*loginfo)
            self.boxes[box].select(folder)
            try:
                self.after_cancel(timeout_id)
            except ValueError:
                pass
            logging.info("Connected to %s" % box)

        except (IMAP4.error, ConnectionResetError, TimeoutError) as e:
            try:
                self.after_cancel(timeout_id)
            except ValueError:
                pass
            if e.args[0] in [
                    b'Invalid login or password', b'Authenticate error',
                    b'Login failed: authentication failure', b'LOGIN failed'
            ]:
                # Identification error
                logging.error("Incorrect login or password for %(mailbox)s" %
                              {"mailbox": box})
                self.login_err_queue.put(box)
            else:
                # try to reconnect
                logging.error('%s: %s' % (box, e))
                self.logout(box, reconnect=True)
        except gaierror as e:
            if e.errno == -2:
                # Either there is No Internet connection or the IMAP server is wrong
                if internet_on():
                    run([
                        "notify-send", "-i", "dialog-error",
                        _("Error"),
                        _("Wrong IMAP server for %(mailbox)s.") % {
                            "mailbox": box
                        }
                    ])
                    # remove box from the active mailboxes
                    active = CONFIG.get("Mailboxes", "active").split(", ")
                    inactive = CONFIG.get("Mailboxes", "inactive").split(", ")
                    while "" in active:
                        active.remove("")
                    while "" in inactive:
                        inactive.remove("")
                    active.remove(box)
                    inactive.append(box)
                    CONFIG.set("Mailboxes", "active", ", ".join(active))
                    CONFIG.set("Mailboxes", "inactive", ", ".join(inactive))
                    logging.error("Wrong IMAP server for %(mailbox)s." %
                                  {"mailbox": box})
                else:
                    if self.notify_no_internet:
                        run([
                            "notify-send", "-i", "dialog-error",
                            _("Error"),
                            _("No Internet connection.")
                        ])
                        self.notify_no_internet = False
                    logging.warning("No Internet connection")
                    # cancel everything
                    try:
                        self.after_cancel(self.check_id)
                    except ValueError:
                        pass
                    try:
                        self.after_cancel(self.timer_id)
                    except ValueError:
                        pass
                    try:
                        self.after_cancel(self.notif_id)
                    except ValueError:
                        pass
                    try:
                        self.after_cancel(self.internet_id)
                    except ValueError:
                        pass
                    # periodically checks if the internet connection is turned on
                    self.internet_id = self.after(self.timeout,
                                                  self.test_connection)
            else:
                # try to reconnect
                logging.exception(str(type(e)))
                run([
                    "notify-send", "-i", "dialog-error",
                    _("Error"),
                    traceback.format_exc()
                ])
                self.logout(box, reconnect=True)

        except ValueError:
            # Error sometimes raised when a connection process is interrupted by a logout process
            pass