Пример #1
0
 def sync (self):
     dialog = Dialog_Loading(self)
     dialog.show()
     dialog.message.setText("Retrieving messages ...")
     thr = threading.Thread(target=self.do_sync)
     thr.start()
     while True:
         thr.join(0.1)
         if thr.is_alive():
             QtGui.QApplication.processEvents()
             dialog.repaint()
             dialog.update()
         else:
             dialog.hide()
             break
Пример #2
0
    def accept (self):
        if not self.input_To.text().strip():
            QMessageBox(QMessageBox.Critical, "Error", "You have to specify a recipient.").exec_()
            return

        to = self.input_To.text().strip()
        subject = self.input_Subject.text().strip()
        content = self.editor.getEditorHtml().strip()

        dialog = Dialog_Loading(self)
        dialog.message.setText("Sending e-mail ...")
        dialog.show()
        thr = threading.Thread(target=partial(self.parent.sendbox.send, to, subject, content))
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                dialog.repaint()
                dialog.update()
            else:
                dialog.hide()
                break
        self.close()
Пример #3
0
class MailboxIMAP:

    def __init__ (self, profile):
        self.config = profile['config']['receiver']
        self.connector = None
        self.dialog = Dialog_Loading(self)
        self.dialog.show()
        thr = threading.Thread(target=partial(self.create_connection, profile, self.dialog))
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                self.dialog.repaint()
                self.dialog.update()
            else:
                self.dialog.hide()
                break

    def logout (self):
        if self.connector:
            try:
                print('Closing connection.')
                self.connector.logout()
            except Exception:
                pass
            self.connector = None

    def create_connection (self, profile, dialog):
        imap = imaplib.IMAP4_SSL if self.config['ssl'] else imaplib.IMAP4
        try:
            self.connector = imap(self.config['host'], self.config['port'])
        except Exception:
            pass
        else:
            print("Logging in ...")
            dialog.message.setText("Logging in ...")
            self.connector.login(self.config['username'], self.config['password'])

    def walk_and_decode (self, header, content_type):
        content = ''
        for part in header.walk():
            charset = part.get_content_charset()
            if part.get_content_type() == content_type:
                part_str = part.get_payload(decode=True)
                content += part_str.decode(charset)
        return content

    def fdecode (self, content):
        try:
            tmp = decode_header(content)
            return tmp[0][0].decode(tmp[0][1])
        except Exception:
            return content

    def decode (self, content):
        header = Parser.parsebytes(content)
        content = ''
        try:
            content = self.walk_and_decode(header, 'text/html')
            if not content:
                bootstrap = '<html><head><style>body{background-color:#ffffff;}</style></head><body>%s</body></html>'
                content = self.walk_and_decode(header, 'text/plain')
                content = bootstrap % content.replace('\n', '<br />')
        except Exception:
            return 'Cannot decode message'
        else:
            return content

    def get (self, mailno):
        rv, data = self.connector.fetch(str(mailno), '(RFC822)')
        if rv != 'OK': return None
        header = Parser.parsebytes(data[0][1])
        return self.fdecode(header['From']), self.fdecode(header['Subject']), self.fdecode(header['Date']), self.decode(data[0][1])

    def do_sync (self):
        self.mails = []
        rv, data = self.connector.select('INBOX')
        if rv != 'OK': return []
        rv, data = self.connector.search(None, "ALL")
        if rv != 'OK': return []
        for mailno in map(int, data[0].split()):
            rv, data = self.connector.fetch(str(mailno), '(RFC822)')
            if rv != 'OK': continue
            header = Parser.parsebytes(data[0][1])
            self.mails.append({'id': mailno, 'header': header})

    def sync (self):
        dialog = Dialog_Loading(self)
        dialog.show()
        dialog.message.setText("Retrieving messages ...")
        thr = threading.Thread(target=self.do_sync)
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                dialog.repaint()
                dialog.update()
            else:
                dialog.hide()
                break

    def list (self):
        return self.mails

    def delete (self, mailno):
        rv, data = self.connector.store(str(mailno), '+FLAGS', r'(\Deleted)')
        if rv != 'OK': return False
        rv, data = self.connector.expunge()
        if rv != 'OK': return False
        return True
Пример #4
0
class MailboxPOP3:

    def __init__ (self, profile):
        self.config = profile['config']['receiver']
        self.storageDir = None
        self.mails = []
        self.local_mails = []
        self.connector = None
        self.dialog = None
        self.synced = False
        self.dialog = Dialog_Loading(self)
        self.dialog.show()
        thr = threading.Thread(target=partial(self.create_connection, profile, self.dialog))
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                self.dialog.repaint()
                self.dialog.update()
            else:
                self.dialog.hide()
                break
        self.get_local_mails()

    def read_local_mail (self, filename):
        data = bytes()
        with open(filename, "rb") as stream:
            chunk = stream.read(4096)
            while chunk:
                data += chunk
                chunk = stream.read(4096)
        return data

    def get_local_mails (self):
        files = [os.path.join(self.storageDir, name) for name in os.listdir(self.storageDir)]
        mailno = -1
        for path in files:
            data = self.read_local_mail(path)
            self.local_mails.append({'id': mailno, 'content': data, 'path': path})
            mailno -= 1

    def create_connection (self, profile, dialog):
        pop3 = poplib.POP3_SSL if self.config['ssl'] else poplib.POP3
        safe_name = re.sub(r"[^A-Za-z0-9-]", "-", profile['name'])
        self.storageDir = os.path.join(
            'storage',
            '%i-%s' % (profile['id'], safe_name))
        try:
            os.mkdir(self.storageDir)
        except FileExistsError:
            pass
        try:
            self.connector = pop3(self.config['host'], self.config['port'])
        except Exception:
            pass
        else:
            print("Logging in ...")
            dialog.message.setText("Logging in ...")
            self.connector.user(self.config['username'])
            self.connector.pass_(self.config['password'])

    def reconnect (self):
        print("Resyncing ...")
        if self.connector:
            self.connector.quit()
        pop3 = poplib.POP3_SSL if self.config['ssl'] else poplib.POP3
        try:
            self.connector = pop3(self.config['host'], self.config['port'])
        except Exception:
            pass
        else:
            self.connector.user(self.config['username'])
            self.connector.pass_(self.config['password'])

    def walk_and_decode (self, header, content_type):
        content = ''
        for part in header.walk():
            charset = part.get_content_charset()
            if part.get_content_type() == content_type:
                part_str = part.get_payload(decode=True)
                content += part_str.decode(charset)
        return content

    def decode (self, content):
        header = Parser.parsebytes(content)
        content = ''
        try:
            content = self.walk_and_decode(header, 'text/html')
            if not content:
                bootstrap = '<html><head><style>body{background-color:#ffffff;}</style></head><body>%s</body></html>'
                content = self.walk_and_decode(header, 'text/plain')
                content = bootstrap % content.replace('\n', '<br />')
        except Exception:
            return 'Cannot decode message.'
        else:
            return content

    def fdecode (self, content):
        try:
            tmp = decode_header(content)
            return tmp[0][0].decode(tmp[0][1])
        except Exception:
            return content

    def get (self, mailno):
        content = None
        for mail in self.local_mails:
            if mail['id'] == mailno:
                header = Parser.parsebytes(mail['content'])
                return self.fdecode(header['From']), self.fdecode(header['Subject']), self.fdecode(header['Date']), self.decode(mail['content'])
        for mail in self.mails:
            if mail['id'] == mailno:
                header = Parser.parsebytes(mail['content'])
                return self.fdecode(header['From']), self.fdecode(header['Subject']), self.fdecode(header['Date']), self.decode(mail['content'])
        return 'Mail is empty.'

    def sync (self):
        self.dialog = Dialog_Loading(self)
        self.dialog.show()
        thr = threading.Thread(target=partial(self.do_sync, self.dialog))
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                self.dialog.repaint()
                self.dialog.update()
            else:
                self.dialog.hide()
                break

    def delete (self, mailno):
        if mailno < 0:
            for mail in self.local_mails:
                if mail['id'] == mailno:
                    os.unlink(mail['path'])
                    self.local_mails.remove(mail)
        else:
            self.connector.dele(mailno)

    def do_sync (self, dialog):
        if self.synced:
            self.reconnect()
        mail_list = self.connector.list()
        dialog.message.setText("Retrieving messages ...")
        print(mail_list[0].decode('utf-8'))
        self.mails = []
        for mail_info in mail_list[1]:
            mailno = int(mail_info.decode('utf-8').split(' ')[0])
            mail = self.connector.retr(mailno)
            content = b'\n'.join(mail[1])
            header = Parser.parsebytes(content)
            filename = datetime.datetime.now().isoformat()
            subject = header['Subject'] if isinstance(header['Subject'], str) else '<No subject>'
            filename += re.sub(r"[^A-Za-z0-9-]", "-", subject)
            filename = filename[:92]
            filename += '.xml'
            path = os.path.join(self.storageDir, filename)
            with open(path, 'wb') as stream:
                stream.write(content)
            self.mails.append({'id': mailno, 'content': content})
        self.synced = True

    def list (self):
        res = []
        for mail in self.local_mails:
            header = Parser.parsebytes(mail['content'])
            res.append({'id': mail['id'], 'header': header})
        for mail in self.mails:
            header = Parser.parsebytes(mail['content'])
            res.append({'id': mail['id'], 'header': header})
        return res

    def logout (self):
        if self.connector:
            print("Closing connection.")
            try:
                self.connector.quit()
            except Exception:
                pass
            self.connector = None
Пример #5
0
class MailboxPOP3:
    def __init__(self, profile):
        self.config = profile['config']['receiver']
        self.storageDir = None
        self.mails = []
        self.local_mails = []
        self.connector = None
        self.dialog = None
        self.synced = False
        self.dialog = Dialog_Loading(self)
        self.dialog.show()
        thr = threading.Thread(
            target=partial(self.create_connection, profile, self.dialog))
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                self.dialog.repaint()
                self.dialog.update()
            else:
                self.dialog.hide()
                break
        self.get_local_mails()

    def read_local_mail(self, filename):
        data = bytes()
        with open(filename, "rb") as stream:
            chunk = stream.read(4096)
            while chunk:
                data += chunk
                chunk = stream.read(4096)
        return data

    def get_local_mails(self):
        files = [
            os.path.join(self.storageDir, name)
            for name in os.listdir(self.storageDir)
        ]
        mailno = -1
        for path in files:
            data = self.read_local_mail(path)
            self.local_mails.append({
                'id': mailno,
                'content': data,
                'path': path
            })
            mailno -= 1

    def create_connection(self, profile, dialog):
        pop3 = poplib.POP3_SSL if self.config['ssl'] else poplib.POP3
        safe_name = re.sub(r"[^A-Za-z0-9-]", "-", profile['name'])
        self.storageDir = os.path.join('storage',
                                       '%i-%s' % (profile['id'], safe_name))
        try:
            os.mkdir(self.storageDir)
        except FileExistsError:
            pass
        try:
            self.connector = pop3(self.config['host'], self.config['port'])
        except Exception:
            pass
        else:
            print("Logging in ...")
            dialog.message.setText("Logging in ...")
            self.connector.user(self.config['username'])
            self.connector.pass_(self.config['password'])

    def reconnect(self):
        print("Resyncing ...")
        if self.connector:
            self.connector.quit()
        pop3 = poplib.POP3_SSL if self.config['ssl'] else poplib.POP3
        try:
            self.connector = pop3(self.config['host'], self.config['port'])
        except Exception:
            pass
        else:
            self.connector.user(self.config['username'])
            self.connector.pass_(self.config['password'])

    def walk_and_decode(self, header, content_type):
        content = ''
        for part in header.walk():
            charset = part.get_content_charset()
            if part.get_content_type() == content_type:
                part_str = part.get_payload(decode=True)
                content += part_str.decode(charset)
        return content

    def decode(self, content):
        header = Parser.parsebytes(content)
        content = ''
        try:
            content = self.walk_and_decode(header, 'text/html')
            if not content:
                bootstrap = '<html><head><style>body{background-color:#ffffff;}</style></head><body>%s</body></html>'
                content = self.walk_and_decode(header, 'text/plain')
                content = bootstrap % content.replace('\n', '<br />')
        except Exception:
            return 'Cannot decode message.'
        else:
            return content

    def fdecode(self, content):
        try:
            tmp = decode_header(content)
            return tmp[0][0].decode(tmp[0][1])
        except Exception:
            return content

    def get(self, mailno):
        content = None
        for mail in self.local_mails:
            if mail['id'] == mailno:
                header = Parser.parsebytes(mail['content'])
                return self.fdecode(header['From']), self.fdecode(
                    header['Subject']), self.fdecode(
                        header['Date']), self.decode(mail['content'])
        for mail in self.mails:
            if mail['id'] == mailno:
                header = Parser.parsebytes(mail['content'])
                return self.fdecode(header['From']), self.fdecode(
                    header['Subject']), self.fdecode(
                        header['Date']), self.decode(mail['content'])
        return 'Mail is empty.'

    def sync(self):
        self.dialog = Dialog_Loading(self)
        self.dialog.show()
        thr = threading.Thread(target=partial(self.do_sync, self.dialog))
        thr.start()
        while True:
            thr.join(0.1)
            if thr.is_alive():
                QtGui.QApplication.processEvents()
                self.dialog.repaint()
                self.dialog.update()
            else:
                self.dialog.hide()
                break

    def delete(self, mailno):
        if mailno < 0:
            for mail in self.local_mails:
                if mail['id'] == mailno:
                    os.unlink(mail['path'])
                    self.local_mails.remove(mail)
        else:
            self.connector.dele(mailno)

    def do_sync(self, dialog):
        if self.synced:
            self.reconnect()
        mail_list = self.connector.list()
        dialog.message.setText("Retrieving messages ...")
        print(mail_list[0].decode('utf-8'))
        self.mails = []
        for mail_info in mail_list[1]:
            mailno = int(mail_info.decode('utf-8').split(' ')[0])
            mail = self.connector.retr(mailno)
            content = b'\n'.join(mail[1])
            header = Parser.parsebytes(content)
            filename = datetime.datetime.now().isoformat()
            subject = header['Subject'] if isinstance(header['Subject'],
                                                      str) else '<No subject>'
            filename += re.sub(r"[^A-Za-z0-9-]", "-", subject)
            filename = filename[:92]
            filename += '.xml'
            path = os.path.join(self.storageDir, filename)
            with open(path, 'wb') as stream:
                stream.write(content)
            self.mails.append({'id': mailno, 'content': content})
        self.synced = True

    def list(self):
        res = []
        for mail in self.local_mails:
            header = Parser.parsebytes(mail['content'])
            res.append({'id': mail['id'], 'header': header})
        for mail in self.mails:
            header = Parser.parsebytes(mail['content'])
            res.append({'id': mail['id'], 'header': header})
        return res

    def logout(self):
        if self.connector:
            print("Closing connection.")
            try:
                self.connector.quit()
            except Exception:
                pass
            self.connector = None