public List<ImapResponse> readStatusResponse(String tag, String commandToLog, UntaggedHandler untaggedHandler) throws IOException, NegativeImapResponseException { return responseParser.readStatusResponse(tag, commandToLog, getLogId(), untaggedHandler); }
private void handleConnectException(ConnectException e) throws ConnectException { String message = e.getMessage(); String[] tokens = message.split("-"); if (tokens.length > 1 && tokens[1] != null) { Timber.e(e, "Stripping host/port from ConnectionException for %s", getLogId()); throw new ConnectException(tokens[1].trim()); } else { throw e; } }
public void sendContinuation(String continuation) throws IOException { outputStream.write(continuation.getBytes()); outputStream.write('\r'); outputStream.write('\n'); outputStream.flush(); if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) { Timber.v("%s>>> %s", getLogId(), continuation); } }
protected boolean isIdleCapable() { if (K9MailLib.isDebug()) { Timber.v("Connection %s has %d capabilities", getLogId(), capabilities.size()); } return capabilities.contains(Capabilities.IDLE); }
protected String getLogId() { String id = store.getStoreConfig().toString() + ":" + getServerId() + "/" + Thread.currentThread().getName(); if (connection != null) { id += "/" + connection.getLogId(); } return id; }
private void adjustDNSCacheTTL() { try { Security.setProperty("networkaddress.cache.ttl", "0"); } catch (Exception e) { Timber.w(e, "Could not set DNS ttl to 0 for %s", getLogId()); } try { Security.setProperty("networkaddress.cache.negative.ttl", "0"); } catch (Exception e) { Timber.w(e, "Could not set DNS negative ttl to 0 for %s", getLogId()); } }
private void requestCapabilitiesIfNecessary() throws IOException, MessagingException { if (!capabilities.isEmpty()) { return; } if (K9MailLib.isDebug()) { Timber.i("Did not get capabilities in banner, requesting CAPABILITY for %s", getLogId()); } requestCapabilities(); }
private List<ImapResponse> extractOrRequestCapabilities(List<ImapResponse> responses) throws IOException, MessagingException { CapabilityResponse capabilityResponse = CapabilityResponse.parse(responses); if (capabilityResponse != null) { Set<String> receivedCapabilities = capabilityResponse.getCapabilities(); Timber.d("Saving %s capabilities for %s", receivedCapabilities, getLogId()); capabilities = receivedCapabilities; } else { Timber.i("Did not get capabilities in post-auth banner, requesting CAPABILITY for %s", getLogId()); requestCapabilities(); } return responses; }
public String sendSaslIrCommand(String command, String initialClientResponse, boolean sensitive) throws IOException, MessagingException { try { open(); String tag = Integer.toString(nextCommandTag++); String commandToSend = tag + " " + command + " " + initialClientResponse + "\r\n"; outputStream.write(commandToSend.getBytes()); outputStream.flush(); if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) { if (sensitive && !K9MailLib.isDebugSensitive()) { Timber.v("%s>>> [Command Hidden, Enable Sensitive Debug Logging To Show]", getLogId()); } else { Timber.v("%s>>> %s %s %s", getLogId(), tag, command, initialClientResponse); } } return tag; } catch (IOException | MessagingException e) { close(); throw e; } }
public String sendCommand(String command, boolean sensitive) throws MessagingException, IOException { try { open(); String tag = Integer.toString(nextCommandTag++); String commandToSend = tag + " " + command + "\r\n"; outputStream.write(commandToSend.getBytes()); outputStream.flush(); if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) { if (sensitive && !K9MailLib.isDebugSensitive()) { Timber.v("%s>>> [Command Hidden, Enable Sensitive Debug Logging To Show]", getLogId()); } else { Timber.v("%s>>> %s %s", getLogId(), tag, command); } } return tag; } catch (IOException | MessagingException e) { close(); throw e; } }
private List<ImapResponse> saslAuthPlain() throws IOException, MessagingException { String command = Commands.AUTHENTICATE_PLAIN; String tag = sendCommand(command, false); readContinuationResponse(tag); String credentials = "\000" + settings.getUsername() + "\000" + settings.getPassword(); byte[] encodedCredentials = Base64.encodeBase64(credentials.getBytes()); outputStream.write(encodedCredentials); outputStream.write('\r'); outputStream.write('\n'); outputStream.flush(); try { return responseParser.readStatusResponse(tag, command, getLogId(), null); } catch (NegativeImapResponseException e) { throw handleAuthenticationFailure(e); } }
private void readInitialResponse() throws IOException { ImapResponse initialResponse = responseParser.readResponse(); if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) { Timber.v("%s <<< %s", getLogId(), initialResponse); } extractCapabilities(Collections.singletonList(initialResponse)); }
public ImapResponse readResponse(ImapResponseCallback callback) throws IOException { try { ImapResponse response = responseParser.readResponse(callback); if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) { Timber.v("%s<<<%s", getLogId(), response); } return response; } catch (IOException e) { close(); throw e; } }
private List<ImapResponse> extractCapabilities(List<ImapResponse> responses) { CapabilityResponse capabilityResponse = CapabilityResponse.parse(responses); if (capabilityResponse != null) { Set<String> receivedCapabilities = capabilityResponse.getCapabilities(); if (K9MailLib.isDebug()) { Timber.d("Saving %s capabilities for %s", receivedCapabilities, getLogId()); } capabilities = receivedCapabilities; } return responses; }
private void enableCompression() throws IOException, MessagingException { try { executeSimpleCommand(Commands.COMPRESS_DEFLATE); } catch (NegativeImapResponseException e) { Timber.d(e, "Unable to negotiate compression: "); return; } try { InflaterInputStream input = new InflaterInputStream(socket.getInputStream(), new Inflater(true)); ZOutputStream output = new ZOutputStream(socket.getOutputStream(), JZlib.Z_BEST_SPEED, true); output.setFlushMode(JZlib.Z_PARTIAL_FLUSH); setUpStreamsAndParser(input, output); if (K9MailLib.isDebug()) { Timber.i("Compression enabled for %s", getLogId()); } } catch (IOException e) { close(); Timber.e(e, "Error enabling compression"); } }
private ImapResponse readContinuationResponse(String tag) throws IOException, MessagingException { ImapResponse response; do { response = readResponse(); String responseTag = response.getTag(); if (responseTag != null) { if (responseTag.equalsIgnoreCase(tag)) { throw new MessagingException("Command continuation aborted: " + response); } else { Timber.w("After sending tag %s, got tag response from previous command %s for %s", tag, response, getLogId()); } } } while (!response.isContinuationRequested()); return response; }
public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive) throws IOException, MessagingException { String commandToLog = command; if (sensitive && !K9MailLib.isDebugSensitive()) { commandToLog = "*sensitive*"; } String tag = sendCommand(command, sensitive); try { return responseParser.readStatusResponse(tag, commandToLog, getLogId(), null); } catch (IOException e) { close(); throw e; } }
private List<ImapResponse> authCramMD5() throws MessagingException, IOException { String command = Commands.AUTHENTICATE_CRAM_MD5; String tag = sendCommand(command, false); ImapResponse response = readContinuationResponse(tag); if (response.size() != 1 || !(response.get(0) instanceof String)) { throw new MessagingException("Invalid Cram-MD5 nonce received"); } byte[] b64Nonce = response.getString(0).getBytes(); byte[] b64CRAM = Authentication.computeCramMd5Bytes(settings.getUsername(), settings.getPassword(), b64Nonce); outputStream.write(b64CRAM); outputStream.write('\r'); outputStream.write('\n'); outputStream.flush(); try { return responseParser.readStatusResponse(tag, command, getLogId(), null); } catch (NegativeImapResponseException e) { throw handleAuthenticationFailure(e); } }
private List<ImapResponse> attemptXOAuth2() throws MessagingException, IOException { String token = oauthTokenProvider.getToken(settings.getUsername(), OAuth2TokenProvider.OAUTH2_TIMEOUT); String authString = Authentication.computeXoauth(settings.getUsername(), token); String tag = sendSaslIrCommand(Commands.AUTHENTICATE_XOAUTH2, authString, true); return responseParser.readStatusResponse(tag, Commands.AUTHENTICATE_XOAUTH2, getLogId(), new UntaggedHandler() { @Override public void handleAsyncUntaggedResponse(ImapResponse response) throws IOException { handleXOAuthUntaggedResponse(response); } }); }
private void startTLS() throws IOException, MessagingException, GeneralSecurityException { executeSimpleCommand(Commands.STARTTLS); String host = settings.getHost(); int port = settings.getPort(); String clientCertificateAlias = settings.getClientCertificateAlias(); socket = socketFactory.createSocket(socket, host, port, clientCertificateAlias); configureSocket(); setUpStreamsAndParserFromSocket(); // Per RFC 2595 (3.1): Once TLS has been started, reissue CAPABILITY command if (K9MailLib.isDebug()) { Timber.i("Updating capabilities after STARTTLS for %s", getLogId()); } requestCapabilities(); }