예제 #1
0
        /// <summary>
        /// Allows the user to select recipients from the Simple MAPI address book.</summary>
        /// <returns>
        /// An <see cref="Array"/> of <see cref="MapiAddress"/> instances holding the selected
        /// address book names and the corresponding e-mail addresses.</returns>
        /// <exception cref="MapiException">
        /// <see cref="Mapi.MAPIAddress"/> indicated an error.</exception>
        /// <remarks><para>
        /// <b>Address</b> shows a dialog allowing the user to select e-mail recipients from an
        /// address book, using the Win32 API call <see cref="Mapi.MAPIAddress"/> which is part of
        /// the Simple MAPI protocol. Only the "To" recipient type is available.
        /// </para><para>
        /// <b>Address</b> returns an empty array if the user cancelled the dialog or did not select
        /// any recipients. No <see cref="MapiException"/> is generated in this case.
        /// </para><note type="caution">
        /// <para>Non-Microsoft e-mail clients rarely support <b>MAPIAddress</b>. Some might report
        /// an error while others might show a nonfunctional dialog or return invalid data. There is
        /// no workaround other than using a Microsoft program as the default e-mail client.
        /// </para><para>
        /// Also note that Simple MAPI does not specify the order in which <b>MAPIAddress</b>
        /// returns the selected recipients. <b>Address</b> maintains the selection order for
        /// Outlook Express, but the order may be reversed or completely arbitrary for other e-mail
        /// clients.</para></note></remarks>

        public static MapiAddress[] Address()
        {
            // remember current working directory
            string currentDir = Directory.GetCurrentDirectory();

            // prepare recipient list data
            uint           nNewRecips  = 0;
            SafeMapiHandle lpNewRecips = null;

            try {
                // invoke MAPIAddress to create a recipient list
                MapiFlags flags = MapiFlags.MAPI_LOGON_UI;
                MapiError code  = Mapi.MAPIAddress(UIntPtr.Zero, UIntPtr.Zero, null, 1,
                                                   null, 0, IntPtr.Zero, flags, 0, out nNewRecips, out lpNewRecips);

                // check for user cancellation
                if (code == MapiError.MAPI_E_USER_ABORT)
                {
                    return(new MapiAddress[0]);
                }

                // check for null recipient list (buggy MAPI server)
                if (code == MapiError.SUCCESS_SUCCESS && nNewRecips > 0 &&
                    (lpNewRecips == null || lpNewRecips.IsInvalid))
                {
                    code = MapiError.MAPI_E_FAILURE;
                }

                // throw exception if MAPI reports failure
                if (code != MapiError.SUCCESS_SUCCESS)
                {
                    ThrowMapiException(code);
                }

                // create (possibly empty) output recipient array
                MapiAddress[] entries = new MapiAddress[nNewRecips];
                if (nNewRecips == 0)
                {
                    return(entries);
                }

                // prepare managed recipient object
                int           size  = Marshal.SizeOf(typeof(MapiRecipDesc));
                MapiRecipDesc recip = new MapiRecipDesc();

                // retrieve unmanaged memory blocks
                for (int i = 0; i < nNewRecips; i++)
                {
                    // copy current array element to managed memory
                    lpNewRecips.GetMemory(i * size, recip);

                    // HACK: Outlook Express inverts the order of selected entries.
                    // We re-invert the order since OE is the most likely client.
                    int index = (int)(nNewRecips - i - 1);

                    // store entry name and address
                    entries[index] = new MapiAddress(recip.lpszName, recip.lpszAddress);
                }

                return(entries);
            }
            finally {
                // release unmanaged memory block
                if (lpNewRecips != null)
                {
                    lpNewRecips.Dispose();
                }

                // restore original working directory
                Directory.SetCurrentDirectory(currentDir);
            }
        }