void nsOutlookMail::OpenMessageStore(CMapiFolder *pNextFolder)
{
  // Open the store specified
  if (pNextFolder->IsStore()) {
    if (!m_mapi.OpenStore(pNextFolder->GetCBEntryID(), pNextFolder->GetEntryID(), &m_lpMdb)) {
      m_lpMdb = NULL;
      IMPORT_LOG0("CMapiApi::OpenStore failed\n");
    }

    return;
  }

  // Check to see if we should open the one and only store
  if (!m_lpMdb) {
    if (m_storeList.GetSize() == 1) {
      CMapiFolder * pFolder = m_storeList.GetItem(0);
      if (pFolder) {
        if (!m_mapi.OpenStore(pFolder->GetCBEntryID(), pFolder->GetEntryID(), &m_lpMdb)) {
          m_lpMdb = NULL;
          IMPORT_LOG0("CMapiApi::OpenStore failed\n");
        }
      }
      else {
        IMPORT_LOG0("Error retrieving the one & only message store\n");
      }
    }
    else {
      IMPORT_LOG0("*** Error importing a folder without a valid message store\n");
    }
  }
}
nsresult nsOutlookMail::ImportAddresses(uint32_t *pCount, uint32_t *pTotal, const PRUnichar *pName, uint32_t id, nsIAddrDatabase *pDb, nsString& errors)
{
  if (id >= (uint32_t)(m_addressList.GetSize())) {
    IMPORT_LOG0("*** Bad address identifier, unable to import\n");
    return NS_ERROR_FAILURE;
  }

  uint32_t  dummyCount = 0;
  if (pCount)
    *pCount = 0;
  else
    pCount = &dummyCount;

  CMapiFolder *pFolder;
  if (id > 0) {
    int32_t idx = (int32_t) id;
    idx--;
    while (idx >= 0) {
      pFolder = m_addressList.GetItem(idx);
      if (pFolder->IsStore()) {
        OpenMessageStore(pFolder);
        break;
      }
      idx--;
    }
  }

  pFolder = m_addressList.GetItem(id);
  OpenMessageStore(pFolder);
  if (!m_lpMdb) {
    IMPORT_LOG1("*** Unable to obtain mapi message store for address book: %S\n", pName);
    return NS_ERROR_FAILURE;
  }

  if (pFolder->IsStore())
    return NS_OK;

  nsresult  rv;

  nsCOMPtr<nsIImportFieldMap>    pFieldMap;

  nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
  if (NS_SUCCEEDED(rv)) {
    rv = impSvc->CreateNewFieldMap(getter_AddRefs(pFieldMap));
  }

  CMapiFolderContents    contents(m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());

  BOOL      done = FALSE;
  ULONG      cbEid;
  LPENTRYID    lpEid;
  ULONG      oType;
  LPMESSAGE    lpMsg;
  nsCString    type;
  LPSPropValue  pVal;
  nsString    subject;

  while (!done) {
    (*pCount)++;

    if (!contents.GetNext(&cbEid, &lpEid, &oType, &done)) {
      IMPORT_LOG1("*** Error iterating address book: %S\n", pName);
      return NS_ERROR_FAILURE;
    }

    if (pTotal && (*pTotal == 0))
      *pTotal = contents.GetCount();

    if (!done && (oType == MAPI_MESSAGE)) {
      if (!m_mapi.OpenMdbEntry(m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
        IMPORT_LOG1("*** Error opening messages in mailbox: %S\n", pName);
        return NS_ERROR_FAILURE;
      }

      // Get the PR_MESSAGE_CLASS attribute,
      // ensure that it is IPM.Contact
      pVal = m_mapi.GetMapiProperty(lpMsg, PR_MESSAGE_CLASS);
      if (pVal) {
        type.Truncate();
        m_mapi.GetStringFromProp(pVal, type);
        if (type.EqualsLiteral("IPM.Contact")) {
          // This is a contact, add it to the address book!
          subject.Truncate();
          pVal = m_mapi.GetMapiProperty(lpMsg, PR_SUBJECT);
          if (pVal)
            m_mapi.GetStringFromProp(pVal, subject);

          nsIMdbRow* newRow = nullptr;
          pDb->GetNewRow(&newRow);
          // FIXME: Check with Candice about releasing the newRow if it
          // isn't added to the database.  Candice's code in nsAddressBook
          // never releases it but that doesn't seem right to me!
          if (newRow) {
            if (BuildCard(subject.get(), pDb, newRow, lpMsg, pFieldMap)) {
              pDb->AddCardRowToDB(newRow);
            }
          }
        }
        else if (type.EqualsLiteral("IPM.DistList"))
        {
          // This is a list/group, add it to the address book!
          subject.Truncate();
          pVal = m_mapi.GetMapiProperty(lpMsg, PR_SUBJECT);
          if (pVal)
            m_mapi.GetStringFromProp(pVal, subject);
          CreateList(subject.get(), pDb, lpMsg, pFieldMap);
        }
      }

      lpMsg->Release();
    }
  }

  rv = pDb->Commit(nsAddrDBCommitType::kLargeCommit);
  return rv;
}
nsresult nsOutlookMail::ImportMailbox(uint32_t *pDoneSoFar, bool *pAbort,
                                      int32_t index, const PRUnichar *pName,
                                      nsIMsgFolder *dstFolder,
                                      int32_t *pMsgCount)
{
  if ((index < 0) || (index >= m_folderList.GetSize())) {
    IMPORT_LOG0("*** Bad mailbox identifier, unable to import\n");
    *pAbort = true;
    return NS_ERROR_FAILURE;
  }

  int32_t    dummyMsgCount = 0;
  if (pMsgCount)
    *pMsgCount = 0;
  else
    pMsgCount = &dummyMsgCount;

  CMapiFolder *pFolder = m_folderList.GetItem(index);
  OpenMessageStore(pFolder);
  if (!m_lpMdb) {
    IMPORT_LOG1("*** Unable to obtain mapi message store for mailbox: %S\n", pName);
    return NS_ERROR_FAILURE;
  }

  if (pFolder->IsStore())
    return NS_OK;

  // now what?
  CMapiFolderContents    contents(m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());

  BOOL    done = FALSE;
  ULONG    cbEid;
  LPENTRYID  lpEid;
  ULONG    oType;
  LPMESSAGE  lpMsg = nullptr;
  ULONG    totalCount;
  double  doneCalc;

  nsCOMPtr<nsIOutputStream> outputStream;
  nsCOMPtr<nsIMsgPluggableStore> msgStore;
  nsresult rv = dstFolder->GetMsgStore(getter_AddRefs(msgStore));
  NS_ENSURE_SUCCESS(rv, rv);

  while (!done) {
    if (!contents.GetNext(&cbEid, &lpEid, &oType, &done)) {
      IMPORT_LOG1("*** Error iterating mailbox: %S\n", pName);
      return NS_ERROR_FAILURE;
    }

    nsCOMPtr<nsIMsgDBHdr> msgHdr;
    bool reusable;

    rv = msgStore->GetNewMsgOutputStream(dstFolder, getter_AddRefs(msgHdr), &reusable,
                                         getter_AddRefs(outputStream));
    totalCount = contents.GetCount();
    doneCalc = *pMsgCount;
    doneCalc /= totalCount;
    doneCalc *= 1000;
    if (pDoneSoFar) {
      *pDoneSoFar = (uint32_t) doneCalc;
      if (*pDoneSoFar > 1000)
        *pDoneSoFar = 1000;
    }

    if (!done && (oType == MAPI_MESSAGE)) {
      if (!m_mapi.OpenMdbEntry(m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
        IMPORT_LOG1("*** Error opening messages in mailbox: %S\n", pName);
        return NS_ERROR_FAILURE;
      }

      // See if it's a drafts folder. Outlook doesn't allow drafts
      // folder to be configured so it's ok to hard code it here.
      nsAutoString folderName(pName);
      nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
      mode = nsIMsgSend::nsMsgSaveAsDraft;
      if (folderName.LowerCaseEqualsLiteral("drafts"))
        mode = nsIMsgSend::nsMsgSaveAsDraft;

      rv = ImportMessage(lpMsg, outputStream, mode);
      if (NS_SUCCEEDED(rv)){ // No errors & really imported
         (*pMsgCount)++;
        msgStore->FinishNewMessage(outputStream, msgHdr);
      }
      else {
        IMPORT_LOG1( "*** Error reading message from mailbox: %S\n", pName);
        msgStore->DiscardNewMessage(outputStream, msgHdr);
      }
      if (!reusable)
        outputStream->Close();
    }
  }

  if (outputStream)
    outputStream->Close();
  return NS_OK;
}
nsresult nsOutlookMail::GetAddressBooks(nsISupportsArray **pArray)
{
  if (!m_haveMapi) {
    IMPORT_LOG0("GetAddressBooks called before Mapi is initialized\n");
    return NS_ERROR_FAILURE;
  }

  nsresult rv = NS_NewISupportsArray(pArray);
  if (NS_FAILED(rv)) {
    IMPORT_LOG0("FAILED to allocate the nsISupportsArray for the address book list\n");
    return rv;
  }

  nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
  if (NS_FAILED(rv))
    return rv;

  m_gotAddresses = true;

  m_addressList.ClearAll();
  m_mapi.Initialize();
  m_mapi.LogOn();
  if (m_storeList.GetSize() == 0)
    m_mapi.IterateStores(m_storeList);

  int i = 0;
  CMapiFolder *pFolder;
  if (m_storeList.GetSize() > 1) {
    while ((pFolder = m_storeList.GetItem(i))) {
      CMapiFolder *pItem = new CMapiFolder(pFolder);
      pItem->SetDepth(1);
      m_addressList.AddItem(pItem);
      if (!m_mapi.GetStoreAddressFolders(pItem->GetCBEntryID(), pItem->GetEntryID(), m_addressList)) {
        IMPORT_LOG1("GetStoreAddressFolders for index %d failed.\n", i);
      }
      i++;
    }
  }
  else {
    if ((pFolder = m_storeList.GetItem(i))) {
      if (!m_mapi.GetStoreAddressFolders(pFolder->GetCBEntryID(), pFolder->GetEntryID(), m_addressList)) {
        IMPORT_LOG1("GetStoreFolders for index %d failed.\n", i);
      }
    }
  }

  // Create the mailbox descriptors for the list of folders
  nsIImportABDescriptor *      pID;
  nsISupports *          pInterface;
  nsString            name;
  nsString            list;

  for (i = 0; i < m_addressList.GetSize(); i++) {
    pFolder = m_addressList.GetItem(i);
    if (!pFolder->IsStore()) {
      rv = impSvc->CreateNewABDescriptor(&pID);
      if (NS_SUCCEEDED(rv)) {
        pID->SetIdentifier(i);
        pFolder->GetDisplayName(name);
        MakeAddressBookNameUnique(name, list);
        pID->SetPreferredName(name);
        pID->SetSize(100);
        rv = pID->QueryInterface(kISupportsIID, (void **) &pInterface);
        (*pArray)->AppendElement(pInterface);
        pInterface->Release();
        pID->Release();
      }
    }
  }

  return NS_OK;
}
예제 #5
0
nsresult nsOutlookMail::ImportMailbox( PRUint32 *pDoneSoFar, bool *pAbort, PRInt32 index, const PRUnichar *pName, nsIFile *pDest, PRInt32 *pMsgCount)
{
    if ((index < 0) || (index >= m_folderList.GetSize())) {
        IMPORT_LOG0( "*** Bad mailbox identifier, unable to import\n");
        *pAbort = PR_TRUE;
        return( NS_ERROR_FAILURE);
    }

    PRInt32    dummyMsgCount = 0;
    if (pMsgCount)
        *pMsgCount = 0;
    else
        pMsgCount = &dummyMsgCount;

    CMapiFolder *pFolder = m_folderList.GetItem( index);
    OpenMessageStore( pFolder);
    if (!m_lpMdb) {
        IMPORT_LOG1( "*** Unable to obtain mapi message store for mailbox: %S\n", pName);
        return( NS_ERROR_FAILURE);
    }

    if (pFolder->IsStore())
        return( NS_OK);

    nsresult  rv;

    // now what?
    CMapiFolderContents    contents( m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());

    BOOL    done = FALSE;
    ULONG    cbEid;
    LPENTRYID  lpEid;
    ULONG    oType;
    LPMESSAGE  lpMsg = nsnull;
    ULONG    totalCount;
    PRFloat64  doneCalc;

    nsCOMPtr<nsIOutputStream> destOutputStream;
    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(destOutputStream), pDest, -1, 0600);
    NS_ENSURE_SUCCESS(rv, rv);

    while (!done) {
        if (!contents.GetNext( &cbEid, &lpEid, &oType, &done)) {
            IMPORT_LOG1( "*** Error iterating mailbox: %S\n", pName);
            return( NS_ERROR_FAILURE);
        }

        totalCount = contents.GetCount();
        doneCalc = *pMsgCount;
        doneCalc /= totalCount;
        doneCalc *= 1000;
        if (pDoneSoFar) {
            *pDoneSoFar = (PRUint32) doneCalc;
            if (*pDoneSoFar > 1000)
                *pDoneSoFar = 1000;
        }

        if (!done && (oType == MAPI_MESSAGE)) {
            if (!m_mapi.OpenMdbEntry( m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
                IMPORT_LOG1( "*** Error opening messages in mailbox: %S\n", pName);
                return( NS_ERROR_FAILURE);
            }

            // See if it's a drafts folder. Outlook doesn't allow drafts
            // folder to be configured so it's ok to hard code it here.
            nsAutoString folderName(pName);
            nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
            mode = nsIMsgSend::nsMsgSaveAsDraft;
            if ( folderName.LowerCaseEqualsLiteral("drafts") )
                mode = nsIMsgSend::nsMsgSaveAsDraft;

            rv = ImportMessage(lpMsg, destOutputStream, mode);
            if (NS_SUCCEEDED( rv)) // No errors & really imported
                (*pMsgCount)++;
            else {
                IMPORT_LOG1( "*** Error reading message from mailbox: %S\n", pName);
            }
        }
    }

    return( NS_OK);
}
예제 #6
0
nsresult nsOutlookMail::ImportMailbox( PRUint32 *pDoneSoFar, PRBool *pAbort, PRInt32 index, const PRUnichar *pName, nsIFile *pDest, PRInt32 *pMsgCount)
{
  if ((index < 0) || (index >= m_folderList.GetSize())) {
    IMPORT_LOG0( "*** Bad mailbox identifier, unable to import\n");
    *pAbort = PR_TRUE;
    return( NS_ERROR_FAILURE);
  }

  PRInt32    dummyMsgCount = 0;
  if (pMsgCount)
    *pMsgCount = 0;
  else
    pMsgCount = &dummyMsgCount;

  CMapiFolder *pFolder = m_folderList.GetItem( index);
  OpenMessageStore( pFolder);
  if (!m_lpMdb) {
    IMPORT_LOG1( "*** Unable to obtain mapi message store for mailbox: %S\n", pName);
    return( NS_ERROR_FAILURE);
  }

  if (pFolder->IsStore())
    return( NS_OK);

  nsresult  rv;

  nsOutlookCompose    compose;
  SimpleBufferTonyRCopiedTwice      copy;

  copy.Allocate( kCopyBufferSize);

  // now what?
  CMapiFolderContents    contents( m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());

  BOOL    done = FALSE;
  ULONG    cbEid;
  LPENTRYID  lpEid;
  ULONG    oType;
  LPMESSAGE  lpMsg = nsnull;
  int      attachCount;
  ULONG    totalCount;
  PRFloat64  doneCalc;
  nsCString  fromLine;
  int      fromLen;
  PRBool    lostAttach = PR_FALSE;

  nsCOMPtr<nsIOutputStream> destOutputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(destOutputStream), pDest, -1, 0600);
  NS_ENSURE_SUCCESS(rv, rv);

  while (!done) {
    if (!contents.GetNext( &cbEid, &lpEid, &oType, &done)) {
      IMPORT_LOG1( "*** Error iterating mailbox: %S\n", pName);
      return( NS_ERROR_FAILURE);
    }

    totalCount = contents.GetCount();
    doneCalc = *pMsgCount;
    doneCalc /= totalCount;
    doneCalc *= 1000;
    if (pDoneSoFar) {
      *pDoneSoFar = (PRUint32) doneCalc;
      if (*pDoneSoFar > 1000)
        *pDoneSoFar = 1000;
    }

    if (!done && (oType == MAPI_MESSAGE)) {
      if (!m_mapi.OpenMdbEntry( m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
        IMPORT_LOG1( "*** Error opening messages in mailbox: %S\n", pName);
        return( NS_ERROR_FAILURE);
      }

      CMapiMessage  msg( lpMsg);

      BOOL bResult = msg.FetchHeaders();
      if (bResult)
        bResult = msg.FetchBody();
      if (bResult)
        fromLine = msg.GetFromLine( fromLen);

      attachCount = msg.CountAttachments();
      BuildAttachments( msg, attachCount);

      if (!bResult) {
        IMPORT_LOG1( "*** Error reading message from mailbox: %S\n", pName);
        return( NS_ERROR_FAILURE);
      }

      // --------------------------------------------------------------
      compose.SetBody( msg.GetBody());

      // Need to convert all headers to unicode (for i18n).
      // Init header here since 'composes' is used for all msgs.
      compose.SetHeaders("");

      nsAutoString newheader;
      nsCAutoString tempCStr(msg.GetHeaders(), msg.GetHeaderLen());

      rv = nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(),
        tempCStr, newheader);
      NS_ASSERTION(NS_SUCCEEDED(rv), "failed to convert headers to utf8");
      if (NS_SUCCEEDED(rv))
        compose.SetHeaders(NS_ConvertUTF16toUTF8(newheader).get());

      compose.SetAttachments( &m_attachments);

      // See if it's a drafts folder. Outlook doesn't allow drafts
      // folder to be configured so it's ok to hard code it here.
      nsAutoString folderName(pName);
      nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
      mode = nsIMsgSend::nsMsgSaveAsDraft;
      if ( folderName.LowerCaseEqualsLiteral("drafts") )
        mode = nsIMsgSend::nsMsgSaveAsDraft;

      /*
      If I can't get no headers,
      I can't get no satisfaction
      */
      if (msg.GetHeaderLen()) {
        nsCAutoString cType;
        SetDefaultContentType(msg, cType);
        nsCOMPtr<nsIFile> compositionFile;
        rv = compose.SendTheMessage(mode, cType, getter_AddRefs(compositionFile));
        if (NS_SUCCEEDED( rv)) {
          rv = compose.CopyComposedMessage( fromLine, compositionFile, destOutputStream, copy);
          DeleteFile( compositionFile);
          if (NS_FAILED( rv)) {
            IMPORT_LOG0( "*** Error copying composed message to destination mailbox\n");
            return( rv);
          }
          (*pMsgCount)++;
        }
      }
      else
        rv = NS_OK;

      // The following code to write msg to folder when compose.SendTheMessage() fails is commented
      // out for now because the code doesn't handle attachments and users will complain anyway so
      // until we fix the code to handle all kinds of msgs correctly we should not even make users
      // think that all msgs are imported ok. This will also help users to identify which msgs are
      // not imported and help to debug the problem.
#if 0
      if (NS_FAILED( rv)) {

        /* NS_PRECONDITION( FALSE, "Manual breakpoint"); */

        IMPORT_LOG1( "Message #%d failed.\n", (int) (*pMsgCount));
        DumpAttachments();

        // --------------------------------------------------------------

        // This is the OLD way of writing out the message which uses
        // all kinds of crufty old crap for attachments.
        // Since we now use Compose to send attachments,
        // this is only fallback error stuff.

        // Attachments get lost.

        if (attachCount) {
          lostAttach = PR_TRUE;
          attachCount = 0;
        }

        BOOL needsTerminate = FALSE;
        if (!WriteMessage( destOutputStream, &msg, attachCount, &needsTerminate)) {
          IMPORT_LOG0( "*** Error writing message\n");
          *pAbort = PR_TRUE;
          return( NS_ERROR_FAILURE);
        }

        if (needsTerminate) {
          if (!WriteMimeBoundary( destOutputStream, &msg, TRUE)) {
            IMPORT_LOG0( "*** Error writing message mime boundary\n");
            *pAbort = PR_TRUE;
            return( NS_ERROR_FAILURE);
          }
        }
      }
#endif

      // Just for YUCKS, let's try an extra endline
      WriteData( destOutputStream, "\x0D\x0A", 2);
    }
  }

  return( NS_OK);
}