async def do_greeting(self) -> Response: preauth_creds = self.config.preauth_credentials if preauth_creds: self._session = await self.login(preauth_creds, self.config) elif socket_info.get().from_localhost: self.auth = self.config.insecure_auth resp_cls = ResponsePreAuth if preauth_creds else ResponseOk return resp_cls(b'*', self.config.greeting, self.capability)
async def do_greeting(self) -> CommandResponse: preauth_creds = self.config.preauth_credentials if preauth_creds: self._session = await self._login(preauth_creds) elif socket_info.get().from_localhost: self.auth = self.config.insecure_auth resp_cls = ResponsePreAuth if preauth_creds else ResponseOk return resp_cls(b'*', self.config.greeting, self.capability)
def _print(cls, log_format: str, output: bytes) -> None: if _log.isEnabledFor(logging.DEBUG): fd = socket_info.get().socket.fileno() lines = cls._lines.split(output) if not lines[-1]: lines = lines[:-1] for line in lines: line_str = str(line, 'utf-8', 'replace') _log.debug(log_format, fd, line_str)
async def run(self, login: LoginProtocol): """Start the socket communication with the server greeting, and then enter the command/response cycle. Args: login: The login/authentication function. """ self._print('%d +++| %s', bytes(socket_info.get())) await self._do_greeting(login) while True: resp: Response try: cmd = await self._read_command() except (ConnectionError, EOFError): break except NotParseable as exc: resp = BadCommandResponse(exc) else: try: if isinstance(cmd, NoOpCommand): resp = NoOpResponse(cmd.tag) elif isinstance(cmd, LogoutCommand): resp = Response(Condition.BYE) elif isinstance(cmd, CapabilityCommand): resp = CapabilitiesResponse(self.capabilities) elif self._session is None: if isinstance(cmd, AuthenticateCommand): resp = await self._do_authenticate(login, cmd) elif isinstance(cmd, StartTLSCommand): resp = await self._do_starttls() else: resp = Response(Condition.NO, text='Bad command.') else: if isinstance(cmd, UnauthenticateCommand): resp = await self._do_unauthenticate() else: assert self._session.filter_set is not None state = FilterState(self._session.filter_set, self.config) resp = await state.run(cmd) except Exception: _log.exception('Unhandled exception') resp = Response(Condition.NO, text='Server error.') await self._write_response(resp) if resp.is_bye: break self._print('%d ---| %s', b'<disconnected>')
async def run(self) -> None: """Start the socket communication with the server greeting, and then enter the command/response cycle. """ self._print('%d +++| %s', bytes(socket_info.get())) greeting = await self._do_greeting() await self._write_response(greeting) while True: resp: Response try: cmd = await self._read_command() except (ConnectionError, EOFError): break except NotParseable as exc: resp = BadCommandResponse(exc) else: try: if isinstance(cmd, NoOpCommand): resp = NoOpResponse(cmd.tag) elif isinstance(cmd, LogoutCommand): resp = Response(Condition.BYE) elif isinstance(cmd, CapabilityCommand): resp = CapabilitiesResponse(self.capabilities) elif self._state is None: if isinstance(cmd, AuthenticateCommand): resp = await self._do_authenticate(cmd) elif isinstance(cmd, StartTLSCommand): resp = await self._do_starttls() else: resp = Response(Condition.NO, text='Bad command.') else: if isinstance(cmd, UnauthenticateCommand): resp = await self._do_unauthenticate() else: resp = await self._state.run(cmd) except Exception: _log.exception('Unhandled exception') resp = Response(Condition.NO, text='Server error.') await self._write_response(resp) if resp.is_bye: break self._print('%d ---| %s', b'<disconnected>')
async def run(self, state: ConnectionState) -> None: """Start the socket communication with the IMAP greeting, and then enter the command/response cycle. Args: state: Defines the interaction with the backend plugin. """ self._print('%d +++| %s', bytes(socket_info.get())) bad_commands = 0 try: greeting = await self._exec(state.do_greeting()) except ResponseError as exc: resp = exc.get_response(b'*') resp.condition = ResponseBye.condition await self.write_response(resp) return else: await self.write_response(greeting) while True: try: cmd = await self.read_command() except (ConnectionError, EOFError): break except CancelledError: await self.send_error_disconnect() break except Exception: await self.send_error_disconnect() raise else: prev_cmd = current_command.set(cmd) try: if isinstance(cmd, AuthenticateCommand): creds = await self.authenticate(state, cmd.mech_name) response, _ = await self._exec( state.do_authenticate(cmd, creds)) elif isinstance(cmd, IdleCommand): response = await self.idle(state, cmd) else: response = await self._exec(state.do_command(cmd)) except ResponseError as exc: resp = exc.get_response(cmd.tag) await self.write_response(resp) if resp.is_terminal: break except AuthenticationError as exc: msg = bytes(str(exc), 'utf-8', 'surrogateescape') resp = ResponseBad(cmd.tag, msg) await self.write_response(resp) except TimeoutError: resp = ResponseNo(cmd.tag, b'Operation timed out.', ResponseCode.of(b'TIMEOUT')) await self.write_response(resp) except CancelledError: await self.send_error_disconnect() break except Exception: await self.send_error_disconnect() raise else: await self.write_response(response) if response.is_bad: bad_commands += 1 if self.bad_command_limit \ and bad_commands >= self.bad_command_limit: msg = b'Too many errors, disconnecting.' response.add_untagged(ResponseBye(msg)) else: bad_commands = 0 if response.is_terminal: break if isinstance(cmd, StartTLSCommand) and state.ssl_context \ and isinstance(response, ResponseOk): await self.start_tls(state.ssl_context) finally: await state.do_cleanup() current_command.reset(prev_cmd) self._print('%d ---| %s', b'<disconnected>')
async def run(self, state: ConnectionState) -> None: """Start the socket communication with the IMAP greeting, and then enter the command/response cycle. Args: state: Defines the interaction with the backend plugin. """ self._print('%d +++| %s', bytes(socket_info.get())) bad_commands = 0 try: greeting = await self._exec(state.do_greeting()) except ResponseError as exc: resp = exc.get_response(b'*') resp.condition = ResponseBye.condition await self.write_response(resp) return else: await self.write_response(greeting) while True: try: cmd = await self.read_command(state) except (ConnectionError, EOFError): break except CancelledError: await self.send_error_disconnect() break except Exception: await self.send_error_disconnect() raise else: prev_cmd = current_command.set(cmd) try: if isinstance(cmd, AuthenticateCommand): creds = await self.authenticate(state, cmd.mech_name) response = await self._exec( state.do_authenticate(cmd, creds)) elif isinstance(cmd, IdleCommand): response = await self.idle(state, cmd) else: response = await self._exec(state.do_command(cmd)) except ResponseError as exc: resp = exc.get_response(cmd.tag) await self.write_response(resp) if resp.is_terminal: break except AuthenticationError as exc: msg = bytes(str(exc), 'utf-8', 'surrogateescape') resp = ResponseBad(cmd.tag, msg) await self.write_response(resp) except TimeoutError: resp = ResponseNo(cmd.tag, b'Operation timed out.', ResponseCode.of(b'TIMEOUT')) await self.write_response(resp) except CancelledError: await self.send_error_disconnect() break except Exception: await self.send_error_disconnect() raise else: await self.write_response(response) if response.is_bad: bad_commands += 1 if self.bad_command_limit \ and bad_commands >= self.bad_command_limit: msg = b'Too many errors, disconnecting.' response.add_untagged(ResponseBye(msg)) else: bad_commands = 0 if response.is_terminal: break if isinstance(cmd, StartTLSCommand) and state.ssl_context \ and isinstance(response, ResponseOk): await self.start_tls(state.ssl_context) finally: await state.do_cleanup() current_command.reset(prev_cmd) self._print('%d ---| %s', b'<disconnected>')