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; }
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); }
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); }