private String executeSimpleCommand(String command, boolean sensitive)
        throws MessagingException {
      try {
        open(Folder.OPEN_MODE_RW);

        if (command != null) {
          if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
            if (sensitive && !K9MailLib.isDebugSensitive()) {
              Log.d(LOG_TAG, ">>> " + "[Command Hidden, Enable Sensitive Debug Logging To Show]");
            } else {
              Log.d(LOG_TAG, ">>> " + command);
            }
          }

          writeLine(command);
        }

        String response = readLine();
        if (response.length() == 0 || response.charAt(0) != '+') {
          throw new Pop3ErrorResponse(response);
        }

        return response;
      } catch (MessagingException me) {
        throw me;
      } catch (Exception e) {
        closeIO();
        throw new MessagingException("Unable to execute POP3 command", e);
      }
    }
 private void indexMessage(int msgNum, Pop3Message message) {
   if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
     Log.d(LOG_TAG, "Adding index for UID " + message.getUid() + " to msgNum " + msgNum);
   }
   mMsgNumToMsgMap.put(msgNum, message);
   mUidToMsgMap.put(message.getUid(), message);
   mUidToMsgNumMap.put(message.getUid(), msgNum);
 }
    private void indexUids(List<String> uids) throws MessagingException, IOException {
      Set<String> unindexedUids = new HashSet<String>();
      for (String uid : uids) {
        if (mUidToMsgMap.get(uid) == null) {
          if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
            Log.d(LOG_TAG, "Need to index UID " + uid);
          }
          unindexedUids.add(uid);
        }
      }
      if (unindexedUids.isEmpty()) {
        return;
      }
      /*
       * If we are missing uids in the cache the only sure way to
       * get them is to do a full UIDL list. A possible optimization
       * would be trying UIDL for the latest X messages and praying.
       */
      String response = executeSimpleCommand(UIDL_COMMAND);
      while ((response = readLine()) != null) {
        if (response.equals(".")) {
          break;
        }
        String[] uidParts = response.split(" +");

        // Ignore messages without a unique-id
        if (uidParts.length >= 2) {
          Integer msgNum = Integer.valueOf(uidParts[0]);
          String msgUid = uidParts[1];
          if (unindexedUids.contains(msgUid)) {
            if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
              Log.d(LOG_TAG, "Got msgNum " + msgNum + " for UID " + msgUid);
            }

            Pop3Message message = mUidToMsgMap.get(msgUid);
            if (message == null) {
              message = new Pop3Message(msgUid, this);
            }
            indexMessage(msgNum, message);
          }
        }
      }
    }
Esempio n. 4
0
  List<ImapResponse> readStatusResponse(
      String tag, String commandToLog, String logId, UntaggedHandler untaggedHandler)
      throws IOException, NegativeImapResponseException {

    List<ImapResponse> responses = new ArrayList<ImapResponse>();

    ImapResponse response;
    do {
      response = readResponse();

      if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) {
        Log.v(LOG_TAG, logId + "<<<" + response);
      }

      if (response.getTag() != null && !response.getTag().equalsIgnoreCase(tag)) {
        Log.w(
            LOG_TAG,
            "After sending tag "
                + tag
                + ", got tag response from previous command "
                + response
                + " for "
                + logId);

        Iterator<ImapResponse> responseIterator = responses.iterator();

        while (responseIterator.hasNext()) {
          ImapResponse delResponse = responseIterator.next();
          if (delResponse.getTag() != null
              || delResponse.size() < 2
              || (!equalsIgnoreCase(delResponse.get(1), Responses.EXISTS)
                  && !equalsIgnoreCase(delResponse.get(1), Responses.EXPUNGE))) {
            responseIterator.remove();
          }
        }
        response = null;
        continue;
      }

      if (untaggedHandler != null) {
        untaggedHandler.handleAsyncUntaggedResponse(response);
      }

      responses.add(response);
    } while (response == null || response.getTag() == null);

    if (response.size() < 1 || !equalsIgnoreCase(response.get(0), Responses.OK)) {
      throw new NegativeImapResponseException(
          "Command: " + commandToLog + "; response: " + response.toString(),
          response.getAlertText());
    }

    return responses;
  }
 private String readLine() throws IOException {
   StringBuilder sb = new StringBuilder();
   int d = mIn.read();
   if (d == -1) {
     throw new IOException("End of stream reached while trying to read line.");
   }
   do {
     if (((char) d) == '\r') {
       continue;
     } else if (((char) d) == '\n') {
       break;
     } else {
       sb.append((char) d);
     }
   } while ((d = mIn.read()) != -1);
   String ret = sb.toString();
   if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
     Log.d(LOG_TAG, "<<< " + ret);
   }
   return ret;
 }
Esempio n. 6
0
  private int getMessageCount(boolean read) throws MessagingException {
    String isRead;
    int messageCount = 0;
    Map<String, String> headers = new HashMap<String, String>();
    String messageBody;

    if (read) {
      isRead = "True";
    } else {
      isRead = "False";
    }

    messageBody = store.getMessageCountXml(isRead);
    headers.put("Brief", "t");
    DataSet dataset = store.processRequest(this.mFolderUrl, "SEARCH", messageBody, headers);
    if (dataset != null) {
      messageCount = dataset.getMessageCount();
    }
    if (K9MailLib.isDebug() && DEBUG_PROTOCOL_WEBDAV) {
      Log.v(LOG_TAG, "Counted messages and webdav returned: " + messageCount);
    }

    return messageCount;
  }
Esempio n. 7
0
  void autoconfigureFolders(final ImapConnection connection)
      throws IOException, MessagingException {
    if (!connection.hasCapability(Capabilities.SPECIAL_USE)) {
      if (K9MailLib.isDebug()) {
        Log.d(LOG_TAG, "No detected folder auto-configuration methods.");
      }
      return;
    }

    if (K9MailLib.isDebug()) {
      Log.d(LOG_TAG, "Folder auto-configuration: Using RFC6154/SPECIAL-USE.");
    }

    String command =
        String.format(
            "LIST (SPECIAL-USE) \"\" %s", ImapUtility.encodeString(getCombinedPrefix() + "*"));
    List<ImapResponse> responses = connection.executeSimpleCommand(command);

    List<ListResponse> listResponses = ListResponse.parseList(responses);

    for (ListResponse listResponse : listResponses) {
      String decodedFolderName;
      try {
        decodedFolderName = folderNameCodec.decode(listResponse.getName());
      } catch (CharacterCodingException e) {
        Log.w(
            LOG_TAG,
            "Folder name not correctly encoded with the UTF-7 variant "
                + "as defined by RFC 3501: "
                + listResponse.getName(),
            e);
        // We currently just skip folders with malformed names.
        continue;
      }

      if (pathDelimiter == null) {
        pathDelimiter = listResponse.getHierarchyDelimiter();
        combinedPrefix = null;
      }

      if (listResponse.hasAttribute("\\Archive") || listResponse.hasAttribute("\\All")) {
        mStoreConfig.setArchiveFolderName(decodedFolderName);
        if (K9MailLib.isDebug()) {
          Log.d(LOG_TAG, "Folder auto-configuration detected Archive folder: " + decodedFolderName);
        }
      } else if (listResponse.hasAttribute("\\Drafts")) {
        mStoreConfig.setDraftsFolderName(decodedFolderName);
        if (K9MailLib.isDebug()) {
          Log.d(LOG_TAG, "Folder auto-configuration detected Drafts folder: " + decodedFolderName);
        }
      } else if (listResponse.hasAttribute("\\Sent")) {
        mStoreConfig.setSentFolderName(decodedFolderName);
        if (K9MailLib.isDebug()) {
          Log.d(LOG_TAG, "Folder auto-configuration detected Sent folder: " + decodedFolderName);
        }
      } else if (listResponse.hasAttribute("\\Junk")) {
        mStoreConfig.setSpamFolderName(decodedFolderName);
        if (K9MailLib.isDebug()) {
          Log.d(LOG_TAG, "Folder auto-configuration detected Spam folder: " + decodedFolderName);
        }
      } else if (listResponse.hasAttribute("\\Trash")) {
        mStoreConfig.setTrashFolderName(decodedFolderName);
        if (K9MailLib.isDebug()) {
          Log.d(LOG_TAG, "Folder auto-configuration detected Trash folder: " + decodedFolderName);
        }
      }
    }
  }
Esempio n. 8
0
File: K9.java Progetto: klonikar/k-9
  @Override
  public void onCreate() {
    if (K9.DEVELOPER_MODE) {
      StrictMode.enableDefaults();
    }

    PRNGFixes.apply();

    super.onCreate();
    app = this;

    sIsDebuggable = ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
    K9MailLib.setDebugStatus(
        new K9MailLib.DebugStatus() {
          @Override
          public boolean enabled() {
            return DEBUG;
          }

          @Override
          public boolean debugSensitive() {
            return DEBUG_SENSITIVE;
          }
        });

    checkCachedDatabaseVersion();

    Preferences prefs = Preferences.getPreferences(this);
    loadPrefs(prefs);

    /*
     * We have to give MimeMessage a temp directory because File.createTempFile(String, String)
     * doesn't work in Android and MimeMessage does not have access to a Context.
     */
    BinaryTempFileBody.setTempDirectory(getCacheDir());

    LocalKeyStore.setKeyStoreLocation(getDir("KeyStore", MODE_PRIVATE).toString());

    /*
     * Enable background sync of messages
     */

    setServicesEnabled(this);
    registerReceivers();

    MessagingController.getInstance(this)
        .addListener(
            new MessagingListener() {
              private void broadcastIntent(
                  String action, Account account, String folder, Message message) {
                try {
                  Uri uri =
                      Uri.parse(
                          "email://messages/"
                              + account.getAccountNumber()
                              + "/"
                              + Uri.encode(folder)
                              + "/"
                              + Uri.encode(message.getUid()));
                  Intent intent = new Intent(action, uri);
                  intent.putExtra(K9.Intents.EmailReceived.EXTRA_ACCOUNT, account.getDescription());
                  intent.putExtra(K9.Intents.EmailReceived.EXTRA_FOLDER, folder);
                  intent.putExtra(K9.Intents.EmailReceived.EXTRA_SENT_DATE, message.getSentDate());
                  intent.putExtra(
                      K9.Intents.EmailReceived.EXTRA_FROM, Address.toString(message.getFrom()));
                  intent.putExtra(
                      K9.Intents.EmailReceived.EXTRA_TO,
                      Address.toString(message.getRecipients(Message.RecipientType.TO)));
                  intent.putExtra(
                      K9.Intents.EmailReceived.EXTRA_CC,
                      Address.toString(message.getRecipients(Message.RecipientType.CC)));
                  intent.putExtra(
                      K9.Intents.EmailReceived.EXTRA_BCC,
                      Address.toString(message.getRecipients(Message.RecipientType.BCC)));
                  intent.putExtra(K9.Intents.EmailReceived.EXTRA_SUBJECT, message.getSubject());
                  intent.putExtra(
                      K9.Intents.EmailReceived.EXTRA_FROM_SELF,
                      account.isAnIdentity(message.getFrom()));
                  K9.this.sendBroadcast(intent);
                  if (K9.DEBUG)
                    Log.d(
                        K9.LOG_TAG,
                        "Broadcasted: action="
                            + action
                            + " account="
                            + account.getDescription()
                            + " folder="
                            + folder
                            + " message uid="
                            + message.getUid());

                } catch (MessagingException e) {
                  Log.w(
                      K9.LOG_TAG,
                      "Error: action="
                          + action
                          + " account="
                          + account.getDescription()
                          + " folder="
                          + folder
                          + " message uid="
                          + message.getUid());
                }
              }

              private void updateUnreadWidget() {
                try {
                  UnreadWidgetProvider.updateUnreadCount(K9.this);
                } catch (Exception e) {
                  if (K9.DEBUG) {
                    Log.e(LOG_TAG, "Error while updating unread widget(s)", e);
                  }
                }
              }

              @Override
              public void synchronizeMailboxRemovedMessage(
                  Account account, String folder, Message message) {
                broadcastIntent(
                    K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
                updateUnreadWidget();
              }

              @Override
              public void messageDeleted(Account account, String folder, Message message) {
                broadcastIntent(
                    K9.Intents.EmailReceived.ACTION_EMAIL_DELETED, account, folder, message);
                updateUnreadWidget();
              }

              @Override
              public void synchronizeMailboxNewMessage(
                  Account account, String folder, Message message) {
                broadcastIntent(
                    K9.Intents.EmailReceived.ACTION_EMAIL_RECEIVED, account, folder, message);
                updateUnreadWidget();
              }

              @Override
              public void folderStatusChanged(
                  Account account, String folderName, int unreadMessageCount) {

                updateUnreadWidget();

                // let observers know a change occurred
                Intent intent = new Intent(K9.Intents.EmailReceived.ACTION_REFRESH_OBSERVER, null);
                intent.putExtra(K9.Intents.EmailReceived.EXTRA_ACCOUNT, account.getDescription());
                intent.putExtra(K9.Intents.EmailReceived.EXTRA_FOLDER, folderName);
                K9.this.sendBroadcast(intent);
              }
            });

    notifyObservers();
  }
    /**
     * Fetches the body of the given message, limiting the downloaded data to the specified number
     * of lines if possible.
     *
     * <p>If lines is -1 the entire message is fetched. This is implemented with RETR for lines = -1
     * or TOP for any other value. If the server does not support TOP, RETR is used instead.
     */
    private void fetchBody(Pop3Message message, int lines) throws IOException, MessagingException {
      String response = null;

      // Try hard to use the TOP command if we're not asked to download the whole message.
      if (lines != -1 && (!mTopNotSupported || mCapabilities.top)) {
        try {
          if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3 && !mCapabilities.top) {
            Log.d(
                LOG_TAG,
                "This server doesn't support the CAPA command. "
                    + "Checking to see if the TOP command is supported nevertheless.");
          }

          response =
              executeSimpleCommand(
                  String.format(
                      Locale.US,
                      TOP_COMMAND + " %d %d",
                      mUidToMsgNumMap.get(message.getUid()),
                      lines));

          // TOP command is supported. Remember this for the next time.
          mCapabilities.top = true;
        } catch (Pop3ErrorResponse e) {
          if (mCapabilities.top) {
            // The TOP command should be supported but something went wrong.
            throw e;
          } else {
            if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
              Log.d(
                  LOG_TAG,
                  "The server really doesn't support the TOP " + "command. Using RETR instead.");
            }

            // Don't try to use the TOP command again.
            mTopNotSupported = true;
          }
        }
      }

      if (response == null) {
        executeSimpleCommand(
            String.format(Locale.US, RETR_COMMAND + " %d", mUidToMsgNumMap.get(message.getUid())));
      }

      try {
        message.parse(new Pop3ResponseInputStream(mIn));

        // TODO: if we've received fewer lines than requested we also have the complete message.
        if (lines == -1 || !mCapabilities.top) {
          message.setFlag(Flag.X_DOWNLOADED_FULL, true);
        }
      } catch (MessagingException me) {
        /*
         * If we're only downloading headers it's possible
         * we'll get a broken MIME message which we're not
         * real worried about. If we've downloaded the body
         * and can't parse it we need to let the user know.
         */
        if (lines == -1) {
          throw me;
        }
      }
    }