Back to index

lightning-sunbird  0.9+nobinonly
nsOutlookMail.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 /*
00040   Outlook mail import
00041 */
00042 
00043 #include "nsCOMPtr.h"
00044 #include "nscore.h"
00045 #include "nsIServiceManager.h"
00046 #include "nsIImportService.h"
00047 #include "nsIImportFieldMap.h"
00048 #include "nsIImportMailboxDescriptor.h"
00049 #include "nsIImportABDescriptor.h"
00050 #include "nsIImportMimeEncode.h"
00051 #include "nsXPIDLString.h"
00052 #include "nsReadableUtils.h"
00053 #include "nsOutlookStringBundle.h"
00054 #include "nsABBaseCID.h"
00055 #include "nsIAbCard.h"
00056 #include "nsIAddrDatabase.h"
00057 #include "mdb.h"
00058 #include "OutlookDebugLog.h"
00059 #include "nsOutlookMail.h"
00060 #include "nsUnicharUtils.h"
00061 #include "nsMsgUtils.h"
00062 
00063 static NS_DEFINE_CID(kImportMimeEncodeCID,       NS_IMPORTMIMEENCODE_CID);
00064 static NS_DEFINE_IID(kISupportsIID,                     NS_ISUPPORTS_IID);
00065 
00066 /* ------------ Address book stuff ----------------- */
00067 typedef struct {
00068        PRInt32              mozField;
00069        PRInt32              multiLine;
00070        ULONG         mapiTag;
00071 } MAPIFields;
00072 
00073 /*
00074        Fields in MAPI, not in Mozilla
00075        PR_OFFICE_LOCATION
00076        FIX - PR_BIRTHDAY - stored as PT_SYSTIME - FIX to extract for moz address book birthday
00077        PR_DISPLAY_NAME_PREFIX - Mr., Mrs. Dr., etc.
00078        PR_SPOUSE_NAME
00079        PR_GENDER - integer, not text
00080        FIX - PR_CONTACT_EMAIL_ADDRESSES - multiuline strings for email addresses, needs
00081               parsing to get secondary email address for mozilla
00082 */
00083 
00084 #define kIsMultiLine -2
00085 #define       kNoMultiLine  -1
00086 
00087 static MAPIFields    gMapiFields[] = {
00088        { 35, kIsMultiLine, PR_BODY},
00089        { 6, kNoMultiLine, PR_BUSINESS_TELEPHONE_NUMBER},
00090        { 7, kNoMultiLine, PR_HOME_TELEPHONE_NUMBER},
00091        { 25, kNoMultiLine, PR_COMPANY_NAME},
00092        { 23, kNoMultiLine, PR_TITLE},
00093        { 10, kNoMultiLine, PR_CELLULAR_TELEPHONE_NUMBER},
00094        { 9, kNoMultiLine, PR_PAGER_TELEPHONE_NUMBER},
00095        { 8, kNoMultiLine, PR_BUSINESS_FAX_NUMBER},
00096        { 8, kNoMultiLine, PR_HOME_FAX_NUMBER},
00097        { 22, kNoMultiLine, PR_COUNTRY},
00098        { 19, kNoMultiLine, PR_LOCALITY},
00099        { 20, kNoMultiLine, PR_STATE_OR_PROVINCE},
00100        { 17, 18, PR_STREET_ADDRESS},
00101        { 21, kNoMultiLine, PR_POSTAL_CODE},
00102        { 27, kNoMultiLine, PR_PERSONAL_HOME_PAGE},
00103        { 26, kNoMultiLine, PR_BUSINESS_HOME_PAGE},
00104        { 13, kNoMultiLine, PR_HOME_ADDRESS_CITY},
00105        { 16, kNoMultiLine, PR_HOME_ADDRESS_COUNTRY},
00106        { 15, kNoMultiLine, PR_HOME_ADDRESS_POSTAL_CODE},
00107        { 14, kNoMultiLine, PR_HOME_ADDRESS_STATE_OR_PROVINCE},
00108        { 11, 12, PR_HOME_ADDRESS_STREET},
00109        { 24, kNoMultiLine, PR_DEPARTMENT_NAME}
00110 };
00111 /* ---------------------------------------------------- */
00112 
00113 
00114 #define       kCopyBufferSize             (16 * 1024)
00115 
00116 // The email address in Outlook Contacts doesn't have a named 
00117 // property,  we need to use this mapi name ID to access the email 
00118 // The MAPINAMEID for email address has ulKind=MNID_ID
00119 // Outlook stores each email address in two IDs,  32899/32900 for Email1
00120 // 32915/32916 for Email2, 32931/32932 for Email3
00121 // Current we use OUTLOOK_EMAIL1_MAPI_ID1 for primary email
00122 // OUTLOOK_EMAIL2_MAPI_ID1 for secondary email
00123 #define       OUTLOOK_EMAIL1_MAPI_ID1 32899    
00124 #define       OUTLOOK_EMAIL1_MAPI_ID2 32900    
00125 #define       OUTLOOK_EMAIL2_MAPI_ID1 32915   
00126 #define       OUTLOOK_EMAIL2_MAPI_ID2 32916   
00127 #define       OUTLOOK_EMAIL3_MAPI_ID1 32931    
00128 #define       OUTLOOK_EMAIL3_MAPI_ID2 32932  
00129 
00130 nsOutlookMail::nsOutlookMail()
00131 {
00132        m_gotAddresses = PR_FALSE;
00133        m_gotFolders = PR_FALSE;
00134        m_haveMapi = CMapiApi::LoadMapi();
00135        m_lpMdb = NULL;
00136 }
00137 
00138 nsOutlookMail::~nsOutlookMail()
00139 {
00140        EmptyAttachments();
00141 }
00142 
00143 nsresult nsOutlookMail::GetMailFolders( nsISupportsArray **pArray)
00144 {
00145        if (!m_haveMapi) {
00146               IMPORT_LOG0( "GetMailFolders called before Mapi is initialized\n");
00147               return( NS_ERROR_FAILURE);
00148        }
00149 
00150        nsresult rv = NS_NewISupportsArray( pArray);
00151        if (NS_FAILED( rv)) {
00152               IMPORT_LOG0( "FAILED to allocate the nsISupportsArray for the mail folder list\n");
00153               return( rv);
00154        }
00155 
00156        nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
00157        if (NS_FAILED( rv))
00158               return( rv);
00159 
00160        m_gotFolders = PR_TRUE;
00161 
00162        m_folderList.ClearAll();
00163 
00164        m_mapi.Initialize();
00165        m_mapi.LogOn();
00166 
00167        if (m_storeList.GetSize() == 0)
00168               m_mapi.IterateStores( m_storeList);
00169 
00170        int i = 0;
00171        CMapiFolder *pFolder;
00172        if (m_storeList.GetSize() > 1) {
00173               while ((pFolder = m_storeList.GetItem( i))) {
00174                      CMapiFolder *pItem = new CMapiFolder( pFolder);
00175                      pItem->SetDepth( 1);
00176                      m_folderList.AddItem( pItem);
00177                      if (!m_mapi.GetStoreFolders( pItem->GetCBEntryID(), pItem->GetEntryID(), m_folderList, 2)) {
00178                             IMPORT_LOG1( "GetStoreFolders for index %d failed.\n", i);
00179                      }
00180                      i++;
00181               }
00182        }
00183        else {
00184               if ((pFolder = m_storeList.GetItem( i))) {
00185                      if (!m_mapi.GetStoreFolders( pFolder->GetCBEntryID(), pFolder->GetEntryID(), m_folderList, 1)) {
00186                             IMPORT_LOG1( "GetStoreFolders for index %d failed.\n", i);
00187                      }
00188               }
00189        }
00190        
00191        // Create the mailbox descriptors for the list of folders
00192        nsIImportMailboxDescriptor *       pID;
00193        nsISupports *                             pInterface;
00194        nsString                                         name;
00195        nsString                                         uniName;
00196 
00197        for (i = 0; i < m_folderList.GetSize(); i++) {
00198               pFolder = m_folderList.GetItem( i);
00199               rv = impSvc->CreateNewMailboxDescriptor( &pID);
00200               if (NS_SUCCEEDED( rv)) {
00201                      pID->SetDepth( pFolder->GetDepth());
00202                      pID->SetIdentifier( i);
00203 
00204                      pFolder->GetDisplayName( name);
00205                      pID->SetDisplayName(name.get());
00206 
00207                      pID->SetSize( 1000);
00208                      rv = pID->QueryInterface( kISupportsIID, (void **) &pInterface);
00209                      (*pArray)->AppendElement( pInterface);
00210                      pInterface->Release();
00211                      pID->Release();
00212               }
00213        }
00214        
00215        return( NS_OK);      
00216 }
00217 
00218 PRBool nsOutlookMail::IsAddressBookNameUnique( nsString& name, nsString& list)
00219 {
00220        nsString             usedName;
00221        usedName.AppendLiteral("[");
00222        usedName.Append( name);
00223        usedName.AppendLiteral("],");
00224 
00225        return( list.Find( usedName) == -1);
00226 }
00227 
00228 void nsOutlookMail::MakeAddressBookNameUnique( nsString& name, nsString& list)
00229 {
00230        nsString             newName;
00231        int                         idx = 1;
00232 
00233        newName = name;
00234        while (!IsAddressBookNameUnique( newName, list)) {
00235               newName = name;
00236               newName.Append(PRUnichar(' '));
00237               newName.AppendInt( (PRInt32) idx);
00238               idx++;
00239        }
00240        
00241        name = newName;
00242        list.AppendLiteral("[");
00243        list.Append( name);
00244        list.AppendLiteral("],");
00245 }
00246 
00247 nsresult nsOutlookMail::GetAddressBooks( nsISupportsArray **pArray)
00248 {
00249        if (!m_haveMapi) {
00250               IMPORT_LOG0( "GetAddressBooks called before Mapi is initialized\n");
00251               return( NS_ERROR_FAILURE);
00252        }
00253 
00254        nsresult rv = NS_NewISupportsArray( pArray);
00255        if (NS_FAILED( rv)) {
00256               IMPORT_LOG0( "FAILED to allocate the nsISupportsArray for the address book list\n");
00257               return( rv);
00258        }
00259 
00260        nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
00261        if (NS_FAILED( rv))
00262               return( rv);
00263 
00264        m_gotAddresses = PR_TRUE;
00265        
00266        m_addressList.ClearAll();
00267        m_mapi.Initialize();
00268        m_mapi.LogOn();
00269        if (m_storeList.GetSize() == 0)
00270               m_mapi.IterateStores( m_storeList);
00271 
00272        int i = 0;
00273        CMapiFolder *pFolder;
00274        if (m_storeList.GetSize() > 1) {
00275               while ((pFolder = m_storeList.GetItem( i))) {
00276                      CMapiFolder *pItem = new CMapiFolder( pFolder);
00277                      pItem->SetDepth( 1);
00278                      m_addressList.AddItem( pItem);
00279                      if (!m_mapi.GetStoreAddressFolders( pItem->GetCBEntryID(), pItem->GetEntryID(), m_addressList)) {
00280                             IMPORT_LOG1( "GetStoreAddressFolders for index %d failed.\n", i);
00281                      }
00282                      i++;
00283               }
00284        }
00285        else {
00286               if ((pFolder = m_storeList.GetItem( i))) {
00287                      if (!m_mapi.GetStoreAddressFolders( pFolder->GetCBEntryID(), pFolder->GetEntryID(), m_addressList)) {
00288                             IMPORT_LOG1( "GetStoreFolders for index %d failed.\n", i);
00289                      }
00290               }
00291        }
00292        
00293        // Create the mailbox descriptors for the list of folders
00294        nsIImportABDescriptor *                   pID;
00295        nsISupports *                             pInterface;
00296        nsString                                         name;
00297        nsString                                         list;
00298 
00299        for (i = 0; i < m_addressList.GetSize(); i++) {
00300               pFolder = m_addressList.GetItem( i);
00301               if (!pFolder->IsStore()) {
00302                      rv = impSvc->CreateNewABDescriptor( &pID);
00303                      if (NS_SUCCEEDED( rv)) {
00304                             pID->SetIdentifier( i);
00305                             pFolder->GetDisplayName( name);
00306                             MakeAddressBookNameUnique( name, list);
00307                             pID->SetPreferredName(name.get());
00308                             pID->SetSize( 100);
00309                             rv = pID->QueryInterface( kISupportsIID, (void **) &pInterface);
00310                             (*pArray)->AppendElement( pInterface);
00311                             pInterface->Release();
00312                             pID->Release();
00313                      }
00314               }
00315        }
00316        
00317        return( NS_OK);      
00318 }
00319 
00320 
00321 
00322 void nsOutlookMail::OpenMessageStore( CMapiFolder *pNextFolder)
00323 {      
00324        // Open the store specified
00325        if (pNextFolder->IsStore()) {
00326               if (!m_mapi.OpenStore( pNextFolder->GetCBEntryID(), pNextFolder->GetEntryID(), &m_lpMdb)) {
00327                      m_lpMdb = NULL;
00328                      IMPORT_LOG0( "CMapiApi::OpenStore failed\n");
00329               }
00330               
00331               return;
00332        }
00333        
00334        // Check to see if we should open the one and only store
00335        if (!m_lpMdb) {
00336               if (m_storeList.GetSize() == 1) {
00337                      CMapiFolder * pFolder = m_storeList.GetItem( 0);
00338                      if (pFolder) {
00339                             if (!m_mapi.OpenStore( pFolder->GetCBEntryID(), pFolder->GetEntryID(), &m_lpMdb)) {
00340                                    m_lpMdb = NULL;
00341                                    IMPORT_LOG0( "CMapiApi::OpenStore failed\n");
00342                             }
00343                      }
00344                      else {
00345                             IMPORT_LOG0( "Error retrieving the one & only message store\n");
00346                      }
00347               }
00348               else {
00349                      IMPORT_LOG0( "*** Error importing a folder without a valid message store\n");
00350               }
00351        }
00352 }
00353 
00354 void nsOutlookMail::SetDefaultContentType(CMapiMessage &msg, nsCString &cType)
00355 {
00356   cType.Truncate();
00357 
00358   // MAPI doesn't seem to return the entire body data (ie, multiple parts) for
00359   // content type "multipart/alternative", instead it only returns the body data 
00360   // for a particular part. For this reason we'll need to set the content type
00361   // here. Same thing when conten type is not being set at all.
00362   if (msg.GetMimeContentLen())
00363   {
00364     // If content type is not multipart/alternative or mixed or related, return.
00365     // for a multipart alternative with attachments, we get multipart mixed!
00366     if (nsCRT::strcasecmp(msg.GetMimeContent(), "multipart/alternative")
00367       && nsCRT::strcasecmp(msg.GetMimeContent(), "multipart/mixed")
00368       && nsCRT::strcasecmp(msg.GetMimeContent(), "multipart/related"))
00369       return;
00370 
00371     // For multipart/alternative, if no body or boundary,
00372     // or boundary is found in body then return.
00373     const char *body = msg.GetBody();
00374     const char *boundary = msg.GetMimeBoundary();
00375     if (!body || !boundary || strstr(body, boundary))
00376       return;
00377   }
00378   
00379   // Now default the content type to text/html or text/plain
00380   // depending whether or not the body data is html.
00381   cType = msg.BodyIsHtml() ? "text/html" : "text/plain";
00382 }
00383 
00384 nsresult nsOutlookMail::ImportMailbox( PRUint32 *pDoneSoFar, PRBool *pAbort, PRInt32 index, const PRUnichar *pName, nsIFileSpec *pDest, PRInt32 *pMsgCount)
00385 {
00386        if ((index < 0) || (index >= m_folderList.GetSize())) {
00387               IMPORT_LOG0( "*** Bad mailbox identifier, unable to import\n");
00388               *pAbort = PR_TRUE;
00389               return( NS_ERROR_FAILURE);
00390        }
00391        
00392        PRInt32              dummyMsgCount = 0;
00393        if (pMsgCount)
00394               *pMsgCount = 0;
00395        else
00396               pMsgCount = &dummyMsgCount;
00397 
00398        CMapiFolder *pFolder = m_folderList.GetItem( index);
00399        OpenMessageStore( pFolder);
00400        if (!m_lpMdb) {
00401               IMPORT_LOG1( "*** Unable to obtain mapi message store for mailbox: %S\n", pName);
00402               return( NS_ERROR_FAILURE);
00403        }
00404        
00405        if (pFolder->IsStore())
00406               return( NS_OK);
00407        
00408        nsCOMPtr<nsIFileSpec>       compositionFile;
00409        nsresult      rv;
00410        if (NS_FAILED( rv = NS_NewFileSpec( getter_AddRefs( compositionFile)))) {
00411               return( rv);
00412        }
00413        
00414        nsOutlookCompose            compose;
00415        SimpleBufferTonyRCopiedTwice                     copy;
00416 
00417        copy.Allocate( kCopyBufferSize);
00418 
00419        // now what?
00420        CMapiFolderContents         contents( m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());
00421 
00422        BOOL          done = FALSE;
00423        ULONG         cbEid;
00424        LPENTRYID     lpEid;
00425        ULONG         oType;
00426        LPMESSAGE     lpMsg = nsnull;
00427        int                  attachCount;
00428        ULONG         totalCount;
00429        PRFloat64     doneCalc;
00430        nsCString     fromLine;
00431        int                  fromLen;
00432        PRBool        lostAttach = PR_FALSE;
00433 
00434        while (!done) {
00435               if (!contents.GetNext( &cbEid, &lpEid, &oType, &done)) {
00436                      IMPORT_LOG1( "*** Error iterating mailbox: %S\n", pName);
00437                      return( NS_ERROR_FAILURE);
00438               }
00439               
00440               totalCount = contents.GetCount();
00441               doneCalc = *pMsgCount;
00442               doneCalc /= totalCount;
00443               doneCalc *= 1000;
00444               if (pDoneSoFar) {
00445                      *pDoneSoFar = (PRUint32) doneCalc;
00446                      if (*pDoneSoFar > 1000)
00447                             *pDoneSoFar = 1000;
00448               }
00449 
00450               if (!done && (oType == MAPI_MESSAGE)) {
00451                      if (!m_mapi.OpenMdbEntry( m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
00452                             IMPORT_LOG1( "*** Error opening messages in mailbox: %S\n", pName);
00453                             return( NS_ERROR_FAILURE);
00454                      }
00455                      
00456                      CMapiMessage  msg( lpMsg);
00457        
00458                      BOOL bResult = msg.FetchHeaders();
00459                      if (bResult)
00460                             bResult = msg.FetchBody();
00461                      if (bResult)
00462                             fromLine = msg.GetFromLine( fromLen);
00463 
00464                      attachCount = msg.CountAttachments();
00465                      BuildAttachments( msg, attachCount);
00466 
00467                      if (!bResult) {
00468                             IMPORT_LOG1( "*** Error reading message from mailbox: %S\n", pName);
00469                             return( NS_ERROR_FAILURE);
00470                      }
00471                                           
00472                      // --------------------------------------------------------------
00473                      compose.SetBody( msg.GetBody());
00474 
00475       // Need to convert all headers to unicode (for i18n).
00476       // Init header here since 'composes' is used for all msgs.
00477       compose.SetHeaders("");
00478       nsCOMPtr<nsIImportService>   impSvc = do_GetService(NS_IMPORTSERVICE_CONTRACTID);
00479       NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get import service");
00480       if (NS_SUCCEEDED(rv))
00481       {
00482         nsAutoString newheader;
00483         nsCAutoString tempCStr(msg.GetHeaders(), msg.GetHeaderLen());
00484         rv = impSvc->SystemStringToUnicode(tempCStr.get(), newheader);
00485         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to convert headers to utf8");
00486         if (NS_SUCCEEDED(rv))
00487           compose.SetHeaders(NS_ConvertUCS2toUTF8(newheader).get());
00488       }
00489 
00490                      compose.SetAttachments( &m_attachments);
00491 
00492       // See if it's a drafts folder. Outlook doesn't allow drafts
00493       // folder to be configured so it's ok to hard code it here.
00494       nsAutoString folderName(pName);
00495       nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
00496       mode = nsIMsgSend::nsMsgSaveAsDraft;
00497       if ( folderName.LowerCaseEqualsLiteral("drafts") )
00498         mode = nsIMsgSend::nsMsgSaveAsDraft;
00499                      
00500                      /*
00501                             If I can't get no headers,
00502                             I can't get no satisfaction
00503                      */
00504                      if (msg.GetHeaderLen()) {
00505         nsCAutoString cType;
00506         SetDefaultContentType(msg, cType);
00507                             rv = compose.SendTheMessage( compositionFile, mode, cType);
00508                             if (NS_SUCCEEDED( rv)) {
00509                                    rv = compose.CopyComposedMessage( fromLine, compositionFile, pDest, copy);
00510                                    DeleteFile( compositionFile);
00511                                    if (NS_FAILED( rv)) {
00512                                           IMPORT_LOG0( "*** Error copying composed message to destination mailbox\n");
00513                                           return( rv);
00514                                    }
00515           (*pMsgCount)++;
00516                             }
00517                      }
00518                      else
00519                             rv = NS_OK;
00520 
00521       // The following code to write msg to folder when compose.SendTheMessage() fails is commented
00522       // out for now because the code doesn't handle attachments and users will complain anyway so
00523       // until we fix the code to handle all kinds of msgs correctly we should not even make users
00524       // think that all msgs are imported ok. This will also help users to identify which msgs are
00525       // not imported and help to debug the problem.
00526 #if 0
00527                      if (NS_FAILED( rv)) {
00528                             
00529                             /* NS_PRECONDITION( FALSE, "Manual breakpoint"); */
00530 
00531                             IMPORT_LOG1( "Message #%d failed.\n", (int) (*pMsgCount));
00532                             DumpAttachments();
00533        
00534                             // --------------------------------------------------------------
00535 
00536                             // This is the OLD way of writing out the message which uses
00537                             // all kinds of crufty old crap for attachments.
00538                             // Since we now use Compose to send attachments, 
00539                             // this is only fallback error stuff.
00540 
00541                             // Attachments get lost.           
00542 
00543                             if (attachCount) {
00544                                    lostAttach = PR_TRUE;
00545                                    attachCount = 0;
00546                             }
00547 
00548                             BOOL needsTerminate = FALSE;
00549                             if (!WriteMessage( pDest, &msg, attachCount, &needsTerminate)) {
00550                                    IMPORT_LOG0( "*** Error writing message\n");
00551                                    *pAbort = PR_TRUE;
00552                                    return( NS_ERROR_FAILURE);
00553                             }
00554                             
00555                             if (needsTerminate) {
00556                                    if (!WriteMimeBoundary( pDest, &msg, TRUE)) {
00557                                           IMPORT_LOG0( "*** Error writing message mime boundary\n");
00558                                           *pAbort = PR_TRUE;
00559                                           return( NS_ERROR_FAILURE);
00560                                    }
00561                             }
00562                      }
00563 #endif
00564 
00565                      // Just for YUCKS, let's try an extra endline
00566                      WriteData( pDest, "\x0D\x0A", 2);
00567               }
00568        }
00569 
00570        return( NS_OK);
00571 }
00572 
00573 BOOL nsOutlookMail::WriteMessage( nsIFileSpec *pDest, CMapiMessage *pMsg, int& attachCount, BOOL *pTerminate)
00574 {
00575        BOOL          bResult = TRUE;
00576        const char *pData;
00577        int                  len;
00578        BOOL          checkStart = FALSE;
00579 
00580        *pTerminate = FALSE;
00581 
00582        pData = pMsg->GetFromLine( len);
00583        if (pData) {
00584               bResult = WriteData( pDest, pData, len);
00585               checkStart = TRUE;
00586        }
00587 
00588        pData = pMsg->GetHeaders( len);
00589        if (pData && len) {
00590     if (checkStart)
00591       bResult = (EscapeFromSpaceLine(pDest, (char *)pData, pData+len) == NS_OK);
00592     else
00593       bResult = (EscapeFromSpaceLine(pDest, (char *)(pData+1), pData+len-1) == NS_OK);
00594        }
00595 
00596        // Do we need to add any mime headers???
00597        //     Is the message multipart?
00598        //            If so, then we are OK, but need to make sure we add mime
00599        //            header info to the body of the message
00600        //     If not AND we have attachments, then we need to add mime headers.
00601        
00602        BOOL needsMimeHeaders = pMsg->IsMultipart();
00603        if (!needsMimeHeaders && attachCount) {
00604               // if the message already has mime headers
00605               // that aren't multipart then we are in trouble!
00606               // in that case, ditch the attachments...  alternatively, we could
00607               // massage the headers and replace the existing mime headers
00608               // with our own but I think this case is likely not to occur.
00609               if (pMsg->HasContentHeader())
00610                      attachCount = 0;
00611               else {
00612                      if (bResult)
00613                             bResult = WriteMimeMsgHeader( pDest, pMsg);
00614                      needsMimeHeaders = TRUE;
00615               }
00616        }
00617 
00618        if (bResult)
00619               bResult = WriteStr( pDest, "\x0D\x0A");
00620        
00621        if (needsMimeHeaders) {
00622               if (bResult)
00623                      bResult = WriteStr( pDest, "This is a MIME formatted message.\x0D\x0A");
00624               if (bResult)
00625                      bResult = WriteStr( pDest, "\x0D\x0A");
00626               if (bResult)
00627                      bResult = WriteMimeBoundary( pDest, pMsg, FALSE);
00628               if (pMsg->BodyIsHtml()) {
00629                      if (bResult)
00630                             bResult = WriteStr( pDest, "Content-type: text/html\x0D\x0A");
00631               }
00632               else {
00633                      if (bResult)
00634                             bResult = WriteStr( pDest, "Content-type: text/plain\x0D\x0A");
00635               }
00636 
00637               if (bResult)
00638                      bResult = WriteStr( pDest, "\x0D\x0A");
00639        }
00640 
00641 
00642        pData = pMsg->GetBody( len);
00643        if (pData && len) {
00644               if (bResult)
00645                      bResult = (EscapeFromSpaceLine(pDest, (char *)pData, pData+len) == NS_OK);
00646               if ((len < 2) || (pData[len - 1] != 0x0A) || (pData[len - 2] != 0x0D))
00647                      bResult = WriteStr( pDest, "\x0D\x0A");
00648        }
00649 
00650        *pTerminate = needsMimeHeaders;
00651 
00652        return( bResult);
00653 }
00654 
00655 
00656 BOOL nsOutlookMail::WriteData( nsIFileSpec *pDest, const char *pData, PRInt32 len)
00657 {      
00658        PRInt32              written;
00659        nsresult rv = pDest->Write( pData, len, &written);
00660        if (NS_FAILED( rv) || (written != len))
00661               return( FALSE);
00662        return( TRUE);
00663 }
00664 
00665 BOOL nsOutlookMail::WriteStr( nsIFileSpec *pDest, const char *pStr)
00666 {      
00667        PRInt32              written;
00668        PRInt32              len = strlen( pStr);
00669 
00670        nsresult rv = pDest->Write( pStr, len, &written);
00671        if (NS_FAILED( rv) || (written != len))
00672               return( FALSE);
00673        return( TRUE);
00674 }
00675 
00676 BOOL nsOutlookMail::WriteMimeMsgHeader( nsIFileSpec *pDest, CMapiMessage *pMsg)
00677 {
00678        BOOL   bResult = TRUE;
00679        if (!pMsg->HasMimeVersion())
00680               bResult = WriteStr( pDest, "MIME-Version: 1.0\x0D\x0A");
00681        pMsg->GenerateBoundary();
00682        if (bResult)
00683               bResult = WriteStr( pDest, "Content-type: multipart/mixed; boundary=\"");
00684        if (bResult)
00685               bResult = WriteStr( pDest, pMsg->GetMimeBoundary());
00686        if (bResult)
00687               bResult = WriteStr( pDest, "\"\x0D\x0A");
00688 
00689        return( bResult);
00690 }
00691 
00692 BOOL nsOutlookMail::WriteMimeBoundary( nsIFileSpec *pDest, CMapiMessage *pMsg, BOOL terminate)
00693 {
00694        BOOL   bResult = WriteStr( pDest, "--");
00695        if (bResult)
00696               bResult = WriteStr( pDest, pMsg->GetMimeBoundary());
00697        if (terminate && bResult)
00698               bResult = WriteStr( pDest, "--");
00699        if (bResult)
00700               bResult = WriteStr( pDest, "\x0D\x0A");
00701 
00702        return( bResult);
00703 }
00704 
00705 
00706 /*
00707 PRBool nsOutlookMail::WriteAttachment( nsIFileSpec *pDest, CMapiMessage *pMsg)
00708 {
00709        nsCOMPtr<nsIFileSpec> pSpec;
00710        nsresult rv = NS_NewFileSpec( getter_AddRefs( pSpec));
00711        if (NS_FAILED( rv) || !pSpec) {
00712               IMPORT_LOG0( "*** Error creating file spec for attachment\n");
00713               return( PR_FALSE);
00714        }
00715 
00716        if (pMsg->GetAttachFileLoc( pSpec)) {
00717               PRBool isFile = PR_FALSE;
00718               PRBool exists = PR_FALSE;
00719               pSpec->Exists( &exists);
00720               pSpec->IsFile( &isFile);
00721 
00722               if (!exists || !isFile) {
00723                      IMPORT_LOG0( "Attachment file does not exist\n");
00724                      return( PR_TRUE);
00725               }
00726        }
00727        else {
00728               IMPORT_LOG0( "Attachment not processed, unable to obtain file\n");
00729               return( PR_TRUE);
00730        }
00731 
00732        // Set up headers...
00733        BOOL bResult = WriteMimeBoundary( pDest, pMsg, FALSE);
00734        // Now set up the encoder object
00735 
00736        if (bResult) {
00737               nsCOMPtr<nsIImportMimeEncode> encoder = do_CreateInstance( kImportMimeEncodeCID, &rv);
00738               if (NS_FAILED( rv)) {
00739                      IMPORT_LOG0( "*** Error creating mime encoder\n");
00740                      return( PR_FALSE);
00741               }
00742 
00743               encoder->Initialize( pSpec, pDest, pMsg->GetFileName(), pMsg->GetMimeType());
00744               encoder->DoEncoding( &bResult);
00745        }
00746 
00747        return( bResult);
00748 }
00749 */
00750 
00751 
00752 
00753 
00754 
00755 
00756 nsresult nsOutlookMail::DeleteFile( nsIFileSpec *pSpec)
00757 {
00758        PRBool        result;
00759        nsresult      rv = NS_OK;
00760 
00761        result = PR_FALSE;
00762        pSpec->IsStreamOpen( &result);
00763        if (result)
00764               pSpec->CloseStream();
00765        result = PR_FALSE;
00766        pSpec->Exists( &result);
00767        if (result) {
00768               result = PR_FALSE;
00769               pSpec->IsFile( &result);
00770               if (result) {
00771                      nsFileSpec    spec;
00772                      rv = pSpec->GetFileSpec( &spec);
00773                      if (NS_SUCCEEDED( rv))
00774                             spec.Delete( PR_FALSE);
00775               }
00776        }
00777 
00778        return( rv);
00779 }
00780 
00781 void nsOutlookMail::EmptyAttachments( void)
00782 {
00783        PRBool exists;
00784        PRBool isFile;
00785        PRInt32 max = m_attachments.Count();
00786        OutlookAttachment *  pAttach;
00787        for (PRInt32 i = 0; i < max; i++) {
00788               pAttach = (OutlookAttachment *) m_attachments.ElementAt( i);
00789               if (pAttach) {
00790                      if (pAttach->pAttachment) {
00791                             exists = PR_FALSE;
00792                             isFile = PR_FALSE;
00793                             pAttach->pAttachment->Exists( &exists);
00794                             if (exists)
00795                                    pAttach->pAttachment->IsFile( &isFile);
00796                             if (exists && isFile)
00797                                    DeleteFile( pAttach->pAttachment);
00798                             NS_RELEASE( pAttach->pAttachment);
00799                      }
00800                      nsCRT::free( pAttach->description);
00801                      nsCRT::free( pAttach->mimeType);
00802                      delete pAttach;
00803               }
00804        }
00805 
00806        m_attachments.Clear();
00807 }
00808 
00809 void nsOutlookMail::BuildAttachments( CMapiMessage& msg, int count)
00810 {
00811        EmptyAttachments();
00812        if (count) {
00813               nsIFileSpec * pSpec;
00814               nsresult rv;
00815               for (int i = 0; i < count; i++) {
00816                      if (!msg.GetAttachmentInfo( i)) {
00817                             IMPORT_LOG1( "*** Error getting attachment info for #%d\n", i);
00818                      }
00819 
00820                      pSpec = nsnull;
00821                      rv = NS_NewFileSpec( &pSpec);
00822                      if (NS_FAILED( rv) || !pSpec) {
00823                             IMPORT_LOG0( "*** Error creating file spec for attachment\n");
00824                      }
00825                      else {
00826                             if (msg.GetAttachFileLoc( pSpec)) {
00827                                    PRBool isFile = PR_FALSE;
00828                                    PRBool exists = PR_FALSE;
00829                                    pSpec->Exists( &exists);
00830                                    pSpec->IsFile( &isFile);
00831 
00832                                    if (!exists || !isFile) {
00833                                           IMPORT_LOG0( "Attachment file does not exist\n");
00834                                           NS_RELEASE( pSpec);
00835                                    }
00836                                    else {
00837                                           // We have a file spec, now get the other info
00838                                           OutlookAttachment *a = new OutlookAttachment;
00839                                           a->mimeType = nsCRT::strdup( msg.GetMimeType());
00840             // Init description here so that we cacn tell
00841             // if defaul tattacchment is needed later.
00842             a->description = nsnull;  
00843 
00844             const char *fileName = msg.GetFileName();
00845             if (fileName && fileName[0]) {
00846               // Convert description to unicode.
00847               nsCOMPtr<nsIImportService>  impSvc = do_GetService(NS_IMPORTSERVICE_CONTRACTID);
00848               NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get import service");
00849               if (NS_SUCCEEDED(rv)) {
00850                 nsAutoString description;
00851                 rv = impSvc->SystemStringToUnicode(msg.GetFileName(), description);
00852                 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to convert system string to unicode");
00853                 if (NS_SUCCEEDED(rv))
00854                   a->description = ToNewUTF8String(description);
00855               }
00856             }
00857 
00858             // If no description use "Attachment i" format.
00859             if (!a->description) {
00860               nsCAutoString str("Attachment ");
00861                                                  str.AppendInt( (PRInt32) i);
00862                                                  a->description = ToNewCString( str);
00863                                           }
00864 
00865                                           a->pAttachment = pSpec;
00866                                           m_attachments.AppendElement( a);
00867                                    }
00868                             }
00869                             else {
00870                                    NS_RELEASE( pSpec);
00871                             }
00872                      }
00873               }
00874        }
00875 }
00876 
00877 void nsOutlookMail::DumpAttachments( void)
00878 {
00879 #ifdef IMPORT_DEBUG
00880        PRInt32              count = 0;
00881        count = m_attachments.Count();
00882        if (!count) {
00883               IMPORT_LOG0( "*** No Attachments\n");
00884               return;
00885        }
00886        IMPORT_LOG1( "#%d attachments\n", (int) count);
00887 
00888        OutlookAttachment *  pAttach;
00889        
00890        for (PRInt32 i = 0; i < count; i++) {
00891               IMPORT_LOG1( "\tAttachment #%d ---------------\n", (int) i);
00892               pAttach = (OutlookAttachment *) m_attachments.ElementAt( i);
00893               if (pAttach->mimeType)
00894                      IMPORT_LOG1( "\t\tMime type: %s\n", pAttach->mimeType);
00895               if (pAttach->description)
00896                      IMPORT_LOG1( "\t\tDescription: %s\n", pAttach->description);
00897               if (pAttach->pAttachment) {
00898                      nsXPIDLCString       path;
00899                      pAttach->pAttachment->GetNativePath( getter_Copies( path));
00900                      IMPORT_LOG1( "\t\tFile: %s\n", (const char *)path);
00901               }
00902        }
00903 #endif
00904 }
00905 
00906 nsresult nsOutlookMail::ImportAddresses( PRUint32 *pCount, PRUint32 *pTotal, const PRUnichar *pName, PRUint32 id, nsIAddrDatabase *pDb, nsString& errors)
00907 {
00908        if (id >= (PRUint32)(m_addressList.GetSize())) {
00909               IMPORT_LOG0( "*** Bad address identifier, unable to import\n");
00910               return( NS_ERROR_FAILURE);
00911        }
00912        
00913        PRUint32      dummyCount = 0;
00914        if (pCount)
00915               *pCount = 0;
00916        else
00917               pCount = &dummyCount;
00918 
00919        CMapiFolder *pFolder;
00920        if (id > 0) {
00921               PRInt32 idx = (PRInt32) id;
00922               idx--;
00923               while (idx >= 0) {
00924                      pFolder = m_addressList.GetItem( idx);
00925                      if (pFolder->IsStore()) {
00926                             OpenMessageStore( pFolder);
00927                             break;
00928                      }
00929                      idx--;
00930               }
00931        }
00932 
00933        pFolder = m_addressList.GetItem( id);
00934        OpenMessageStore( pFolder);
00935        if (!m_lpMdb) {
00936               IMPORT_LOG1( "*** Unable to obtain mapi message store for address book: %S\n", pName);
00937               return( NS_ERROR_FAILURE);
00938        }
00939        
00940        if (pFolder->IsStore())
00941               return( NS_OK);
00942        
00943        nsresult      rv;
00944 
00945        nsCOMPtr<nsIImportFieldMap>        pFieldMap;
00946 
00947        nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
00948        if (NS_SUCCEEDED( rv)) {
00949               rv = impSvc->CreateNewFieldMap( getter_AddRefs( pFieldMap));
00950        }
00951 
00952        CMapiFolderContents         contents( m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());
00953 
00954        BOOL                 done = FALSE;
00955        ULONG                cbEid;
00956        LPENTRYID            lpEid;
00957        ULONG                oType;
00958        LPMESSAGE            lpMsg;
00959        nsCString            type;
00960        LPSPropValue  pVal;
00961        nsString             subject;
00962 
00963        while (!done) {
00964               (*pCount)++;
00965 
00966               if (!contents.GetNext( &cbEid, &lpEid, &oType, &done)) {
00967                      IMPORT_LOG1( "*** Error iterating address book: %S\n", pName);
00968                      return( NS_ERROR_FAILURE);
00969               }
00970               
00971               if (pTotal && (*pTotal == 0))
00972                      *pTotal = contents.GetCount();
00973 
00974               if (!done && (oType == MAPI_MESSAGE)) {
00975                      if (!m_mapi.OpenMdbEntry( m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
00976                             IMPORT_LOG1( "*** Error opening messages in mailbox: %S\n", pName);
00977                             return( NS_ERROR_FAILURE);
00978                      }
00979 
00980                      // Get the PR_MESSAGE_CLASS attribute,
00981                      // ensure that it is IPM.Contact
00982                      pVal = m_mapi.GetMapiProperty( lpMsg, PR_MESSAGE_CLASS);
00983                      if (pVal) {
00984                             type.Truncate( 0);
00985                             m_mapi.GetStringFromProp( pVal, type);
00986                             if (type.EqualsLiteral("IPM.Contact")) {
00987                                    // This is a contact, add it to the address book!
00988                                    subject.Truncate( 0);
00989                                    pVal = m_mapi.GetMapiProperty( lpMsg, PR_SUBJECT);
00990                                    if (pVal)
00991                                           m_mapi.GetStringFromProp( pVal, subject);
00992                                    
00993                                    nsIMdbRow* newRow = nsnull;
00994                                    pDb->GetNewRow( &newRow); 
00995                                    // FIXME: Check with Candice about releasing the newRow if it
00996                                    // isn't added to the database.  Candice's code in nsAddressBook
00997                                    // never releases it but that doesn't seem right to me!
00998                                    if (newRow) {
00999                                           if (BuildCard( subject.get(), pDb, newRow, lpMsg, pFieldMap)) {
01000                                                  pDb->AddCardRowToDB( newRow);
01001                                           }
01002                                    }
01003                             }
01004         else if (type.EqualsLiteral("IPM.DistList"))
01005         {
01006           // This is a list/group, add it to the address book!
01007           subject.Truncate( 0);
01008           pVal = m_mapi.GetMapiProperty( lpMsg, PR_SUBJECT);
01009           if (pVal)
01010             m_mapi.GetStringFromProp( pVal, subject);
01011           CreateList(subject.get(), pDb, lpMsg, pFieldMap);
01012         }
01013                      }                    
01014 
01015                      lpMsg->Release();
01016               }
01017        }
01018 
01019 
01020   rv = pDb->Commit(nsAddrDBCommitType::kLargeCommit);
01021        return rv;
01022 }
01023 nsresult nsOutlookMail::CreateList( const PRUnichar * pName,
01024                                    nsIAddrDatabase *pDb,
01025                                    LPMAPIPROP pUserList,
01026                                    nsIImportFieldMap *pFieldMap)
01027 {
01028   // If no name provided then we're done.
01029   if (!pName || !(*pName))
01030     return NS_OK;
01031   
01032   nsresult rv = NS_ERROR_FAILURE;
01033   // Make sure we have db to work with.
01034   if (!pDb)
01035     return rv;
01036   
01037   nsCOMPtr <nsIMdbRow> newListRow;
01038   rv = pDb->GetNewListRow(getter_AddRefs(newListRow));
01039   NS_ENSURE_SUCCESS(rv, rv);
01040   nsCAutoString column;
01041   column.AssignWithConversion(pName);
01042   rv = pDb->AddListName(newListRow, column.get());
01043   NS_ENSURE_SUCCESS(rv, rv);
01044   
01045   HRESULT             hr;
01046   LPSPropValue aValue = NULL ;
01047   ULONG aValueCount = 0 ;
01048   
01049   LPSPropTagArray properties = NULL ;
01050   m_mapi.MAPIAllocateBuffer(CbNewSPropTagArray(1),
01051     (void **)&properties) ;
01052   properties->cValues = 1;
01053   properties->aulPropTag [0] = m_mapi.GetEmailPropertyTag(pUserList, 0x8054);
01054   hr = pUserList->GetProps(properties, 0, &aValueCount, &aValue) ;
01055   
01056   SBinaryArray *sa=(SBinaryArray *)&aValue->Value.bin;
01057   if (!sa || !sa->lpbin)
01058     return NS_ERROR_NULL_POINTER;
01059   
01060   LPENTRYID    lpEid;
01061   ULONG        cbEid;
01062   PRInt32        idx;
01063   LPMESSAGE        lpMsg;
01064   nsCString        type;
01065   LPSPropValue    pVal;
01066   nsString        subject;
01067   PRUint32 total;
01068   
01069   
01070   total=sa->cValues;
01071   for (idx = 0;idx < sa->cValues ;idx++)
01072   {
01073     lpEid= (LPENTRYID) sa->lpbin[idx].lpb;
01074     cbEid = sa->lpbin[idx].cb;
01075     
01076     
01077     if (!m_mapi.OpenEntry(cbEid, lpEid, (LPUNKNOWN *) &lpMsg))
01078     {
01079       
01080       IMPORT_LOG1( "*** Error opening messages in mailbox: %S\n", pName);
01081       return( NS_ERROR_FAILURE);
01082     }
01083     // This is a contact, add it to the address book!
01084     subject.Truncate( 0);
01085     pVal = m_mapi.GetMapiProperty( lpMsg, PR_SUBJECT);
01086     if (pVal)
01087       m_mapi.GetStringFromProp( pVal, subject);
01088     
01089     nsCOMPtr <nsIMdbRow> newRow;
01090     nsCOMPtr <nsIMdbRow> oldRow;
01091     pDb->GetNewRow( getter_AddRefs(newRow));
01092     if (newRow) {
01093       if (BuildCard( subject.get(), pDb, newRow, lpMsg, pFieldMap)) 
01094       {
01095         nsCOMPtr <nsIAbCard> userCard;
01096         nsCOMPtr <nsIAbCard> newCard;
01097         userCard = do_CreateInstance(NS_ABMDBCARD_CONTRACTID, &rv);
01098         NS_ENSURE_SUCCESS(rv, rv);
01099         pDb->InitCardFromRow(userCard,newRow);
01100         
01101         //add card to db
01102         PRBool bl=PR_FALSE;
01103         pDb->FindRowByCard(userCard,getter_AddRefs(oldRow));
01104         if (oldRow)
01105         {
01106           newRow = oldRow;
01107         }
01108         else
01109         {
01110           pDb->AddCardRowToDB( newRow);
01111         }
01112         
01113         //add card list
01114         pDb->AddListCardColumnsToRow(userCard,
01115           newListRow,idx+1,
01116           getter_AddRefs(newCard),PR_TRUE);
01117         
01118         
01119       }
01120     }
01121     
01122     
01123   }
01124   
01125   rv = pDb->AddCardRowToDB(newListRow);
01126   NS_ENSURE_SUCCESS(rv, rv);
01127   
01128   rv = pDb->SetListAddressTotal(newListRow, total);
01129   rv = pDb->AddListDirNode(newListRow);
01130   return rv;
01131 }
01132 
01133 
01134 void nsOutlookMail::SanitizeValue( nsString& val)
01135 {
01136        val.ReplaceSubstring(NS_LITERAL_STRING("\x0D\x0A").get(),
01137                          NS_LITERAL_STRING(", ").get());
01138        val.ReplaceChar( 13, ',');
01139        val.ReplaceChar( 10, ',');
01140 }
01141 
01142 void nsOutlookMail::SplitString( nsString& val1, nsString& val2)
01143 {
01144        nsString      temp;
01145 
01146        // Find the last line if there is more than one!
01147        PRInt32 idx = val1.RFind( "\x0D\x0A");
01148        PRInt32       cnt = 2;
01149        if (idx == -1) {
01150               cnt = 1;
01151               idx = val1.RFindChar( 13);
01152        }
01153        if (idx == -1)
01154               idx= val1.RFindChar( 10);
01155        if (idx != -1) {
01156               val1.Right( val2, val1.Length() - idx - cnt);
01157               val1.Left( temp, idx);
01158               val1 = temp;
01159               SanitizeValue( val1);
01160        }
01161 }
01162 
01163 PRBool nsOutlookMail::BuildCard( const PRUnichar *pName, nsIAddrDatabase *pDb, nsIMdbRow *newRow, LPMAPIPROP pUser, nsIImportFieldMap *pFieldMap)
01164 {
01165        
01166        nsString             lastName;
01167        nsString             firstName;
01168        nsString             eMail;
01169        nsString             nickName;
01170        nsString             middleName;
01171        nsString             secondEMail;
01172   ULONG       emailTag;
01173 
01174        LPSPropValue  pProp = m_mapi.GetMapiProperty( pUser, PR_EMAIL_ADDRESS);
01175        if (!pProp) {
01176     emailTag = m_mapi.GetEmailPropertyTag(pUser, OUTLOOK_EMAIL1_MAPI_ID1);
01177     if (emailTag) {
01178            pProp = m_mapi.GetMapiProperty( pUser, emailTag);
01179     }
01180   }
01181        if (pProp) {
01182               m_mapi.GetStringFromProp( pProp, eMail);
01183               SanitizeValue( eMail);
01184        }
01185 
01186   // for secondary email
01187   emailTag = m_mapi.GetEmailPropertyTag(pUser, OUTLOOK_EMAIL2_MAPI_ID1);
01188   if (emailTag) {
01189          pProp = m_mapi.GetMapiProperty( pUser, emailTag);
01190          if (pProp) {
01191                 m_mapi.GetStringFromProp( pProp, secondEMail);
01192                 SanitizeValue( secondEMail);
01193          }
01194   }
01195 
01196        pProp = m_mapi.GetMapiProperty( pUser, PR_GIVEN_NAME);
01197        if (pProp) {
01198               m_mapi.GetStringFromProp( pProp, firstName);
01199               SanitizeValue( firstName);
01200        }
01201        pProp = m_mapi.GetMapiProperty( pUser, PR_SURNAME);
01202        if (pProp) {
01203               m_mapi.GetStringFromProp( pProp, lastName);
01204               SanitizeValue( lastName);
01205        }
01206        pProp = m_mapi.GetMapiProperty( pUser, PR_MIDDLE_NAME);
01207        if (pProp) {
01208               m_mapi.GetStringFromProp( pProp, middleName);
01209               SanitizeValue( middleName);
01210        }
01211        pProp = m_mapi.GetMapiProperty( pUser, PR_NICKNAME);
01212        if (pProp) {
01213               m_mapi.GetStringFromProp( pProp, nickName);
01214               SanitizeValue( nickName);
01215        }
01216        if (firstName.IsEmpty() && lastName.IsEmpty()) {
01217               firstName = pName;
01218        }
01219 
01220        nsString      displayName;
01221        pProp = m_mapi.GetMapiProperty( pUser, PR_DISPLAY_NAME);
01222        if (pProp) {
01223               m_mapi.GetStringFromProp( pProp, displayName);
01224               SanitizeValue( displayName);
01225        }
01226        if (displayName.IsEmpty()) {
01227               if (firstName.IsEmpty())
01228                      displayName = pName;
01229               else {
01230                      displayName = firstName;
01231                      if (!middleName.IsEmpty()) {
01232                             displayName.Append( PRUnichar(' '));
01233                             displayName.Append( middleName);
01234                      }
01235                      if (!lastName.IsEmpty()) {
01236                             displayName.Append( PRUnichar(' '));
01237                             displayName.Append( lastName);
01238                      }
01239               }
01240        }
01241        
01242        // We now have the required fields
01243        // write them out followed by any optional fields!
01244        if (!displayName.IsEmpty()) {
01245               pDb->AddDisplayName( newRow, NS_ConvertUCS2toUTF8(displayName).get());
01246        }
01247        if (!firstName.IsEmpty()) {
01248               pDb->AddFirstName( newRow, NS_ConvertUCS2toUTF8(firstName).get());
01249        }
01250        if (!lastName.IsEmpty()) {
01251               pDb->AddLastName( newRow, NS_ConvertUCS2toUTF8(lastName).get());
01252        }
01253        if (!nickName.IsEmpty()) {
01254               pDb->AddNickName( newRow, NS_ConvertUCS2toUTF8(nickName).get());
01255        }
01256        if (!eMail.IsEmpty()) {
01257               pDb->AddPrimaryEmail( newRow, NS_ConvertUCS2toUTF8(eMail).get());
01258        }
01259        if (!secondEMail.IsEmpty()) {
01260               pDb->Add2ndEmail( newRow, NS_ConvertUCS2toUTF8(secondEMail).get());
01261        }
01262 
01263        // Do all of the extra fields!
01264 
01265        nsString      value;
01266        nsString      line2;
01267 
01268        if (pFieldMap) {
01269               int max = sizeof( gMapiFields) / sizeof( MAPIFields);
01270               for (int i = 0; i < max; i++) {
01271                      pProp = m_mapi.GetMapiProperty( pUser, gMapiFields[i].mapiTag);
01272                      if (pProp) {
01273                             m_mapi.GetStringFromProp( pProp, value);
01274                             if (!value.IsEmpty()) {
01275                                    if (gMapiFields[i].multiLine == kNoMultiLine) {
01276                                           SanitizeValue( value);
01277                                           pFieldMap->SetFieldValue( pDb, newRow, gMapiFields[i].mozField, value.get());
01278                                    }
01279                                    else if (gMapiFields[i].multiLine == kIsMultiLine) {
01280                                           pFieldMap->SetFieldValue( pDb, newRow, gMapiFields[i].mozField, value.get());
01281                                    }
01282                                    else {
01283                                           line2.Truncate();
01284                                           SplitString( value, line2);
01285                                           if (!value.IsEmpty())
01286                                                  pFieldMap->SetFieldValue( pDb, newRow, gMapiFields[i].mozField, value.get());
01287                                           if (!line2.IsEmpty())
01288                                                  pFieldMap->SetFieldValue( pDb, newRow, gMapiFields[i].multiLine, line2.get());
01289                                    }
01290                             }
01291                      }
01292               }
01293        }
01294 
01295 
01296        return( PR_TRUE);
01297 }