The Dew Review – Taking a Look at the Latest Release of Aspose.Email

Introduction

I have been spending some time working with the latest Apose.Email for .NET. It has been twelve or thirteen years since I have written any email related code. Back in the early 2000s, I did a little bit of work with Visual Basic and the Outlook Collaboration Data Objects (CDO). We have come a long way since that time. Email in the cloud is now becoming the norm with Gmail and Office 365.

There’s still plenty of need for local and Exchange based email processing in business applications as well. I will get to one possible scenario in my own application below.

Latest Aspose.Email Release

The Aspose.Email library supports just about any email related activity imaginable. Here is just a handful of scenarios developers can code into their own applications with Aspose.Email:

Generate emails and send via SMTP
  • Embed objects in message body – Send emails with embedded images or documents.
  • Attach files – Attach files to an email as a user would from their email client.
  • Mail merge – Powerful support for mail merge and mass emailing.
  • iCalendar support – Read and manipulate calendar events via the iCalendar standard.
  • Receive POP3 mail
    • Work with IMAP mail sources
    • Authentication
    • Work with messages and folders
    • SSL support (for POP3 and SMTP)
    Message Files
    • EML/MSG/MHT formats – All common mail message formats are supported.
    • Work with files or streams – Open messages from disk or network streams.
    • Manipulate PST files – Create, read and manipulate Outlook PST files and their contents.
    MS Exchange Server
    • WebDav and Exchange Web Services support
    • Unified Messaging operations
    • Send emails and Meeting Invites
    Advanced support for recurrence
    • Easily and reliably calculate event recurrence
    • Suppoprt for iCalendar (RFC 2445)

    Detailed developer documentation for all of the Aspose.Email features is available online here.

    So, whether your application needs to work with Exchange, Outlook files, POP3/SMTP, or talk to Gmail via IMAP, Aspose.Email has APIs to help with each situation. There are also sample apps for each feature exposed in Aspose.Email to get developers started off on the right track.

    An IMAP Console Application

    There are dozens of sample applications installed along with Apose.Email. To get started, launch the Aspose Examples Dashboard:

    asposeexamples

    The example apps are grouped by feature set. Developers can view the code in the Sample Browser, launch the solution in C# or VB, or run the example app right from the Browser application.

    I decided to take a closer look at one of the IMAP samples. The one I chose was “Fetch Messages from IMAP Server and Save to Disk”, which does exacly what the name implies. It is a console application that connects to a Gmail account via IMAP, selects the Inbox folder and loops through all of the messages, saving each one to a local folder in the “.eml” format. Here is the complete code implementation for the app after a couple of ReSharper refactorings.

    public static void Main(string[] args)
    {
        // The path to the documents directory.
        string dataDir = Path.GetFullPath("../../../Data/");
        Directory.CreateDirectory(dataDir);
    
        //Create an instance of the ImapClient class
        var client = new ImapClient
                     {
                         Host = "imap.gmail.com",
                         Username = "asposetest123@gmail.com",
                         Password = "F123456f",
                         Port = 993,
                         SecurityMode = ImapSslSecurityMode.Implicit,
                         EnableSsl = true
                     };
    
        try
        {
            client.Connect();
           
            //Log in to the remote server.
            client.Login();
    
            // Select the inbox folder
            client.SelectFolder(ImapFolderInfo.InBox);
    
            // Get the message info collection
            ImapMessageInfoCollection list = client.ListMessages();
    
            // Download each message
            for (int i = 0; i < list.Count; i++)
            {
                //Save the EML file locally
                client.SaveMessage(list[i].UniqueId, dataDir + list[i].UniqueId + ".eml");
            }
    
            //Disconnect to the remote IMAP server
            client.Disconnect();
    
            System.Console.WriteLine("Disconnected from the IMAP server");
        }
        catch (System.Exception ex)
        {
            System.Console.Write(ex.ToString());
        }
    }
    

    It is simple and intuitive to use.

    The PST Archive Utility

    I didn’t have the time to write my own applications that use every aspect of the library, so I decided to take one set of features and focus there. For years, I have been meaning to organize my work-related PST files into yearly archives. In fact, I have one PST that covers nearly seven years of email. It is nearly 6gb in size and contains who knows how many thousands of items.

    I built a small utility that will read a selected PST file, iterate through all of its folders and move all items for the specified year into a new PST with the year prepended to the PST’s file name, mirroring the folder structure of the original PST. I decided to build the utility as a WPF application, but this could function nicely as a command line utility also.

    pst1

    Using the utility is rather straightforward, simply:

    1. Enter the full path to the PST to be read.
    2. Click ‘Open PST’.
    3. The available years will display. Select a year.
    4. Click ‘Process PST’.
    5. When complete, the status message will update to “New PST Created for Year xxxx”.

    The code to display the available years iterates through the folders and items, collecting the unique years into a List<int>. It then sorts them before setting the property in the ViewModel to which the Available Years ListBox is bound.

    /// <summary>
    /// Gets all the years of items in a PST file.
    /// </summary>
    private void GetPstYears()
    {
        if (String.IsNullOrWhiteSpace(PstPath) || !File.Exists(PstPath)) return;
    
        using (PersonalStorage mainPst = PersonalStorage.FromFile(PstPath, true))
        {
            CurrentStatus = "Processing Years...";
    
            List<int> years = GetAvailableYears(mainPst.RootFolder);
            years.Sort();
            Years.Clear();
    
            foreach (int year in years)
            {
                Years.Add(year);
            }
    
            CurrentStatus = "PST Ready";
        }
    }
    
    /// <summary>
    /// Gets the available years in a specified Outlook folder.
    /// </summary>
    /// <param name="folder">The folder.</param>
    /// <returns>A list of years.</returns>
    private List<int> GetAvailableYears(FolderInfo folder)
    {
        var years = new List<int>();
    
        foreach (MapiMessage message in
                    folder.EnumerateMapiMessages().Where(message => !years.Contains(message.DeliveryTime.Year)))
        {
            years.Add(message.DeliveryTime.Year);
        }
    
        foreach (int subYear in from folderInfo in folder.EnumerateFolders()
            where folderInfo.HasSubFolders
            select GetAvailableYears(folderInfo)
            into subYears
            from subYear in subYears
            where !years.Contains(subYear)
            select subYear)
        {
            years.Add(subYear);
        }
    
        return years;
    }
    

    Similarly, the code to move the messages for the selected year to the new PST, iterates the folder structure to find any matching items.

    /// <summary>
    /// Process a PST by moving items from a selected year to a new PST
    /// while creating the same folder structure.
    /// </summary>
    private void ProcessPst()
    {
        if (SelectedYearIndex < 0 || String.IsNullOrWhiteSpace(PstPath) || !File.Exists(PstPath)) return;
    
        int year = Years[SelectedYearIndex];
    
        using (PersonalStorage mainPst = PersonalStorage.FromFile(PstPath, true))
        {
            string newFileName = PstPath.Insert(PstPath.LastIndexOf("\\", StringComparison.Ordinal) + 1, year.ToString(CultureInfo.InvariantCulture));
    
            using (PersonalStorage pstWithYear = PersonalStorage.Create(newFileName, FileFormatVersion.Unicode))
            {
                ProcessSubfolders(mainPst.RootFolder, pstWithYear.RootFolder, year);
            }
        }
    
        CurrentStatus = String.Format("New PST Created for Year {0}", Years[SelectedYearIndex]);
    }
    
    /// <summary>
    /// Processes the subfolders of a provided PST folder and adds items
    /// from the specified year to the new folder provided.
    /// </summary>
    /// <param name="folder">The source folder.</param>
    /// <param name="newParentFolder">The new folder.</param>
    /// <param name="year">The year of items to move.</param>
    private void ProcessSubfolders(FolderInfo folder, FolderInfo newParentFolder, int year)
    {
        foreach (FolderInfo folderInfo in folder.EnumerateFolders())
        {
            FolderInfo newFolder = newParentFolder.GetSubFolder(folderInfo.DisplayName) ??
                                   newParentFolder.AddSubFolder(folderInfo.DisplayName);
    
            if (folderInfo.HasSubFolders)
            {
                ProcessSubfolders(folderInfo, newFolder, year);
            }
    
            newFolder.AddMessages(folderInfo.EnumerateMapiMessages().Where(m => m.DeliveryTime.Year == year));
    
            if (newFolder.ContentCount == 0 && !newFolder.HasSubFolders && newFolder.DisplayName != "Deleted Items")
                newParentFolder.DeleteChildItem(newFolder.EntryId);
        }
    }
    

    You can see that all of the PST manipulation is very intuitive. Everything I needed to know, I was able to quickly learn from the documentation and the sample applications. It feels as if the classes are a part of the .NET Framework. It is a very well written API.

    You can download the complete source code for the project here.

    Summary

    If you are working on any projects involving email processing or access, Aspose.Email can definitely simplify the code required to get the job done. I will definitely keep these libraries in mind for future projects and you should too.

    Happy coding!

    del.icio.us Tags: ,,

     

    Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”

    Morning Dew Lightning Review – Syncfusion Essential Studio for WPF

    It has been a hectic fourth quarter of 2013 for me, but I want to write up my thoughts on the Syncfusion Essential Studio for WPF before the holidays are upon us. I have been trying different WPF controls throughout the year and all of them provide great value to the modern desktop and enterprise app developers.

    What’s New

    I have been using Studio 2013v3 for the past several weeks, but 2013v4 was just released, so I will just quickly touch on what’s new in the latest release first. Here’s a rundown of the latest features for WPF:

    • 3D Charts
    • Localization Support in Report Viewer and Report Designer
    • Customized Fast Bitmap Lines Series & Some New Types of Trend Lines in Charts

    Most of my WPF apps focus more on data capture, so I won’t be touching these new features in my day-to-day work.

    GridData Control

    I have been spending much of my time working with the GridData control. It is a powerful control with extensive support for binding, filtering/grouping/sorting, import/export and working with unbound data. The performance on filtering and sorting is great. Under the covers it is using PLINQ to optimize the performance with multiple CPUs/cores. The grid designer provides a simple way to create a great looking grid that does exactly what you need for your data.

    Docking Manager

    I also worked with the Docking Manager for WPF in Essential Studio. If there is anything in Visual Studio’s UI that you wish you could build into your app, the Docking Manager can probably help you get it done. It supports docked panels, floating panels, auto-hiding/pinning and docked tabs. The tabbed document UI that Visual Studio uses can also be created with Docking Manager via an MDI Child Mode.

    To style the docked panels, there is support for 10 different themes or you can customize any of them to create your own to match existing application standards in your company.

    Rich-Text Box and Ribbon

    The best summary of what the Rich Text control can do is on Syncfusion’s site:

    The RichTextBox control is a Microsoft Word-like word processor control that lets users view and edit rich content like formatted text, images, lists, and tables. It can also import and export .doc, .docx, HTML, XAML, and .txt file formats.

    It’s like having Word in your app without the Office runtime dependency. Combine it with the ribbon control and you can create your very own word processing experience with all of these features:

    • Text formatting
    • Paragraph alignment and indentation features
    • Insert an image or any UIElement
    • Tables support
    • Page layout
    • Import and export to .doc, .docx, HTML, XAML, .txt
    • Printing and zooming
    • Keyboard shortcuts
    • Undo and redo support
    • Command support
    • Clipboard support
    • Read only mode

    Summary

    The WPF tools are really easy learn and are easy to customize and extend with styles and templates. The design experience is equally rich in Visual Studio and Blend (I was using VS 2013).

    Go check them out, and happy coding!

    The Dew Review – Intel Haswell Ultrabook Review – Part 3: A Developer’s Best Friend

    Welcome to my third and final review of Intel’s latest generation Ultrabook prototype hardware, powered by the Haswell processor. You can read my previous reviews here:

    Hiccups

    I have had a couple of hiccups in the last few weeks, neither of which changes my overall impressions of these Ultrabooks. First, I had a hardware issue with the display. A 1px vertical green line was omnipresent on the screen about an inch from the right edge of the display. I returned the unit and Intel’s support quickly sent a replacement. The second issue could be hardware, driver or Windows 8.1 related. It’s impossible to know for sure. The Windows was inactive for 10 minutes and put the hardware to sleep. When I tried to wake it up, nothing worked. Closing/opening the lid did nothing, and pressing keyboard keys or the power button only made the backlit keyboard flash. Plugging in a USB thumb drive finally woke it up, but Windows had crashed and restored itself to default settings. I had to re-install all of my drivers and software. Despite this bumps in the road, I wouldn’t hesitate to recommend an Intel Haswwell powered Ultrabook to any Windows developer. It’s just the nature of testing prototype hardware not intended for retail sale.

    Windows 8.1

    I have been using the release version of Windows 8.1 from MSDN on this Ultrabook. I installed it shortly after my second review. The little changes in the OS really make a big difference for the PC. I do not use all of the enhancements. For example, I do not boot directly to my desktop, and I have yet to press the start button on the desktop. I suspect I might use the start button if I didn’t have a touch-enabled device. I do like the changes to the start screen a lot. Not having every new app’s icon placed on my start page is my favorite change. It’s also nice to have SkyDrive more tightly integrated with the OS.

    .NET Development

    I have been doing all of my personal development projects on this machine, with all of the code checked in to TFS Online and backing up on SkyDrive. Because the Visual Studio 2013 Release Candidate has a Go-Live license, I have been using it as my main IDE, developing projects for Windows Desktop (WPF), Windows Phone 8, Windows 8.1, Windows Azure and the web. Other tools I have been using on this PC include ReSharper 8, WebStorm 7, WebMatrix and Icenium Graphite. I also plan on installing Xamarin Studio to do some cross-platform mobile development.

    Most of my personal development time has been spent doing Windows Phone 8 and WPF development. It is really great to have a touch-enabled Ultrabook to run and test my apps. It makes interacting with the Windows Phone emulator feel more natural, and it is very likely that my WPF apps will be used by others on touch-enabled PCs. Any modern development really should be done on a PC with a multi-touch screen.

    Other Tidbits

    I haven’t run into any issues with performance while running multiple instances of Visual Studio, Blend, emulators and other applications at the same time.

    I have not given the battery a proper torture test, but it is never something I have to think about when I am away from my power supply for a few hours.

    The screen looks amazing. The resolution is true HD (1920×1080), and everything looks crisp and clean.

    Tip: If you use Google Chrome on the Desktop and don’t like the blurry look on high resolution, open chrome://flags and change the “HiDPI Support” flag from Default to Enabled.

    I would like to thank Intel for the opportunity to review this Haswell Ultrabook. It has been a great experience. If you have a chance to buy one, like maybe a Lenovo ThinkPad X1 Carbon Touch, you will not be disappointed

     

    Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.