Friday 23 May 2014

Insert Email Into Exchange Public Folder - Adding (2 of 2)

In one of our products we are required to insert an email item into exchange, After much nail biting after realising that Microsoft Exchange WebService Documentation is extremely poor. I have come up with a solution that accepts a FileInfo Object and a FileStream and puts the file into a 'Public Folder' into exchange. Heres the code

public static void InsertIntoExchange(FileInfo file, FileStream stream)
        {
           
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    if (stream.Length == 0)
                        throw new Exception(string.Format("File Error: {0} Contains Zero Bytes",file.FullName));

                    Folder selectedPublicFolder = null;

                    //Set your Aspose Licence Here

                    MapiMessage mapiMessage = MapiMessage.FromStream(stream);
                    mapiMessage.Save(ms);

                    var properties = mapiMessage.NamedProperties.Values.Cast().ToList();

                    var propProjectId = properties.Where(y => y.NameId == "ProjectID").FirstOrDefault();
                    var propFileStatus = properties.Where(y => y.NameId == "FileStatus").FirstOrDefault();

                    if (propProjectId != null && propFileStatus != null)
                    {
                        string projectId = propProjectId.GetString();
                        Enumerators.FileStatus fileStatus = (Enumerators.FileStatus)Enum.Parse(typeof(Enumerators.FileStatus), propFileStatus.GetString());

                        if (fileStatus == Enumerators.FileStatus.Uploaded)
                        {
                              throw new Exception("File Already Uploaded");
                        }
                        else if (fileStatus == Enumerators.FileStatus.Failed)
                        {
                            throw new Exception("File Failed");
                        }
                        else
                        {
                            selectedPublicFolder = //Find Exchange Public Folder

                            if (selectedPublicFolder == null)
                            {
    throw new Exception("Public Folder Was Not Found");                                
                            }

                            FolderIdType f = new FolderIdType();
                            f.Id = selectedPublicFolder.Id.UniqueId;

                            try
                            {
                                CreateItemType ciType = new CreateItemType()
                                {
                                    MessageDisposition = MessageDispositionType.SaveOnly,
                                    MessageDispositionSpecified = true,
                                    SavedItemFolderId = new TargetFolderIdType()
                                    {
                                        Item = f
                                    },
                                    Items = new NonEmptyArrayOfAllItemsType()
                                };


                                using (MemoryStream tms = new MemoryStream())
                                {
                                    //Load AsposeLicence Again

                                    MailMessage m = MailMessage.Load(stream);
                                    m.Save(tms);

                                    MessageType msg = new MessageType()
                                    {

                                        MimeContent = new MimeContentType()
                                        {
                                            Value = Convert.ToBase64String(tms.ToArray())
                                        },

                                        IsRead = true
                                    };

                                    ExtendedPropertyType type = new ExtendedPropertyType();

                                    PathToExtendedFieldType epExPath = new PathToExtendedFieldType();
                                    epExPath.PropertyTag = "0x0E07";
                                    epExPath.PropertyType = MapiPropertyTypeType.Integer;

                                    type.ExtendedFieldURI = epExPath;
                                    type.Item = "1";

                                    msg.DateTimeSent = m.Date;
                                    
                                    msg.ExtendedProperty = new ExtendedPropertyType[1];
                                    msg.ExtendedProperty[0] = type;

                                    ciType.Items.Items = new ItemType[1];
                                    ciType.Items.Items[0] = msg;

                                    CreateItemResponseType response = Global.ExchangeServiceBinding.CreateItem(ciType);


                                    if (response.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
                                    {
                                        throw new Exception(response.ResponseMessages.Items[0].MessageText);
                                    }

                                }

                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }
                            finally
                            {
                                mapiMessage.NamedProperties.Remove(propFileStatus.Tag);

                                MapiNamedPropertyMappingStorage mappingStorage = mapiMessage.NamedPropertyMapping;
                                Guid PS_PUBLIC_STRINGS = new Guid("00020329-0000-0000-C000-000000000046");

                                // Create a named property
                                MapiProperty stringProperty = new MapiProperty(mappingStorage.GetNextAvailablePropertyId(Aspose.Email.Outlook.MapiPropertyType.PT_UNICODE),
                                                        Encoding.Unicode.GetBytes(((int)fileStatus).ToString()));

                                // Set message property
                                mapiMessage.SetProperty(stringProperty);
                                string stringNameId = "FileStatus";
                                mappingStorage.AddNamedPropertyMapping(stringProperty, stringNameId, PS_PUBLIC_STRINGS);

                                stream.Close();

                                mapiMessage.Save(file.FullName);
                            }
                        }


                    }


                    else if (propProjectId == null)
                    {
                        throw new Exception("File Failure: Project ID was not found in file: " + file.Name);

                    }
                    else if (propFileStatus == null)
                    {
                        throw new Exception("File Failure: FileStatus was not found in file: " + file.Name);
                    }
                    else
                    {
                        throw new Exception("File Failure: The File May Not Be a valid file: " + file.Name);                        
                    }
                }

            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

If however you are using Exchange 2010 the best way is to insert the object into the 'Inbox' First then perform a 'Move' operation as Exchange Mangles the Header and Mime object if a direct insert occurs. Add this at the end of the Insertion Method Above
//*Attempt to Move Item *//
                                            var newId = (((ExchangeWebServices.ItemInfoResponseMessageType)
                                                (((ExchangeWebServices.BaseResponseMessageType) (response))
                                                    .ResponseMessages.Items[0]))
                                                .Items.Items[0]).ItemId;

                                            if (newId != null)
                                            {
                                                MoveItemType t = new MoveItemType()
                                                {
                                                    ItemIds = new BaseItemIdType[]
                                                    {
                                                        newId
                                                    },

                                                };
                                                t.ToFolderId = new TargetFolderIdType();
                                                t.ToFolderId.Item = f;

                                                var moveItemResponse = Global.ExchangeServiceBinding.MoveItem(t);

                                                if (response.ResponseMessages.Items[0].ResponseClass ==
                                                    ResponseClassType.Error)
                                                {
                                                    throw new Exception("File Uploaded but it failed to move from Inbox");
                                                }

                                            }