78
115
self.__dialog = MainDialog(self)
82
def login(self, force=False):
84
Login. Try to login from saved key, if this does not exist or
85
force is True, show login dialog
88
self.awn.theme.icon("login")
90
# If we're forcing initiation, just draw the dialog.
91
# We wouldn't be forcing if we want to use the saved login token.
117
# Login from key or dialog
119
login_data = self.get_data_from_key(self.get_key())
121
self.login(login_data)
93
123
self.__dialog.login_form()
94
self.awn.dialog.toggle("main", "show")
98
token = self.awn.settings["login-token"]
99
except: # You know what? too bad. No get_null, no exception handling
102
# Force login if the token is 0, which we take to mean that there is no
103
# login information. We'd delete the key, but that's not always
106
return self.login(True)
108
key = self.awn.keyring.from_token(token)
110
if not self.awn.keyring.unlock():
111
return self.login(True)
113
self.perform_login(key, startup=True)
124
#self.awn.dialog.toggle("main", "show")
126
def init_keyring(self):
128
self.keyring = awnlib.Keyring()
129
except awnlib.KeyringError:
133
'''Get key for backend from Gnome Keyring'''
135
def set_login_settings_to_default():
136
# Default setting means we have no key at all
137
self.awn.settings["login-keyring-token"] = ["Backend", "Keyring", "Token"]
139
if self.keyring is None:
141
if self.back.__name__ == "UnixSpool":
144
# Migration code from old "login-token" to new "login-keyring-token"
145
# To be deleted in the version following version 0.6
147
old_token = self.awn.settings["login-token"]
149
# New installation, token does not exist
153
self.awn.settings["login-keyring-token"] = \
155
gnomekeyring.get_default_keyring_sync(),
157
self.awn.settings["login-token"] = 0
159
keydata = self.awn.settings["login-keyring-token"]
160
if len(keydata) == 0 or len(keydata) > 3:
161
set_login_settings_to_default()
163
if keydata[0] != self.back.__name__:
167
key = self.keyring.from_token(keydata[1], long(keydata[2]))
169
except awnlib.KeyringNoMatchError:
170
set_login_settings_to_default()
173
def get_data_from_key(self, key):
174
# Unix Spool has no password, get data from config
175
if self.back.__name__ == "UnixSpool":
176
path = self.awn.settings["unix-spool"]
177
if path == "default":
178
path = os.path.join("/var/spool/mail/",
179
os.path.split(os.path.expanduser("~"))[1])
182
data['username'] = os.path.split(path)[1]
185
if self.keyring is None or key is None:
190
data['password'] = key.password
191
except awnlib.KeyringError:
192
# Reads data from keyring, probably only KeyringCancelledError,
193
# but return None on any failure
198
def save_key(self, data):
199
'''Save login data for backend in Gnome Keyring'''
201
if self.keyring is None or data is None:
204
# Spool has no password, just save path in config
205
if self.back.__name__ == "UnixSpool":
206
self.awn.settings["unix-spool"] = data["path"]
209
password = data['password']
211
del attrs['password']
212
desc = "Awn Extras/Mail/" + self.back.__name__ + "/" + attrs['username']
217
key = self.keyring.new(
223
self.awn.settings["login-keyring-token"] = [self.back.__name__,
226
except awnlib.KeyringCancelledError:
227
# User cancelled himself
231
key.password = password
234
except awnlib.KeyringCancelledError:
115
237
def logout(self):
116
238
if hasattr(self, "timer"):
117
239
self.timer.stop()
118
240
self.awn.theme.icon("login")
119
self.awn.settings["login-token"] = 0
121
def perform_login(self, key, startup=False):
126
self.mail = self.back(key) # Login
127
except RuntimeError, error:
128
self.__dialog.login_form(True, str(error))
131
self.mail.update() # Update
133
self.__dialog.login_form(True)
136
self.awn.notification.send(_("Mail Applet"),
137
_("Logging in as %s") % key.attrs["username"],
138
self.__getIconPath("login"))
141
self.awn.theme.icon("read")
143
self.awn.settings["login-token"] = key.token
145
self.timer = self.awn.timing.register(self.refresh,
146
self.awn.settings["timeout"] * 60)
147
if startup and self.awn.settings["hide"]:
148
self.awn.timing.delay(self.refresh, 0.1) # init must finish first
150
self.refresh(show=False)
152
def refresh(self, show=True):
241
self.awn.tooltip.set(_("Mail Applet (Click to Log In)"))
243
def login(self, data):
244
# Initialize backend, check login data
245
# IMAP backend already connects to server
247
self.mail = self.back(data)
248
except LoginError, error:
249
self.__dialog.login_form(True, str(error))
255
except LoginError, error:
256
self.__dialog.login_form(True, str(error))
260
self.__dialog.update_email_list()
261
self.awn.notification.send(_("Mail Applet"),
262
_("Logging in as %s") % data["username"],
263
self.__getIconPath("login"))
265
self.timer = self.awn.timing.register(self.refresh,
266
self.awn.settings["timeout"] * 60)
153
269
oldSubjects = self.mail.subjects
156
273
self.mail.update()
157
except RuntimeError, e:
274
except LoginError, e:
158
275
self.awn.theme.icon("error")
160
276
if self.awn.settings["show-network-errors"]:
161
277
self.awn.notification.send(_("Network error - Mail Applet"), str(e), "")
280
self.__dialog.update_email_list()
282
# Notify on new subjects
164
283
diffSubjects = [i for i in self.mail.subjects if i not in oldSubjects]
166
284
if len(diffSubjects) > 0:
167
285
msg = strMailMessages(len(diffSubjects)) + ":\n" + \
168
286
"\n".join(diffSubjects)
170
287
self.awn.notification.send(_("New Mail - Mail Applet"), msg,
171
288
self.__getIconPath("mail-unread"))
173
self.awn.tooltip.set(strMessages(len(self.mail.subjects)))
175
self.awn.theme.icon("unread" if len(self.mail.subjects) > 0 else "read")
177
if self.awn.settings["hide"] and len(self.mail.subjects) == 0:
179
self.awn.dialog.hide()
183
self.__dialog.update_email_list()
185
290
def __getIconPath(self, name):
186
291
path = os.path.join(mail_theme_dir, self.awn.settings["theme"], "scalable", name + ".svg")
187
292
if os.path.isfile(path):
566
682
# Get source of message
686
def drawLoginWindow(cls, *groups):
687
vbox = gtk.VBox(spacing=12)
689
usrE, box = get_label_entry(_("Username:"), *groups)
692
pwdE, box = get_label_entry(_("Password:"), *groups)
693
pwdE.set_visibility(False)
696
return {"layout": vbox, "callback": cls.__submitLoginWindow,
697
"widgets": [usrE, pwdE],
698
"fill-in": cls.__fillinLoginWindow}
701
def __submitLoginWindow(widgets):
702
return {'username': widgets[0].get_text(), \
703
'password': widgets[1].get_text()}
706
def __fillinLoginWindow(widgets, data):
707
widgets[0].set_text(data['username'])
708
widgets[1].set_text(data['password'])
571
712
title = _("Google Apps")
713
fields = ['username', 'domain', 'password']
573
def __init__(self, key):
715
def __init__(self, data):
717
check_login_data(self, self.data)
577
return "https://mail.google.com/a/%s" % self.key.attrs["domain"]
720
return "https://mail.google.com/a/%s" % self.data["domain"]
579
722
def update(self):
581
if not "username" in self.key.attrs or \
582
not "domain" in self.key.attrs:
583
raise RuntimeError(_("Could not log in: No username or domain"))
586
723
f = feedparser.parse(\
587
724
"https://%s%%40%s:%s@mail.google.com/a/%s/feed/atom" \
588
% (self.key.attrs["username"], self.key.attrs["domain"], \
589
self.key.password, self.key.attrs["domain"]))
725
% (self.data["username"], self.data["domain"], \
726
self.data['password'], self.data["domain"]))
591
728
if "bozo_exception" in f.keys():
592
raise RuntimeError(_("There seem to be problems with our \
729
raise LoginError(_("There seem to be problems with our \
593
730
connection to your account. Your best bet is probably \
594
731
to log out and try again."))
595
732
# Hehe, Google is funny. Bozo exception
731
if self.key.attrs["usessl"]:
732
self.server = poplib.POP3_SSL(self.key.attrs["url"])
879
if 'usessl' in self.data and self.data["usessl"]:
880
self.server = poplib.POP3_SSL(self.data["url"])
734
self.server = poplib.POP3(self.key.attrs["url"])
882
self.server = poplib.POP3(self.data["url"])
735
883
except socket.gaierror, message:
736
raise RuntimeError(_("Could not log in: ") + str(message))
884
raise LoginError(_("Could not log in: ") + str(message))
737
885
except socket.error, message:
738
raise RuntimeError(_("Could not log in: ") + str(message))
886
raise LoginError(_("Could not log in: ") + str(message))
741
if not "username" in self.key.attrs:
742
raise RuntimeError(_("Could not log in: No username"))
743
self.server.user(self.key.attrs["username"])
889
self.server.user(self.data["username"])
745
self.server.pass_(self.key.password)
891
self.server.pass_(self.data['password'])
746
892
except poplib.error_proto:
747
raise RuntimeError(_("Could not log in: Username or password incorrect"))
893
raise LoginError(_("Could not log in: Username or password incorrect"))
751
897
messagesInfo = self.server.list()[1][-20:]
752
except poplib.error_proto, err:
753
raise RuntimeError("POP protocol error: %s" % err)
898
except poplib.error_proto, message:
899
raise LoginError(_("Could not log in: ") + str(message))
756
902
for msg in messagesInfo:
809
955
return {"layout": vbox, "callback": cls.__submitLoginWindow,
810
"widgets": [usrE, pwdE, srvE, sslE]}
813
def __submitLoginWindow(widgets, awn):
814
return awn.keyring.new("Mail Applet - %s(%s)" \
815
% (widgets[0].get_text(), "POP"), \
816
widgets[1].get_text(), \
817
{"username": widgets[0].get_text(),
818
"url": widgets[2].get_text(),
819
"usessl": widgets[3].get_active()}, "network")
956
"widgets": [usrE, pwdE, srvE, sslE],
957
"fill-in": cls.__fillinLoginWindow}
960
def __submitLoginWindow(widgets):
961
return {'username': widgets[0].get_text(), \
962
'password': widgets[1].get_text(), \
963
'url': widgets[2].get_text(), \
964
"usessl": widgets[3].get_active()}
967
def __fillinLoginWindow(widgets, data):
968
widgets[0].set_text(data['username'])
969
widgets[1].set_text(data['password'])
970
widgets[2].set_text(data['url'])
971
widgets[3].set_active(data['usessl'])
832
def __init__(self, key):
833
args = key.attrs["url"].split(":")
835
if key.attrs["usessl"]:
836
self.server = imaplib.IMAP4_SSL(*args)
838
self.server = imaplib.IMAP4(*args)
841
self.server.login(key.attrs["username"], key.password)
842
except poplib.error_proto:
843
raise RuntimeError(_("Could not log in"))
983
fields = ['username', 'url', 'usessl', 'password']
984
optional = ['folder']
986
def __init__(self, data):
988
check_login_data(self, self.data)
989
args = self.data["url"].split(":")
992
if self.data["usessl"]:
993
self.server = imaplib.IMAP4_SSL(*args)
995
self.server = imaplib.IMAP4(*args)
996
except imaplib.socket.error:
997
raise LoginError(_("Server did not respond"))
1000
self.server.login(self.data["username"], self.data['password'])
1001
except imaplib.IMAP4.error:
1002
raise LoginError(_("Could not log in"))
845
1004
mboxs = [i.split(")")[1].split(" ", 2)[2].strip('"') for i in self.server.list()[1]]
846
self.box = key.attrs["folder"]
1005
self.box = self.data["folder"]
848
1007
if self.box not in mboxs and self.box != "":
849
raise RuntimeError(_("Folder does not exst"))
1008
raise LoginError(_("Folder does not exst"))
851
1010
if self.box != "":
852
1011
self.server.select(self.box)
928
1088
folder = "INBOX"
932
return awn.keyring.new("Mail Applet - %s(%s)" \
933
% (widgets[0].get_text(), "IMAP"), \
934
widgets[1].get_text(), \
935
{"username": widgets[0].get_text(),
936
"url": widgets[2].get_text(),
937
"usessl": widgets[3].get_active(),
938
"folder": folder}, "network")
1091
return {'username': widgets[0].get_text(), \
1092
'password': widgets[1].get_text(), \
1093
'url': widgets[2].get_text(), \
1094
'usessl': widgets[3].get_active(), \
1098
def __fillinLoginWindow(widgets, data):
1099
widgets[0].set_text(data['username'])
1100
widgets[1].set_text(data['password'])
1101
widgets[2].set_text(data['url'])
1102
widgets[3].set_active(data['usessl'])
1103
if data['folder'] == "":
1104
widgets[4].set_active(False)
1106
widgets[4].set_active(True)
1107
widgets[5].set_text(data['folder'])
940
1110
if __name__ == "__main__":
941
1111
awnlib.init_start(MailApplet, {