comparison sat/plugins/plugin_misc_imap.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 26edcf3a30eb
children ab2696e34d29
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core.constants import Const as C 21 from sat.core.constants import Const as C
22 from sat.core.log import getLogger 22 from sat.core.log import getLogger
23
23 log = getLogger(__name__) 24 log = getLogger(__name__)
24 from twisted.internet import protocol, defer 25 from twisted.internet import protocol, defer
25 from twisted.cred import portal, checkers, credentials 26 from twisted.cred import portal, checkers, credentials
26 from twisted.cred import error as cred_error 27 from twisted.cred import error as cred_error
27 from twisted.mail import imap4 28 from twisted.mail import imap4
39 C.PI_TYPE: "Misc", 40 C.PI_TYPE: "Misc",
40 C.PI_PROTOCOLS: [], 41 C.PI_PROTOCOLS: [],
41 C.PI_DEPENDENCIES: ["Maildir"], 42 C.PI_DEPENDENCIES: ["Maildir"],
42 C.PI_MAIN: "IMAP_server", 43 C.PI_MAIN: "IMAP_server",
43 C.PI_HANDLER: "no", 44 C.PI_HANDLER: "no",
44 C.PI_DESCRIPTION: _("""Create an Imap server that you can use to read your "normal" type messages""") 45 C.PI_DESCRIPTION: _(
46 """Create an Imap server that you can use to read your "normal" type messages"""
47 ),
45 } 48 }
46 49
47 50
48 class IMAP_server(object): 51 class IMAP_server(object):
49 #TODO: connect profile on mailbox request, once password is accepted 52 # TODO: connect profile on mailbox request, once password is accepted
50 53
51 params = """ 54 params = """
52 <params> 55 <params>
53 <general> 56 <general>
54 <category name="Mail Server"> 57 <category name="Mail Server">
60 63
61 def __init__(self, host): 64 def __init__(self, host):
62 log.info(_("Plugin Imap Server initialization")) 65 log.info(_("Plugin Imap Server initialization"))
63 self.host = host 66 self.host = host
64 67
65 #parameters 68 # parameters
66 host.memory.updateParams(self.params) 69 host.memory.updateParams(self.params)
67 70
68 port = int(self.host.memory.getParamA("IMAP Port", "Mail Server")) 71 port = int(self.host.memory.getParamA("IMAP Port", "Mail Server"))
69 log.info(_("Launching IMAP server on port %d") % port) 72 log.info(_("Launching IMAP server on port %d") % port)
70 73
74 77
75 class Message(object): 78 class Message(object):
76 implements(imap4.IMessage) 79 implements(imap4.IMessage)
77 80
78 def __init__(self, uid, flags, mess_fp): 81 def __init__(self, uid, flags, mess_fp):
79 log.debug('Message Init') 82 log.debug("Message Init")
80 self.uid = uid 83 self.uid = uid
81 self.flags = flags 84 self.flags = flags
82 self.mess_fp = mess_fp 85 self.mess_fp = mess_fp
83 self.message = Parser().parse(mess_fp) 86 self.message = Parser().parse(mess_fp)
84 87
85 def getUID(self): 88 def getUID(self):
86 """Retrieve the unique identifier associated with this message. 89 """Retrieve the unique identifier associated with this message.
87 """ 90 """
88 log.debug('getUID (message)') 91 log.debug("getUID (message)")
89 return self.uid 92 return self.uid
90 93
91 def getFlags(self): 94 def getFlags(self):
92 """Retrieve the flags associated with this message. 95 """Retrieve the flags associated with this message.
93 @return: The flags, represented as strings. 96 @return: The flags, represented as strings.
94 """ 97 """
95 log.debug('getFlags') 98 log.debug("getFlags")
96 return self.flags 99 return self.flags
97 100
98 def getInternalDate(self): 101 def getInternalDate(self):
99 """Retrieve the date internally associated with this message. 102 """Retrieve the date internally associated with this message.
100 @return: An RFC822-formatted date string. 103 @return: An RFC822-formatted date string.
101 """ 104 """
102 log.debug('getInternalDate') 105 log.debug("getInternalDate")
103 return self.message['Date'] 106 return self.message["Date"]
104 107
105 def getHeaders(self, negate, *names): 108 def getHeaders(self, negate, *names):
106 """Retrieve a group of message headers. 109 """Retrieve a group of message headers.
107 @param names: The names of the headers to retrieve or omit. 110 @param names: The names of the headers to retrieve or omit.
108 @param negate: If True, indicates that the headers listed in names 111 @param negate: If True, indicates that the headers listed in names
109 should be omitted from the return value, rather than included. 112 should be omitted from the return value, rather than included.
110 @return: A mapping of header field names to header field values 113 @return: A mapping of header field names to header field values
111 """ 114 """
112 log.debug(u'getHeaders %s - %s' % (negate, names)) 115 log.debug(u"getHeaders %s - %s" % (negate, names))
113 final_dict = {} 116 final_dict = {}
114 to_check = [name.lower() for name in names] 117 to_check = [name.lower() for name in names]
115 for header in self.message.keys(): 118 for header in self.message.keys():
116 if (negate and not header.lower() in to_check) or \ 119 if (negate and not header.lower() in to_check) or (
117 (not negate and header.lower() in to_check): 120 not negate and header.lower() in to_check
121 ):
118 final_dict[header] = self.message[header] 122 final_dict[header] = self.message[header]
119 return final_dict 123 return final_dict
120 124
121 def getBodyFile(self): 125 def getBodyFile(self):
122 """Retrieve a file object containing only the body of this message. 126 """Retrieve a file object containing only the body of this message.
123 """ 127 """
124 log.debug('getBodyFile') 128 log.debug("getBodyFile")
125 return StringIO(self.message.get_payload()) 129 return StringIO(self.message.get_payload())
126 130
127 def getSize(self): 131 def getSize(self):
128 """Retrieve the total size, in octets, of this message. 132 """Retrieve the total size, in octets, of this message.
129 """ 133 """
130 log.debug('getSize') 134 log.debug("getSize")
131 self.mess_fp.seek(0, os.SEEK_END) 135 self.mess_fp.seek(0, os.SEEK_END)
132 return self.mess_fp.tell() 136 return self.mess_fp.tell()
133 137
134 def isMultipart(self): 138 def isMultipart(self):
135 """Indicate whether this message has subparts. 139 """Indicate whether this message has subparts.
136 """ 140 """
137 log.debug('isMultipart') 141 log.debug("isMultipart")
138 return False 142 return False
139 143
140 def getSubPart(self, part): 144 def getSubPart(self, part):
141 """Retrieve a MIME sub-message 145 """Retrieve a MIME sub-message
142 @param part: The number of the part to retrieve, indexed from 0. 146 @param part: The number of the part to retrieve, indexed from 0.
143 @return: The specified sub-part. 147 @return: The specified sub-part.
144 """ 148 """
145 log.debug('getSubPart') 149 log.debug("getSubPart")
146 return TypeError 150 return TypeError
147 151
148 152
149 class SatMailbox(object): 153 class SatMailbox(object):
150 implements(imap4.IMailbox) 154 implements(imap4.IMailbox)
151 155
152 def __init__(self, host, name, profile): 156 def __init__(self, host, name, profile):
153 self.host = host 157 self.host = host
154 self.listeners = set() 158 self.listeners = set()
155 log.debug(u'Mailbox init (%s)' % name) 159 log.debug(u"Mailbox init (%s)" % name)
156 if name != "INBOX": 160 if name != "INBOX":
157 raise imap4.MailboxException("Only INBOX is managed for the moment") 161 raise imap4.MailboxException("Only INBOX is managed for the moment")
158 self.mailbox = self.host.plugins["Maildir"].accessMessageBox(name, self.messageNew, profile) 162 self.mailbox = self.host.plugins["Maildir"].accessMessageBox(
163 name, self.messageNew, profile
164 )
159 165
160 def messageNew(self): 166 def messageNew(self):
161 """Called when a new message is in the mailbox""" 167 """Called when a new message is in the mailbox"""
162 log.debug("messageNew signal received") 168 log.debug("messageNew signal received")
163 nb_messages = self.getMessageCount() 169 nb_messages = self.getMessageCount()
165 listener.newMessages(nb_messages, None) 171 listener.newMessages(nb_messages, None)
166 172
167 def getUIDValidity(self): 173 def getUIDValidity(self):
168 """Return the unique validity identifier for this mailbox. 174 """Return the unique validity identifier for this mailbox.
169 """ 175 """
170 log.debug('getUIDValidity') 176 log.debug("getUIDValidity")
171 return 0 177 return 0
172 178
173 def getUIDNext(self): 179 def getUIDNext(self):
174 """Return the likely UID for the next message added to this mailbox. 180 """Return the likely UID for the next message added to this mailbox.
175 """ 181 """
176 log.debug('getUIDNext') 182 log.debug("getUIDNext")
177 return self.mailbox.getNextUid() 183 return self.mailbox.getNextUid()
178 184
179 def getUID(self, message): 185 def getUID(self, message):
180 """Return the UID of a message in the mailbox 186 """Return the UID of a message in the mailbox
181 @param message: The message sequence number 187 @param message: The message sequence number
182 @return: The UID of the message. 188 @return: The UID of the message.
183 """ 189 """
184 log.debug(u'getUID (%i)' % message) 190 log.debug(u"getUID (%i)" % message)
185 #return self.mailbox.getUid(message-1) #XXX: it seems that this method get uid and not message sequence number 191 # return self.mailbox.getUid(message-1) #XXX: it seems that this method get uid and not message sequence number
186 return message 192 return message
187 193
188 def getMessageCount(self): 194 def getMessageCount(self):
189 """Return the number of messages in this mailbox. 195 """Return the number of messages in this mailbox.
190 """ 196 """
191 log.debug('getMessageCount') 197 log.debug("getMessageCount")
192 ret = self.mailbox.getMessageCount() 198 ret = self.mailbox.getMessageCount()
193 log.debug("count = %i" % ret) 199 log.debug("count = %i" % ret)
194 return ret 200 return ret
195 201
196 def getRecentCount(self): 202 def getRecentCount(self):
197 """Return the number of messages with the 'Recent' flag. 203 """Return the number of messages with the 'Recent' flag.
198 """ 204 """
199 log.debug('getRecentCount') 205 log.debug("getRecentCount")
200 return len(self.mailbox.getMessageIdsWithFlag('\\Recent')) 206 return len(self.mailbox.getMessageIdsWithFlag("\\Recent"))
201 207
202 def getUnseenCount(self): 208 def getUnseenCount(self):
203 """Return the number of messages with the 'Unseen' flag. 209 """Return the number of messages with the 'Unseen' flag.
204 """ 210 """
205 log.debug('getUnseenCount') 211 log.debug("getUnseenCount")
206 return self.getMessageCount() - len(self.mailbox.getMessageIdsWithFlag('\\SEEN')) 212 return self.getMessageCount() - len(self.mailbox.getMessageIdsWithFlag("\\SEEN"))
207 213
208 def isWriteable(self): 214 def isWriteable(self):
209 """Get the read/write status of the mailbox. 215 """Get the read/write status of the mailbox.
210 @return: A true value if write permission is allowed, a false value otherwise. 216 @return: A true value if write permission is allowed, a false value otherwise.
211 """ 217 """
212 log.debug('isWriteable') 218 log.debug("isWriteable")
213 return True 219 return True
214 220
215 def destroy(self): 221 def destroy(self):
216 """Called before this mailbox is deleted, permanently. 222 """Called before this mailbox is deleted, permanently.
217 """ 223 """
218 log.debug('destroy') 224 log.debug("destroy")
219 225
220 def requestStatus(self, names): 226 def requestStatus(self, names):
221 """Return status information about this mailbox. 227 """Return status information about this mailbox.
222 @param names: The status names to return information regarding. 228 @param names: The status names to return information regarding.
223 The possible values for each name are: MESSAGES, RECENT, UIDNEXT, 229 The possible values for each name are: MESSAGES, RECENT, UIDNEXT,
225 @return: A dictionary containing status information about the 231 @return: A dictionary containing status information about the
226 requested names is returned. If the process of looking this 232 requested names is returned. If the process of looking this
227 information up would be costly, a deferred whose callback will 233 information up would be costly, a deferred whose callback will
228 eventually be passed this dictionary is returned instead. 234 eventually be passed this dictionary is returned instead.
229 """ 235 """
230 log.debug('requestStatus') 236 log.debug("requestStatus")
231 return imap4.statusRequestHelper(self, names) 237 return imap4.statusRequestHelper(self, names)
232 238
233 def addListener(self, listener): 239 def addListener(self, listener):
234 """Add a mailbox change listener 240 """Add a mailbox change listener
235 241
236 @type listener: Any object which implements C{IMailboxListener} 242 @type listener: Any object which implements C{IMailboxListener}
237 @param listener: An object to add to the set of those which will 243 @param listener: An object to add to the set of those which will
238 be notified when the contents of this mailbox change. 244 be notified when the contents of this mailbox change.
239 """ 245 """
240 log.debug(u'addListener %s' % listener) 246 log.debug(u"addListener %s" % listener)
241 self.listeners.add(listener) 247 self.listeners.add(listener)
242 248
243 def removeListener(self, listener): 249 def removeListener(self, listener):
244 """Remove a mailbox change listener 250 """Remove a mailbox change listener
245 251
248 @param listener: The object to remove from the set of listeners. 254 @param listener: The object to remove from the set of listeners.
249 255
250 @raise ValueError: Raised when the given object is not a listener for 256 @raise ValueError: Raised when the given object is not a listener for
251 this mailbox. 257 this mailbox.
252 """ 258 """
253 log.debug('removeListener') 259 log.debug("removeListener")
254 if listener in self.listeners: 260 if listener in self.listeners:
255 self.listeners.remove(listener) 261 self.listeners.remove(listener)
256 else: 262 else:
257 raise imap4.MailboxException('Trying to remove an unknown listener') 263 raise imap4.MailboxException("Trying to remove an unknown listener")
258 264
259 def addMessage(self, message, flags=(), date=None): 265 def addMessage(self, message, flags=(), date=None):
260 """Add the given message to this mailbox. 266 """Add the given message to this mailbox.
261 @param message: The RFC822 formatted message 267 @param message: The RFC822 formatted message
262 @param flags: The flags to associate with this message 268 @param flags: The flags to associate with this message
263 @param date: If specified, the date to associate with this 269 @param date: If specified, the date to associate with this
264 @return: A deferred whose callback is invoked with the message 270 @return: A deferred whose callback is invoked with the message
265 id if the message is added successfully and whose errback is 271 id if the message is added successfully and whose errback is
266 invoked otherwise. 272 invoked otherwise.
267 """ 273 """
268 log.debug('addMessage') 274 log.debug("addMessage")
269 raise imap4.MailboxException("Client message addition not implemented yet") 275 raise imap4.MailboxException("Client message addition not implemented yet")
270 276
271 def expunge(self): 277 def expunge(self):
272 """Remove all messages flagged \\Deleted. 278 """Remove all messages flagged \\Deleted.
273 @return: The list of message sequence numbers which were deleted, 279 @return: The list of message sequence numbers which were deleted,
274 or a Deferred whose callback will be invoked with such a list. 280 or a Deferred whose callback will be invoked with such a list.
275 """ 281 """
276 log.debug('expunge') 282 log.debug("expunge")
277 self.mailbox.removeDeleted() 283 self.mailbox.removeDeleted()
278 284
279 def fetch(self, messages, uid): 285 def fetch(self, messages, uid):
280 """Retrieve one or more messages. 286 """Retrieve one or more messages.
281 @param messages: The identifiers of messages to retrieve information 287 @param messages: The identifiers of messages to retrieve information
282 about 288 about
283 @param uid: If true, the IDs specified in the query are UIDs; 289 @param uid: If true, the IDs specified in the query are UIDs;
284 """ 290 """
285 log.debug(u'fetch (%s, %s)' % (messages, uid)) 291 log.debug(u"fetch (%s, %s)" % (messages, uid))
286 if uid: 292 if uid:
287 messages.last = self.mailbox.getMaxUid() 293 messages.last = self.mailbox.getMaxUid()
288 messages.getnext = self.mailbox.getNextExistingUid 294 messages.getnext = self.mailbox.getNextExistingUid
289 for mess_uid in messages: 295 for mess_uid in messages:
290 if mess_uid is None: 296 if mess_uid is None:
291 log.debug('stopping iteration') 297 log.debug("stopping iteration")
292 raise StopIteration 298 raise StopIteration
293 try: 299 try:
294 yield (mess_uid, Message(mess_uid, self.mailbox.getFlagsUid(mess_uid), self.mailbox.getMessageUid(mess_uid))) 300 yield (
301 mess_uid,
302 Message(
303 mess_uid,
304 self.mailbox.getFlagsUid(mess_uid),
305 self.mailbox.getMessageUid(mess_uid),
306 ),
307 )
295 except IndexError: 308 except IndexError:
296 continue 309 continue
297 else: 310 else:
298 messages.last = self.getMessageCount() 311 messages.last = self.getMessageCount()
299 for mess_idx in messages: 312 for mess_idx in messages:
300 if mess_idx > self.getMessageCount(): 313 if mess_idx > self.getMessageCount():
301 raise StopIteration 314 raise StopIteration
302 yield (mess_idx, Message(mess_idx, self.mailbox.getFlags(mess_idx), self.mailbox.getMessage(mess_idx - 1))) 315 yield (
316 mess_idx,
317 Message(
318 mess_idx,
319 self.mailbox.getFlags(mess_idx),
320 self.mailbox.getMessage(mess_idx - 1),
321 ),
322 )
303 323
304 def store(self, messages, flags, mode, uid): 324 def store(self, messages, flags, mode, uid):
305 """Set the flags of one or more messages. 325 """Set the flags of one or more messages.
306 @param messages: The identifiers of the messages to set the flags of. 326 @param messages: The identifiers of the messages to set the flags of.
307 @param flags: The flags to set, unset, or add. 327 @param flags: The flags to set, unset, or add.
314 @return: A dict mapping message sequence numbers to sequences of str 334 @return: A dict mapping message sequence numbers to sequences of str
315 representing the flags set on the message after this operation has 335 representing the flags set on the message after this operation has
316 been performed, or a Deferred whose callback will be invoked with 336 been performed, or a Deferred whose callback will be invoked with
317 such a dict. 337 such a dict.
318 """ 338 """
319 log.debug('store') 339 log.debug("store")
320 340
321 flags = [flag.upper() for flag in flags] 341 flags = [flag.upper() for flag in flags]
322 342
323 def updateFlags(getF, setF): 343 def updateFlags(getF, setF):
324 ret = {} 344 ret = {}
325 for mess_id in messages: 345 for mess_id in messages:
326 if (uid and mess_id is None) or (not uid and mess_id > self.getMessageCount()): 346 if (uid and mess_id is None) or (
347 not uid and mess_id > self.getMessageCount()
348 ):
327 break 349 break
328 _flags = set(getF(mess_id) if mode else []) 350 _flags = set(getF(mess_id) if mode else [])
329 if mode == -1: 351 if mode == -1:
330 _flags.difference_update(set(flags)) 352 _flags.difference_update(set(flags))
331 else: 353 else:
346 else: 368 else:
347 messages.last = self.getMessageCount() 369 messages.last = self.getMessageCount()
348 ret = updateFlags(self.mailbox.getFlags, self.mailbox.setFlags) 370 ret = updateFlags(self.mailbox.getFlags, self.mailbox.setFlags)
349 newFlags = {} 371 newFlags = {}
350 for idx in ret: 372 for idx in ret:
351 #we have to convert idx to uid for the listeners 373 # we have to convert idx to uid for the listeners
352 newFlags[self.mailbox.getUid(idx)] = ret[idx] 374 newFlags[self.mailbox.getUid(idx)] = ret[idx]
353 for listener in self.listeners: 375 for listener in self.listeners:
354 listener.flagsChanged(newFlags) 376 listener.flagsChanged(newFlags)
355 return ret 377 return ret
356 378
357 def getFlags(self): 379 def getFlags(self):
358 """Return the flags defined in this mailbox 380 """Return the flags defined in this mailbox
359 Flags with the \\ prefix are reserved for use as system flags. 381 Flags with the \\ prefix are reserved for use as system flags.
360 @return: A list of the flags that can be set on messages in this mailbox. 382 @return: A list of the flags that can be set on messages in this mailbox.
361 """ 383 """
362 log.debug('getFlags') 384 log.debug("getFlags")
363 return ['\\SEEN', '\\ANSWERED', '\\FLAGGED', '\\DELETED', '\\DRAFT'] # TODO: add '\\RECENT' 385 return [
386 "\\SEEN",
387 "\\ANSWERED",
388 "\\FLAGGED",
389 "\\DELETED",
390 "\\DRAFT",
391 ] # TODO: add '\\RECENT'
364 392
365 def getHierarchicalDelimiter(self): 393 def getHierarchicalDelimiter(self):
366 """Get the character which delimits namespaces for in this mailbox. 394 """Get the character which delimits namespaces for in this mailbox.
367 """ 395 """
368 log.debug('getHierarchicalDelimiter') 396 log.debug("getHierarchicalDelimiter")
369 return '.' 397 return "."
370 398
371 399
372 class ImapSatAccount(imap4.MemoryAccount): 400 class ImapSatAccount(imap4.MemoryAccount):
373 #implements(imap4.IAccount) 401 # implements(imap4.IAccount)
374 402
375 def __init__(self, host, profile): 403 def __init__(self, host, profile):
376 log.debug("ImapAccount init") 404 log.debug("ImapAccount init")
377 self.host = host 405 self.host = host
378 self.profile = profile 406 self.profile = profile
379 imap4.MemoryAccount.__init__(self, profile) 407 imap4.MemoryAccount.__init__(self, profile)
380 self.addMailbox("Inbox") # We only manage Inbox for the moment 408 self.addMailbox("Inbox") # We only manage Inbox for the moment
381 log.debug('INBOX added') 409 log.debug("INBOX added")
382 410
383 def _emptyMailbox(self, name, id): 411 def _emptyMailbox(self, name, id):
384 return SatMailbox(self.host, name, self.profile) 412 return SatMailbox(self.host, name, self.profile)
385 413
386 414
389 417
390 def __init__(self, host): 418 def __init__(self, host):
391 self.host = host 419 self.host = host
392 420
393 def requestAvatar(self, avatarID, mind, *interfaces): 421 def requestAvatar(self, avatarID, mind, *interfaces):
394 log.debug('requestAvatar') 422 log.debug("requestAvatar")
395 profile = avatarID.decode('utf-8') 423 profile = avatarID.decode("utf-8")
396 if imap4.IAccount not in interfaces: 424 if imap4.IAccount not in interfaces:
397 raise NotImplementedError 425 raise NotImplementedError
398 return imap4.IAccount, ImapSatAccount(self.host, profile), lambda: None 426 return imap4.IAccount, ImapSatAccount(self.host, profile), lambda: None
399 427
400 428
402 """ 430 """
403 This credential checker check against SàT's profile and associated jabber's password 431 This credential checker check against SàT's profile and associated jabber's password
404 Check if the profile exists, and if the password is OK 432 Check if the profile exists, and if the password is OK
405 Return the profile as avatarId 433 Return the profile as avatarId
406 """ 434 """
435
407 implements(checkers.ICredentialsChecker) 436 implements(checkers.ICredentialsChecker)
408 credentialInterfaces = (credentials.IUsernamePassword, 437 credentialInterfaces = (
409 credentials.IUsernameHashedPassword) 438 credentials.IUsernamePassword,
439 credentials.IUsernameHashedPassword,
440 )
410 441
411 def __init__(self, host): 442 def __init__(self, host):
412 self.host = host 443 self.host = host
413 444
414 def _cbPasswordMatch(self, matched, profile): 445 def _cbPasswordMatch(self, matched, profile):
415 if matched: 446 if matched:
416 return profile.encode('utf-8') 447 return profile.encode("utf-8")
417 else: 448 else:
418 return failure.Failure(cred_error.UnauthorizedLogin()) 449 return failure.Failure(cred_error.UnauthorizedLogin())
419 450
420 def requestAvatarId(self, credentials): 451 def requestAvatarId(self, credentials):
421 profiles = self.host.memory.getProfilesList() 452 profiles = self.host.memory.getProfilesList()
422 if not credentials.username in profiles: 453 if not credentials.username in profiles:
423 return defer.fail(cred_error.UnauthorizedLogin()) 454 return defer.fail(cred_error.UnauthorizedLogin())
424 d = self.host.memory.asyncGetParamA("Password", "Connection", profile_key=credentials.username) 455 d = self.host.memory.asyncGetParamA(
456 "Password", "Connection", profile_key=credentials.username
457 )
425 d.addCallback(lambda password: credentials.checkPassword(password)) 458 d.addCallback(lambda password: credentials.checkPassword(password))
426 d.addCallback(self._cbPasswordMatch, credentials.username) 459 d.addCallback(self._cbPasswordMatch, credentials.username)
427 return d 460 return d
428 461
429 462