mirror of
https://github.com/pulb/mailnag.git
synced 2026-05-06 15:15:58 +02:00
rewritten account stuff (unfortunately this breaks existing config files)
This commit is contained in:
125
Mailnag/common/account.py
Normal file
125
Mailnag/common/account.py
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# account.py
|
||||
#
|
||||
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
|
||||
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
PACKAGE_NAME = "mailnag"
|
||||
|
||||
import gettext
|
||||
import time
|
||||
import poplib
|
||||
import daemon.imaplib2 as imaplib
|
||||
|
||||
gettext.bindtextdomain(PACKAGE_NAME, './locale')
|
||||
gettext.textdomain(PACKAGE_NAME)
|
||||
_ = gettext.gettext
|
||||
|
||||
account_defaults = {
|
||||
'enabled' : '0',
|
||||
'name' : '',
|
||||
'user' : '',
|
||||
'server' : '',
|
||||
'port' : '',
|
||||
'ssl' : '0',
|
||||
'imap' : '0',
|
||||
'idle' : '0',
|
||||
'folder' : ''
|
||||
}
|
||||
|
||||
class Account:
|
||||
def __init__(self, enabled = False, name = _('Unnamed'), user = '', \
|
||||
password = '', server = '', port = '', ssl = False, imap = False, idle = False, folder = '' ):
|
||||
|
||||
self.enabled = enabled # bool
|
||||
self.name = name
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.ssl = ssl # bool
|
||||
self.imap = imap # bool
|
||||
self.idle = idle # bool
|
||||
self.folder = folder
|
||||
|
||||
|
||||
def get_connection(self): # get email server connection
|
||||
if self.imap: # IMAP
|
||||
try:
|
||||
srv = self._get_IMAP_connection()
|
||||
except:
|
||||
print "Warning: Cannot connect to IMAP account: %s. " \
|
||||
"Next try in 30 seconds." % self.server
|
||||
time.sleep(30) # wait 30 seconds
|
||||
try:
|
||||
srv = self._get_IMAP_connection()
|
||||
except:
|
||||
print "Error: Cannot connect to IMAP account: %s. " % self.server
|
||||
srv = None
|
||||
else: # POP
|
||||
try:
|
||||
srv = self._get_POP3_connection()
|
||||
except:
|
||||
print "Warning: Cannot connect to POP account: %s. " \
|
||||
"Next try in 30 seconds." % self.server
|
||||
time.sleep(30) # wait 30 seconds
|
||||
try:
|
||||
srv = self._get_POP3_connection()
|
||||
except:
|
||||
print "Error: Cannot connect to POP account: %s. " % self.server
|
||||
srv = None
|
||||
|
||||
return srv # server object
|
||||
|
||||
|
||||
def _get_IMAP_connection(self):
|
||||
if self.ssl:
|
||||
if self.port == '':
|
||||
srv = imaplib.IMAP4_SSL(self.server)
|
||||
else:
|
||||
srv = imaplib.IMAP4_SSL(self.server, self.port)
|
||||
else:
|
||||
if self.port == '':
|
||||
srv = imaplib.IMAP4(self.server)
|
||||
else:
|
||||
srv = imaplib.IMAP4(self.server, self.port)
|
||||
|
||||
srv.login(self.user, self.password)
|
||||
return srv
|
||||
|
||||
|
||||
def _get_POP3_connection(self):
|
||||
if self.ssl:
|
||||
if self.port == '':
|
||||
srv = poplib.POP3_SSL(self.server)
|
||||
else:
|
||||
srv = poplib.POP3_SSL(self.server, self.port)
|
||||
else:
|
||||
if self.port == '':
|
||||
srv = poplib.POP3(self.server)
|
||||
else:
|
||||
srv = poplib.POP3(self.server, self.port)
|
||||
|
||||
srv.getwelcome()
|
||||
srv.user(self.user)
|
||||
srv.pass_(self.password)
|
||||
return srv
|
||||
|
||||
109
Mailnag/common/accountlist.py
Normal file
109
Mailnag/common/accountlist.py
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# accountlist.py
|
||||
#
|
||||
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
PACKAGE_NAME = "mailnag"
|
||||
|
||||
from ConfigParser import NoSectionError
|
||||
from common.account import Account, account_defaults
|
||||
from common.keyring import Keyring
|
||||
|
||||
class AccountList(list):
|
||||
def __init__(self):
|
||||
self._keyring = Keyring()
|
||||
|
||||
|
||||
def load_from_cfg(self, cfg, enabled_only=False):
|
||||
del self[:]
|
||||
|
||||
i = 1
|
||||
section_name = "Account" + str(i)
|
||||
|
||||
while cfg.has_section(section_name):
|
||||
enabled = bool(int( self._get_account_cfg(cfg, section_name, 'enabled') ))
|
||||
|
||||
if (not enabled_only) or (enabled_only and enabled):
|
||||
name = self._get_account_cfg(cfg, section_name, 'name')
|
||||
user = self._get_account_cfg(cfg, section_name, 'user')
|
||||
server = self._get_account_cfg(cfg, section_name, 'server')
|
||||
port = self._get_account_cfg(cfg, section_name, 'port')
|
||||
ssl = bool(int( self._get_account_cfg(cfg, section_name, 'ssl') ))
|
||||
imap = bool(int( self._get_account_cfg(cfg, section_name, 'imap') ))
|
||||
idle = bool(int( self._get_account_cfg(cfg, section_name, 'idle') ))
|
||||
folder = self._get_account_cfg(cfg, section_name, 'folder')
|
||||
|
||||
protocol = 'imap' if imap else 'pop'
|
||||
password = self._keyring.get(protocol, user, server)
|
||||
|
||||
acc = Account(enabled, name, user, password, server, port, ssl, imap, idle, folder)
|
||||
self.append(acc)
|
||||
|
||||
i = i + 1
|
||||
section_name = "Account" + str(i)
|
||||
|
||||
|
||||
def save_to_cfg(self, cfg):
|
||||
# remove existing accounts from cfg
|
||||
i = 1
|
||||
section_name = "Account" + str(i)
|
||||
while cfg.has_section(section_name):
|
||||
cfg.remove_section(section_name)
|
||||
i = i + 1
|
||||
section_name = "Account" + str(i)
|
||||
|
||||
# add accounts
|
||||
i = 1
|
||||
for acc in self:
|
||||
section_name = "Account" + str(i)
|
||||
|
||||
cfg.add_section(section_name)
|
||||
|
||||
cfg.set(section_name, 'enabled', int(acc.enabled))
|
||||
cfg.set(section_name, 'name', acc.name)
|
||||
cfg.set(section_name, 'user', acc.user)
|
||||
cfg.set(section_name, 'server', acc.server)
|
||||
cfg.set(section_name, 'port', acc.port)
|
||||
cfg.set(section_name, 'ssl', int(acc.ssl))
|
||||
cfg.set(section_name, 'imap', int(acc.imap))
|
||||
cfg.set(section_name, 'idle', int(acc.idle))
|
||||
cfg.set(section_name, 'folder', acc.folder)
|
||||
|
||||
protocol = 'imap' if acc.imap else 'pop'
|
||||
self._keyring.set(protocol, acc.user, acc.server, acc.password)
|
||||
|
||||
i = i + 1
|
||||
|
||||
# delete obsolete entries from Keyring
|
||||
self._keyring.remove(self)
|
||||
|
||||
|
||||
def import_from_keyring(self):
|
||||
# append imported accounts to existing accounts
|
||||
self.extend(self._keyring.import_accounts())
|
||||
|
||||
|
||||
def _get_account_cfg(self, cfg, section_name, option_name):
|
||||
if cfg.has_option(section_name, option_name):
|
||||
return cfg.get(section_name, option_name)
|
||||
else:
|
||||
return account_defaults[option_name]
|
||||
|
||||
@@ -21,45 +21,33 @@
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
import os
|
||||
import ConfigParser
|
||||
import xdg.BaseDirectory as bd
|
||||
|
||||
from ConfigParser import RawConfigParser
|
||||
from utils import get_default_mail_reader
|
||||
|
||||
|
||||
mailnag_defaults = {
|
||||
'general':
|
||||
{
|
||||
'mail_client' : get_default_mail_reader(),
|
||||
'messagetray_label' : "mailnag",
|
||||
'check_interval' : 5,
|
||||
'notification_mode' : 0,
|
||||
'sender_format' : 1,
|
||||
'playsound' : 1,
|
||||
'messagetray_label' : 'mailnag',
|
||||
'check_interval' : '5',
|
||||
'notification_mode' : '0',
|
||||
'sender_format' : '1',
|
||||
'playsound' : '1',
|
||||
'soundfile' : 'mailnag.ogg',
|
||||
'autostart' : 1
|
||||
'autostart' : '1'
|
||||
},
|
||||
'filter':
|
||||
{
|
||||
'filter_on' : 0,
|
||||
'filter_enabled' : '0',
|
||||
'filter_text' : 'newsletter, viagra'
|
||||
},
|
||||
'script':
|
||||
{
|
||||
'script0_on' : 0,
|
||||
'script1_on' : 0,
|
||||
'script0_enabled' : '0',
|
||||
'script1_enabled' : '0',
|
||||
'script0_file' : '',
|
||||
'script1_file' : '',
|
||||
},
|
||||
'account':
|
||||
{
|
||||
'on' : '',
|
||||
'name' : '',
|
||||
'server' : '',
|
||||
'user' : '',
|
||||
'imap' : '',
|
||||
'folder' : '',
|
||||
'port' : ''
|
||||
'script1_file' : ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +59,7 @@ def cfg_exists():
|
||||
|
||||
|
||||
def read_cfg():
|
||||
cfg = ConfigParser.RawConfigParser()
|
||||
cfg = RawConfigParser()
|
||||
cfg._sections = mailnag_defaults # HACK : use cfg.read_dict(mailnag_defaults) in python 3
|
||||
|
||||
if os.path.exists(cfg_file):
|
||||
|
||||
@@ -27,7 +27,9 @@ from gi.repository import GObject, GLib, GdkPixbuf, Gtk
|
||||
import locale
|
||||
import gettext
|
||||
import gnomekeyring
|
||||
from utils import get_data_file
|
||||
|
||||
from common.utils import get_data_file
|
||||
from common.account import Account
|
||||
|
||||
PACKAGE_NAME = "mailnag"
|
||||
|
||||
@@ -89,7 +91,7 @@ class Keyring:
|
||||
return ''
|
||||
|
||||
|
||||
def import_accounts(self): # get email accounts from Gnome-Keyring
|
||||
def import_accounts(self): # get email accounts from Gnome-Keyring
|
||||
accounts = []
|
||||
if gnomekeyring.list_item_ids_sync(self.defaultKeyring):
|
||||
displayNameDict = {}
|
||||
@@ -101,21 +103,26 @@ class Keyring:
|
||||
or displayName.startswith('imap://'):
|
||||
server = displayName.split('@')[1][:-1]
|
||||
if displayName.startswith('imap://'):
|
||||
imap = 1
|
||||
imap = True
|
||||
user = displayName.split('@')[0][7:]
|
||||
else:
|
||||
imap = 0
|
||||
imap = False
|
||||
user = displayName.split('@')[0][6:]
|
||||
|
||||
user = user.replace('%40','@')
|
||||
|
||||
if ';' in user:
|
||||
user = user.split(';')[0]
|
||||
|
||||
password = gnomekeyring.item_get_info_sync(self.defaultKeyring, \
|
||||
displayNameDict[displayName]).get_secret()
|
||||
accounts.append([server, user, password, imap])
|
||||
|
||||
accounts.append(Account(enabled = True, name = "%s (%s)" % (server, user), \
|
||||
server = server, user = user, password = password, imap = imap))
|
||||
return accounts
|
||||
|
||||
|
||||
def set(self, protocol, user, server, password): # store password in Gnome-Keyring
|
||||
def set(self, protocol, user, server, password): # store password in Gnome-Keyring
|
||||
if password != '':
|
||||
displayNameDict = {}
|
||||
for identity in gnomekeyring.list_item_ids_sync(self.defaultKeyring):
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# account.py
|
||||
#
|
||||
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
|
||||
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
class Account:
|
||||
def __init__(self, on, name, server, user, password, imap, folder, port):
|
||||
self.id = str(id(self)) # unique identifier
|
||||
self.on = on # int
|
||||
self.name = name
|
||||
self.server = server
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.imap = imap # int
|
||||
self.folder = folder
|
||||
self.port = port
|
||||
|
||||
|
||||
def get_row(self):
|
||||
return [self.id, self.on, self.name]
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
PACKAGE_NAME = "mailnag"
|
||||
|
||||
from gi.repository import GLib, GdkPixbuf, Gtk
|
||||
import gettext
|
||||
from gi.repository import GLib, GdkPixbuf, Gtk
|
||||
from common.utils import get_data_file
|
||||
|
||||
gettext.bindtextdomain(PACKAGE_NAME, './locale')
|
||||
@@ -38,8 +38,8 @@ class AccountDialog:
|
||||
builder.set_translation_domain(PACKAGE_NAME)
|
||||
builder.add_from_file(get_data_file("account_dialog.ui"))
|
||||
builder.connect_signals({ \
|
||||
"account_type_changed" : self.__on_cmb_account_type_changed, \
|
||||
"entry_changed" : self.__on_entry_changed, \
|
||||
"chk_account_imap_toggled" : self.__on_chk_account_imap_toggled, \
|
||||
"btn_cancel_clicked" : self.__on_btn_cancel_clicked, \
|
||||
"btn_save_clicked" : self.__on_btn_save_clicked \
|
||||
})
|
||||
@@ -47,15 +47,20 @@ class AccountDialog:
|
||||
self.window = builder.get_object("account_dialog")
|
||||
self.window.set_transient_for(parent)
|
||||
|
||||
self.cmb_account_type = builder.get_object("cmb_account_type")
|
||||
self.entry_account_name = builder.get_object("entry_account_name")
|
||||
self.entry_account_user = builder.get_object("entry_account_user")
|
||||
self.entry_account_password = builder.get_object("entry_account_password")
|
||||
self.entry_account_server = builder.get_object("entry_account_server")
|
||||
self.entry_account_port = builder.get_object("entry_account_port")
|
||||
self.chk_account_imap = builder.get_object("chk_account_imap")
|
||||
self.label_account_folder = builder.get_object("label_account_folder")
|
||||
self.entry_account_folder = builder.get_object("entry_account_folder")
|
||||
self.chk_account_push = builder.get_object("chk_account_push")
|
||||
self.chk_account_ssl = builder.get_object("chk_account_ssl")
|
||||
self.button_save = builder.get_object("button_save")
|
||||
|
||||
self.cmb_account_type.set_active(0) # default to POP3
|
||||
|
||||
|
||||
def run(self):
|
||||
return self.window.run()
|
||||
@@ -83,7 +88,14 @@ class AccountDialog:
|
||||
self.button_save.set_sensitive(ok)
|
||||
|
||||
|
||||
def __on_chk_account_imap_toggled(self, widget):
|
||||
self.entry_account_folder.set_sensitive(self.chk_account_imap.get_active())
|
||||
def __on_cmb_account_type_changed(self, widget):
|
||||
if self.cmb_account_type.get_active() == 0: # POP3
|
||||
self.label_account_folder.set_visible(False)
|
||||
self.entry_account_folder.set_visible(False)
|
||||
self.chk_account_push.set_visible(False)
|
||||
else: # IMAP
|
||||
self.label_account_folder.set_visible(True)
|
||||
self.entry_account_folder.set_visible(True)
|
||||
self.chk_account_push.set_visible(True)
|
||||
|
||||
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# accounts.py
|
||||
#
|
||||
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
|
||||
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
PACKAGE_NAME = "mailnag"
|
||||
|
||||
import gettext
|
||||
from configuration.account import Account
|
||||
|
||||
gettext.bindtextdomain(PACKAGE_NAME, './locale')
|
||||
gettext.textdomain(PACKAGE_NAME)
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class Accounts:
|
||||
def __init__(self, cfg, keyring):
|
||||
self.account = []
|
||||
self.current = None # currently selected account_id
|
||||
self.cfg = cfg
|
||||
self.keyring = keyring
|
||||
|
||||
def add(self, on = 0, name = _('Unnamed'), server = '', user= '' , \
|
||||
password = '', imap = 0, folder = '', port = ''): # add one new account
|
||||
self.account.append(Account(on, name, server, user, \
|
||||
password, imap, folder, port))
|
||||
this_account = self.account[-1] # get last element of the list
|
||||
id = this_account.id
|
||||
return id
|
||||
|
||||
|
||||
def remove(self, id): # delete account by id
|
||||
for acc in self.account[:]: # iterate copy of account list
|
||||
if acc.id == id: # find matching account
|
||||
self.account.remove(acc) # delete it
|
||||
break # stop iteration
|
||||
|
||||
|
||||
def load(self):
|
||||
self.account = [] # empty account list
|
||||
|
||||
on = self.cfg.get('account', 'on')
|
||||
name = self.cfg.get('account', 'name')
|
||||
server = self.cfg.get('account', 'server')
|
||||
user = self.cfg.get('account', 'user')
|
||||
imap = self.cfg.get('account', 'imap')
|
||||
folder = self.cfg.get('account', 'folder')
|
||||
port = self.cfg.get('account', 'port')
|
||||
|
||||
separator = '|'
|
||||
on_list = on.split(separator)
|
||||
name_list = name.split(separator)
|
||||
server_list = server.split(separator)
|
||||
user_list = user.split(separator)
|
||||
imap_list = imap.split(separator)
|
||||
folder_list = folder.split(separator)
|
||||
port_list = port.split(separator)
|
||||
|
||||
for i in range(len(name_list)): # iterate 0 to nr of elements in name_list
|
||||
name = name_list[i]
|
||||
if name == '': continue
|
||||
on = int(on_list[i])
|
||||
server = server_list[i]
|
||||
user = user_list[i]
|
||||
imap = int(imap_list[i])
|
||||
folder = folder_list[i]
|
||||
port = port_list[i]
|
||||
if imap: protocol = 'imap'
|
||||
else: protocol = 'pop'
|
||||
password = self.keyring.get(protocol, user, server)
|
||||
self.add(on, name, server, user, password, imap, folder, port) # fill Account list
|
||||
|
||||
|
||||
def get(self, id): # return all data of one account
|
||||
self.current = id
|
||||
for acc in self.account:
|
||||
if acc.id == id:
|
||||
return acc
|
||||
return None
|
||||
|
||||
|
||||
def get_current(self): # return current account
|
||||
if self.current != None:
|
||||
for acc in self.account:
|
||||
if acc.id == self.current:
|
||||
return acc
|
||||
return None
|
||||
|
||||
|
||||
def get_cfg(self): # return arrays of account strings for cfg
|
||||
separator = '|'
|
||||
|
||||
on_list = []
|
||||
name_list = []
|
||||
server_list = []
|
||||
user_list = []
|
||||
password_list = []
|
||||
imap_list = []
|
||||
folder_list = []
|
||||
port_list = []
|
||||
|
||||
for acc in self.account: # collect all values
|
||||
on_list.append(str(int(acc.on)))
|
||||
name_list.append(acc.name)
|
||||
server_list.append(acc.server)
|
||||
user_list.append(acc.user)
|
||||
password_list.append(acc.password)
|
||||
imap_list.append(str(int(acc.imap)))
|
||||
folder_list.append(acc.folder)
|
||||
port_list.append(acc.port)
|
||||
|
||||
cfg_on = separator.join(on_list) # concatenate values
|
||||
cfg_name = separator.join(name_list)
|
||||
cfg_server = separator.join(server_list)
|
||||
cfg_user = separator.join(user_list)
|
||||
cfg_imap = separator.join(imap_list)
|
||||
cfg_folder = separator.join(folder_list)
|
||||
cfg_port = separator.join(port_list)
|
||||
|
||||
return cfg_on, cfg_name, cfg_server, cfg_user, password_list, cfg_imap, cfg_folder, cfg_port
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ import gettext
|
||||
|
||||
from common.utils import get_data_file
|
||||
from common.config import read_cfg, write_cfg
|
||||
from common.keyring import Keyring
|
||||
from common.accountlist import AccountList
|
||||
from common.account import Account
|
||||
from configuration.accountdialog import AccountDialog
|
||||
from configuration.accounts import Accounts
|
||||
|
||||
locale.bindtextdomain(PACKAGE_NAME, './locale')
|
||||
gettext.bindtextdomain(PACKAGE_NAME, './locale')
|
||||
@@ -61,13 +61,12 @@ class ConfigWindow:
|
||||
|
||||
self.window = builder.get_object("config_window")
|
||||
self.window.set_icon(GdkPixbuf.Pixbuf.new_from_file_at_size(get_data_file("mailnag.svg"), 48, 48));
|
||||
self.keyring = Keyring()
|
||||
self.cfg = read_cfg()
|
||||
|
||||
#
|
||||
# account tab
|
||||
#
|
||||
self.accounts = Accounts(self.cfg, self.keyring)
|
||||
self.accounts = AccountList()
|
||||
|
||||
self.treeview_accounts = builder.get_object("treeview_accounts")
|
||||
self.liststore_accounts = builder.get_object("liststore_accounts")
|
||||
@@ -75,11 +74,6 @@ class ConfigWindow:
|
||||
self.button_edit = builder.get_object("button_edit")
|
||||
self.button_remove = builder.get_object("button_remove")
|
||||
|
||||
# colhead = [('Id'), _('Active'), _('Name')] # column headings
|
||||
#
|
||||
# renderer_id = Gtk.CellRendererText()
|
||||
# column_id = Gtk.TreeViewColumn(colhead[0], renderer_id, text=0) # Account Id
|
||||
|
||||
renderer_on = Gtk.CellRendererToggle()
|
||||
renderer_on.connect("toggled", self.__on_account_toggled) # bind toggle signal
|
||||
column_on = Gtk.TreeViewColumn(_('Enabled'), renderer_on) # Account On/Off
|
||||
@@ -135,38 +129,35 @@ class ConfigWindow:
|
||||
self.entry_label.set_text(self.cfg.get('general', 'messagetray_label'))
|
||||
self.spinbutton_interval.set_value(int(self.cfg.get('general', 'check_interval')))
|
||||
self.cb_notification_mode.set_active(int(self.cfg.get('general', 'notification_mode')))
|
||||
self.chk_playsound.set_active(int(self.cfg.get('general', 'playsound')))
|
||||
self.chk_autostart.set_active(int(self.cfg.get('general', 'autostart')))
|
||||
self.chk_playsound.set_active(bool(int(self.cfg.get('general', 'playsound'))))
|
||||
self.chk_autostart.set_active(bool(int(self.cfg.get('general', 'autostart'))))
|
||||
|
||||
|
||||
self.chk_enable_filter.set_active(int(self.cfg.get('filter', 'filter_on')))
|
||||
self.chk_enable_filter.set_active(bool(int(self.cfg.get('filter', 'filter_enabled'))))
|
||||
self.textbuffer_filter.set_text(self.cfg.get('filter', 'filter_text'))
|
||||
|
||||
self.chk_script0.set_active(int(self.cfg.get('script', 'script0_on')))
|
||||
self.chk_script0.set_active(bool(int(self.cfg.get('script', 'script0_enabled'))))
|
||||
|
||||
tmp = self.cfg.get('script', 'script0_file')
|
||||
if len(tmp) > 0:
|
||||
self.filechooser_script0.set_filename(tmp)
|
||||
|
||||
self.chk_script1.set_active(int(self.cfg.get('script', 'script1_on')))
|
||||
self.chk_script1.set_active(bool(int(self.cfg.get('script', 'script1_enabled'))))
|
||||
|
||||
tmp = self.cfg.get('script', 'script1_file')
|
||||
if len(tmp) > 0:
|
||||
self.filechooser_script1.set_filename(tmp)
|
||||
|
||||
self.accounts.load()
|
||||
self.accounts.load_from_cfg(self.cfg)
|
||||
|
||||
if len(self.accounts.account) == 0:
|
||||
imported_accounts = self.keyring.import_accounts()
|
||||
if len(imported_accounts) > 0 and \
|
||||
self.show_yesno_dialog(_("Mailnag found %s mail accounts on this computer.\n\nDo you want to import them?") % len(imported_accounts)):
|
||||
for arr in imported_accounts:
|
||||
self.accounts.add(name = "%s (%s)" % (arr[1], arr[0]), \
|
||||
on = 1, server = arr[0], user = arr[1], \
|
||||
password = arr[2], imap = arr[3])
|
||||
|
||||
for acc in self.accounts.account:
|
||||
row = acc.get_row()
|
||||
if len(self.accounts) == 0:
|
||||
self.accounts.import_from_keyring()
|
||||
if len(self.accounts) > 0 and \
|
||||
(not self.show_yesno_dialog(_("Mailnag found %s mail accounts on this computer.\n\nDo you want to import them?") % len(self.accounts))):
|
||||
del self.accounts[:]
|
||||
|
||||
for acc in self.accounts:
|
||||
row = [acc, acc.enabled, acc.name]
|
||||
self.liststore_accounts.append(row)
|
||||
self.select_path((0,))
|
||||
|
||||
@@ -180,34 +171,22 @@ class ConfigWindow:
|
||||
autostart = self.chk_autostart.get_active()
|
||||
self.cfg.set('general', 'autostart', int(autostart))
|
||||
|
||||
self.cfg.set('filter', 'filter_on', int(self.chk_enable_filter.get_active()))
|
||||
self.cfg.set('filter', 'filter_enabled', int(self.chk_enable_filter.get_active()))
|
||||
start, end = self.textbuffer_filter.get_bounds()
|
||||
self.cfg.set('filter', 'filter_text', self.textbuffer_filter.get_text(start, end, True))
|
||||
|
||||
self.cfg.set('script', 'script0_on', int(self.chk_script0.get_active()))
|
||||
self.cfg.set('script', 'script0_enabled', int(self.chk_script0.get_active()))
|
||||
tmp = self.filechooser_script0.get_filename()
|
||||
if tmp == None: tmp = ""
|
||||
self.cfg.set('script', 'script0_file', tmp)
|
||||
|
||||
self.cfg.set('script', 'script1_on', int(self.chk_script1.get_active()))
|
||||
self.cfg.set('script', 'script1_enabled', int(self.chk_script1.get_active()))
|
||||
tmp = self.filechooser_script1.get_filename()
|
||||
if tmp == None: tmp = ""
|
||||
self.cfg.set('script', 'script1_file', tmp)
|
||||
|
||||
on, name, server, user, password, imap, folder, port = self.accounts.get_cfg()
|
||||
self.cfg.set('account', 'on', on)
|
||||
self.cfg.set('account', 'name', name)
|
||||
self.cfg.set('account', 'server', server)
|
||||
self.cfg.set('account', 'user', user)
|
||||
self.cfg.set('account', 'imap', imap)
|
||||
self.cfg.set('account', 'folder', folder)
|
||||
self.cfg.set('account', 'port', port)
|
||||
|
||||
for acc in self.accounts.account:
|
||||
if bool(acc.imap): protocol = 'imap'
|
||||
else: protocol = 'pop'
|
||||
self.keyring.set(protocol, acc.user, acc.server, acc.password)
|
||||
|
||||
self.accounts.save_to_cfg(self.cfg)
|
||||
|
||||
write_cfg(self.cfg)
|
||||
|
||||
if autostart: self.create_autostart()
|
||||
@@ -227,9 +206,9 @@ class ConfigWindow:
|
||||
treeselection = self.treeview_accounts.get_selection() # get tree_selection object
|
||||
selection = treeselection.get_selected() # get selected tupel (model, iter)
|
||||
model, iter = selection # get selected iter
|
||||
if iter != None: id = model.get_value(iter, 0) # get account_id from treeviews 1. column
|
||||
else: id = None
|
||||
return id, model, iter
|
||||
if iter != None: acc = model.get_value(iter, 0) # get account object from treeviews 1. column
|
||||
else: acc = None
|
||||
return acc, model, iter
|
||||
|
||||
|
||||
def select_path(self, path): # select path in treeview
|
||||
@@ -239,18 +218,20 @@ class ConfigWindow:
|
||||
|
||||
|
||||
def edit_account(self):
|
||||
id, model, iter = self.get_selected_account()
|
||||
acc, model, iter = self.get_selected_account()
|
||||
if iter != None:
|
||||
acc = self.accounts.get(id)
|
||||
d = AccountDialog(self.window)
|
||||
|
||||
d.cmb_account_type.set_active(acc.imap)
|
||||
|
||||
d.entry_account_name.set_text(acc.name)
|
||||
d.entry_account_user.set_text(acc.user)
|
||||
d.entry_account_password.set_text(acc.password)
|
||||
d.entry_account_server.set_text(acc.server)
|
||||
d.entry_account_port.set_text(acc.port)
|
||||
d.chk_account_imap.set_active(acc.imap)
|
||||
d.entry_account_folder.set_text(acc.folder)
|
||||
d.chk_account_push.set_active(acc.idle)
|
||||
d.chk_account_ssl.set_active(acc.ssl)
|
||||
|
||||
res = d.run()
|
||||
|
||||
@@ -260,8 +241,16 @@ class ConfigWindow:
|
||||
acc.password = d.entry_account_password.get_text()
|
||||
acc.server = d.entry_account_server.get_text()
|
||||
acc.port = d.entry_account_port.get_text()
|
||||
acc.imap = d.chk_account_imap.get_active()
|
||||
acc.folder = d.entry_account_folder.get_text()
|
||||
acc.ssl = d.chk_account_ssl.get_active()
|
||||
|
||||
if d.cmb_account_type.get_active() == 0: # POP3
|
||||
acc.imap = False
|
||||
acc.folder = ''
|
||||
acc.idle = False
|
||||
else: # IMAP
|
||||
acc.imap = True
|
||||
acc.folder = d.entry_account_folder.get_text()
|
||||
acc.idle = d.chk_account_push.get_active()
|
||||
|
||||
model.set_value(iter, 2, acc.name)
|
||||
|
||||
@@ -303,25 +292,33 @@ class ConfigWindow:
|
||||
def __on_account_toggled(self, cell, path): # chk_box account_on toggled
|
||||
model = self.liststore_accounts
|
||||
iter = model.get_iter(path)
|
||||
id = model.get_value(iter, 0)
|
||||
acc = self.accounts.get(id) # get account by id
|
||||
acc.on = not acc.on # update account.on
|
||||
acc = model.get_value(iter, 0)
|
||||
acc.enabled = not acc.enabled
|
||||
|
||||
self.liststore_accounts.set_value(iter, 1, not cell.get_active())
|
||||
|
||||
|
||||
|
||||
def __on_btn_add_clicked(self, widget):
|
||||
d = AccountDialog(self.window)
|
||||
res = d.run()
|
||||
|
||||
if res == 1:
|
||||
id = self.accounts.add(1, d.entry_account_name.get_text(),
|
||||
d.entry_account_server.get_text(), d.entry_account_user.get_text(),
|
||||
d.entry_account_password.get_text(), d.chk_account_imap.get_active(),
|
||||
d.entry_account_folder.get_text(), d.entry_account_port.get_text()
|
||||
)
|
||||
if d.cmb_account_type.get_active() == 0: # POP3
|
||||
imap = False
|
||||
folder = ''
|
||||
idle = False
|
||||
else: # IMAP
|
||||
imap = True
|
||||
folder = d.entry_account_folder.get_text()
|
||||
idle = d.chk_account_push.get_active()
|
||||
|
||||
row = [id, 1, d.entry_account_name.get_text()]
|
||||
acc = Account(enabled = True, name = d.entry_account_name.get_text(), \
|
||||
user = d.entry_account_user.get_text(), password = d.entry_account_password.get_text(), \
|
||||
server = d.entry_account_server.get_text(), port = d.entry_account_port.get_text(), \
|
||||
ssl = d.chk_account_ssl.get_active(), imap = imap, idle = idle , folder = folder)
|
||||
self.accounts.append(acc)
|
||||
|
||||
row = [acc, True, acc.name]
|
||||
iter = self.liststore_accounts.append(row)
|
||||
model = self.treeview_accounts.get_model()
|
||||
path = model.get_path(iter)
|
||||
@@ -336,11 +333,10 @@ class ConfigWindow:
|
||||
|
||||
|
||||
def __on_btn_remove_clicked(self, widget):
|
||||
id, model, iter = self.get_selected_account()
|
||||
acc, model, iter = self.get_selected_account()
|
||||
if iter != None:
|
||||
name = model.get_value(iter, 2) # get account_name
|
||||
if self.show_yesno_dialog(_('Delete this account:') + \
|
||||
'\n\n' + name):
|
||||
'\n\n' + acc.name):
|
||||
|
||||
p = model.get_path(iter)
|
||||
if not p.prev():
|
||||
@@ -348,7 +344,7 @@ class ConfigWindow:
|
||||
self.select_path(p) # select prev/next account
|
||||
|
||||
model.remove(iter) # delete in treeview
|
||||
self.accounts.remove(id) # delete in accounts list
|
||||
self.accounts.remove(acc) # delete in accounts list
|
||||
|
||||
|
||||
def __on_treeview_accounts_row_activated(self, treeview, path, view_column):
|
||||
@@ -378,8 +374,7 @@ class ConfigWindow:
|
||||
|
||||
|
||||
def __save_and_quit(self):
|
||||
self.save_config()
|
||||
self.keyring.remove(self.accounts.account) # delete obsolete entries from Keyring
|
||||
self.save_config()
|
||||
Gtk.main_quit()
|
||||
|
||||
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# account.py
|
||||
#
|
||||
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
|
||||
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import time
|
||||
import poplib
|
||||
import daemon.imaplib2 as imaplib
|
||||
|
||||
class Account:
|
||||
def __init__(self, check_interval, name, server, user, password, imap, folder, port):
|
||||
self.check_interval = check_interval
|
||||
self.name = name
|
||||
self.server = server
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.imap = imap # int
|
||||
self.folder = folder
|
||||
self.port = port
|
||||
self.mail_count = 0
|
||||
|
||||
|
||||
def get_connection(self): # get email server connection
|
||||
if self.imap: # IMAP
|
||||
try:
|
||||
try:
|
||||
if self.port == '':
|
||||
srv = imaplib.IMAP4_SSL(self.server) # SSL
|
||||
else:
|
||||
srv = imaplib.IMAP4_SSL(self.server, self.port)
|
||||
except:
|
||||
if self.port == '':
|
||||
srv = imaplib.IMAP4(self.server) # non SSL
|
||||
else:
|
||||
srv = imaplib.IMAP4(self.server, self.port)
|
||||
srv.login(self.user, self.password)
|
||||
except:
|
||||
print "Warning: Cannot connect to IMAP account: %s. " \
|
||||
"Next try in 30 seconds." % self.server
|
||||
time.sleep(30) # wait 30 seconds
|
||||
try:
|
||||
try:
|
||||
if self.port == '':
|
||||
srv = imaplib.IMAP4_SSL(self.server) # SSL
|
||||
else:
|
||||
srv = imaplib.IMAP4_SSL(self.server, self.port)
|
||||
except:
|
||||
if self.port == '':
|
||||
srv = imaplib.IMAP4(self.server) # non SSL
|
||||
else:
|
||||
srv = imaplib.IMAP4(self.server, self.port)
|
||||
srv.login(self.user, self.password)
|
||||
except:
|
||||
print "Error: Cannot connect to IMAP account: %s. " \
|
||||
"Next try in %s minutes." % (self.server, self.check_interval)
|
||||
srv = None
|
||||
else: # POP
|
||||
try:
|
||||
try:
|
||||
if self.port == '':
|
||||
srv = poplib.POP3_SSL(self.server) # connect to Email-Server via SSL
|
||||
else:
|
||||
srv = poplib.POP3_SSL(self.server, self.port)
|
||||
except:
|
||||
if self.port == '':
|
||||
srv = poplib.POP3(self.server) # non SSL
|
||||
else:
|
||||
srv = poplib.POP3(self.server, self.port)
|
||||
srv.getwelcome()
|
||||
srv.user(self.user)
|
||||
srv.pass_(self.password)
|
||||
except:
|
||||
print "Warning: Cannot connect to POP account: %s. " \
|
||||
"Next try in 30 seconds." % self.server
|
||||
time.sleep(30) # wait 30 seconds
|
||||
try:
|
||||
try:
|
||||
if self.port == '':
|
||||
srv = poplib.POP3_SSL(self.server) # try it again
|
||||
else:
|
||||
srv = poplib.POP3_SSL(self.server, self.port)
|
||||
except:
|
||||
if self.port == '':
|
||||
srv = poplib.POP3(self.server) # non SSL
|
||||
else:
|
||||
srv = poplib.POP3(self.server, self.port)
|
||||
srv.getwelcome()
|
||||
srv.user(self.user)
|
||||
srv.pass_(self.password)
|
||||
except:
|
||||
print "Error: Cannot connect to POP account: %s. " \
|
||||
"Next try in %s minutes." % (self.server, self.check_interval)
|
||||
srv = None
|
||||
|
||||
return srv # server object
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# accounts.py
|
||||
#
|
||||
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
|
||||
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
from common.keyring import Keyring
|
||||
from daemon.account import Account
|
||||
|
||||
class Accounts:
|
||||
def __init__(self, cfg):
|
||||
self.account = []
|
||||
keyring = Keyring()
|
||||
self.keyring_was_locked = keyring.was_locked
|
||||
|
||||
separator = '|'
|
||||
on_list = cfg.get('account', 'on').split(separator)
|
||||
name_list = cfg.get('account', 'name').split(separator)
|
||||
server_list = cfg.get('account', 'server').split(separator)
|
||||
user_list = cfg.get('account', 'user').split(separator)
|
||||
imap_list = cfg.get('account', 'imap').split(separator)
|
||||
folder_list = cfg.get('account', 'folder').split(separator)
|
||||
port_list = cfg.get('account', 'port').split(separator)
|
||||
check_interval = cfg.get('general', 'check_interval')
|
||||
|
||||
# check if the account list is empty
|
||||
if len(name_list) == 1 and name_list[0] == '':
|
||||
return
|
||||
|
||||
for i in range(len(name_list)): # iterate 0 to nr of elements in name_list
|
||||
on = int(on_list[i])
|
||||
name = name_list[i]
|
||||
if not on or name == '': continue # ignore accounts that are off or have no name
|
||||
server = server_list[i]
|
||||
user = user_list[i]
|
||||
imap = int(imap_list[i])
|
||||
folder = folder_list[i]
|
||||
port = port_list[i]
|
||||
if imap: protocol = 'imap'
|
||||
else: protocol = 'pop'
|
||||
password = keyring.get(protocol, user, server)
|
||||
self.account.append(Account(check_interval, name, server, user, password, imap, folder, port))
|
||||
|
||||
|
||||
def get_count(self, name): # get number of emails for this provider
|
||||
count = 'error'
|
||||
for acc in self.account:
|
||||
if acc.name == name:
|
||||
count = str(acc.mail_count)
|
||||
break
|
||||
if count == 'error':
|
||||
print 'Cannot find account (get_count)'
|
||||
return count
|
||||
@@ -32,8 +32,8 @@ class Idlers:
|
||||
|
||||
|
||||
def run(self):
|
||||
for acc in self._accounts.account:
|
||||
if acc.imap: # TODO : and enable_push
|
||||
for acc in self._accounts:
|
||||
if acc.imap and acc.idle:
|
||||
try:
|
||||
self._new_idler(acc)
|
||||
except:
|
||||
@@ -52,7 +52,7 @@ class Idlers:
|
||||
return
|
||||
|
||||
# Need to get out of AUTH mode.
|
||||
if account.folder:
|
||||
if len(account.folder) > 0:
|
||||
server.select(account.folder)
|
||||
else:
|
||||
server.select("INBOX")
|
||||
|
||||
@@ -187,14 +187,14 @@ class MailChecker:
|
||||
|
||||
def run_user_scripts(self, event, data):
|
||||
if event == "on_mail_check":
|
||||
if self.cfg.get('script', 'script0_on') == '1':
|
||||
if self.cfg.get('script', 'script0_enabled') == '1':
|
||||
script_file = self.cfg.get('script', 'script0_file')
|
||||
if script_file != '' and os.path.exists(script_file):
|
||||
self.pid.append(subprocess.Popen("%s %s" % (script_file, data), shell = True))
|
||||
else:
|
||||
print 'Warning: cannot execute script:', script_file
|
||||
|
||||
if (data != '0') and (self.cfg.get('script', 'script1_on') == '1'):
|
||||
if (data != '0') and (self.cfg.get('script', 'script1_enabled') == '1'):
|
||||
script_file = self.cfg.get('script', 'script1_file')
|
||||
if script_file != '' and os.path.exists(script_file):
|
||||
self.pid.append(subprocess.Popen("%s %s" % (script_file, data), shell = True))
|
||||
|
||||
@@ -41,9 +41,9 @@ class Mails:
|
||||
mail_list = [] # initialize list of mails
|
||||
mail_ids = [] # initialize list of mail ids
|
||||
while not self.is_online(): time.sleep(5) # wait for internet connection
|
||||
filter_on = int(self.cfg.get('filter', 'filter_on')) # get filter switch
|
||||
filter_enabled = bool(int(self.cfg.get('filter', 'filter_enabled'))) # get filter switch
|
||||
|
||||
for acc in self.accounts.account: # loop all email accounts
|
||||
for acc in self.accounts:
|
||||
srv = acc.get_connection() # get server connection for this account
|
||||
if srv == None:
|
||||
continue # continue with next account if server is empty
|
||||
@@ -116,7 +116,7 @@ class Mails:
|
||||
id = str(hash(subject)) # create emergency id
|
||||
|
||||
if id not in mail_ids: # prevent duplicates caused by Gmail labels
|
||||
if not (filter_on and self.in_filter(sender + subject)): # check filter
|
||||
if not (filter_enabled and self.in_filter(sender + subject)): # check filter
|
||||
mail_list.append(Mail(seconds, subject, \
|
||||
sender, datetime, id, acc.name))
|
||||
mail_count += 1 # increment mail counter for this IMAP folder
|
||||
@@ -178,7 +178,7 @@ class Mails:
|
||||
uidl = str(hash(subject)) # create emergency id
|
||||
|
||||
id = acc.user + uidl.split(' ')[2] # create unique id
|
||||
if not (filter_on and self.in_filter(sender + subject)): # check filter
|
||||
if not (filter_enabled and self.in_filter(sender + subject)): # check filter
|
||||
mail_list.append(Mail(seconds, subject, sender, \
|
||||
datetime, id, acc.name))
|
||||
mail_count += 1 # increment mail counter for this IMAP folder
|
||||
|
||||
@@ -29,7 +29,7 @@ import signal
|
||||
|
||||
from common.config import read_cfg, cfg_exists, cfg_folder
|
||||
from common.utils import set_procname
|
||||
from daemon.accounts import Accounts
|
||||
from common.accountlist import AccountList
|
||||
from daemon.mailchecker import MailChecker
|
||||
from daemon.idlers import Idlers
|
||||
|
||||
@@ -91,14 +91,20 @@ def main():
|
||||
print 'Error: Cannot find configuration file. Please run mailnag_config first.'
|
||||
exit(1)
|
||||
|
||||
accounts = Accounts(cfg)
|
||||
accounts = AccountList()
|
||||
accounts.load_from_cfg(cfg, enabled_only = True)
|
||||
|
||||
mailchecker = MailChecker(cfg, accounts)
|
||||
mailchecker.check(True) # immediate check, firstcheck=True
|
||||
|
||||
check_interval = int(cfg.get('general', 'check_interval'))
|
||||
GObject.timeout_add_seconds(60 * check_interval, mailchecker.check)
|
||||
# start polling thread for POP3 accounts and
|
||||
# IMAP accounts without idle support
|
||||
if sum(1 for acc in accounts if ((not acc.imap ) or (acc.imap and not acc.idle))) > 0:
|
||||
mailchecker.check(True) # immediate check, firstcheck=True
|
||||
check_interval = int(cfg.get('general', 'check_interval'))
|
||||
GObject.timeout_add_seconds(60 * check_interval, mailchecker.check)
|
||||
|
||||
if False:
|
||||
# start idler threads for IMAP accounts with idle support
|
||||
if sum(1 for acc in accounts if (acc.imap and acc.idle)) > 0:
|
||||
idlers = Idlers(accounts, mailchecker.check)
|
||||
idlers.run()
|
||||
|
||||
|
||||
@@ -67,67 +67,25 @@
|
||||
<property name="margin_top">6</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<property name="n_rows">7</property>
|
||||
<property name="n_rows">9</property>
|
||||
<property name="n_columns">2</property>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment4">
|
||||
<object class="GtkAlignment" id="alignment8">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label11">
|
||||
<object class="GtkLabel" id="label15">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Accountname:</property>
|
||||
<property name="label" translatable="yes">Port:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label12">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">User:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment6">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Password:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
@@ -146,27 +104,6 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment8">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label15">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Port (optional):</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
@@ -175,23 +112,86 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_name">
|
||||
<object class="GtkAlignment" id="alignment6">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="invisible_char_set">True</property>
|
||||
<signal name="changed" handler="entry_changed" swapped="no"/>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Password:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_user">
|
||||
<object class="GtkAlignment" id="alignment5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label12">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">User:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label11">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Accountname:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_port">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="invisible_char_set">True</property>
|
||||
<property name="placeholder_text">optional</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_server">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
@@ -201,7 +201,7 @@
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
@@ -218,13 +218,13 @@
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_server">
|
||||
<object class="GtkEntry" id="entry_account_user">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
@@ -234,59 +234,34 @@
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_port">
|
||||
<object class="GtkEntry" id="entry_account_name">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="invisible_char_set">True</property>
|
||||
<signal name="changed" handler="entry_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment9">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="top_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="chk_account_imap">
|
||||
<property name="label" translatable="yes">IMAP</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="chk_account_imap_toggled" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment10">
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="left_padding">24</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label17">
|
||||
<object class="GtkLabel" id="label_account_folder">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
@@ -304,11 +279,11 @@
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_account_folder">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="invisible_char_set">True</property>
|
||||
<property name="placeholder_text">optional</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@@ -317,9 +292,81 @@
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="chk_account_push">
|
||||
<property name="label" translatable="yes">Enable Push-IMAP</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">7</property>
|
||||
<property name="width">2</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Account type:</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="cmb_account_type">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<items>
|
||||
<item>POP3</item>
|
||||
<item>IMAP</item>
|
||||
</items>
|
||||
<signal name="changed" handler="account_type_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="chk_account_ssl">
|
||||
<property name="label" translatable="yes">Enable SSL encryption</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">8</property>
|
||||
<property name="width">2</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
|
||||
@@ -623,9 +623,9 @@ Copyright (c) 2011 Ralf Hersel</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="liststore_accounts">
|
||||
<columns>
|
||||
<!-- column-name account_id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name account_on -->
|
||||
<!-- column-name account_obj -->
|
||||
<column type="PyObject"/>
|
||||
<!-- column-name account_enabled -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name account_name -->
|
||||
<column type="gchararray"/>
|
||||
|
||||
Reference in New Issue
Block a user