public JsonResult GetMail(int? timezoneOffset, bool showUnreadOnly, bool showPreview, string folderName)
        {
            var successful = false;
            var output = new List<GmailThread>();
            var unreadCount = 0;
            var folders = new List<string>();

            if (Request.IsAuthenticated)
            {
                using (var uow = new UnitOfWork(GlobalConfig.ConnectionString))
                {
                    var user = uow.UserRepository.GetUserByUsername(User.Identity.Name);

                    if (DateTime.Compare(DateTime.Now, user.OAuthAccessTokenExpiration) < 0)
                    {
                        using (
                            var imap = new ImapClient("imap.gmail.com", user.EmailAddress,
                                user.CurrentOAuthAccessToken, AuthMethods.SaslOAuth, 993, true,
                                true))
                        {
                            imap.SelectMailbox(folderName);

                            var listMailboxes = imap.ListMailboxes(string.Empty, "*");

                            foreach (var listMailbox in listMailboxes)
                            {
                                if (!listMailbox.Name.StartsWith("[Gmail]") &&
                                    String.Compare(listMailbox.Name, folderName, StringComparison.OrdinalIgnoreCase) != 0)
                                {
                                    folders.Add(listMailbox.Name);
                                }
                            }

                            var searchCondition = SearchCondition.Undeleted();
                            if (showUnreadOnly)
                            {
                                searchCondition = searchCondition.And(SearchCondition.Unseen());
                            }

                            //Get messages and organize into threads

                            var uidCollection = imap.Search(searchCondition);

                            var messages = new List<GmailMessage>();
                            foreach (var uid in uidCollection)
                            {
                                var cacheKey = "gmail_" + uid + (showPreview ? "_WPrev" : "");
                                var mailMessageBytes = HttpContext.Cache.Get(cacheKey) as byte[];
                                if (mailMessageBytes == null)
                                {
                                    var mailMessage = new GmailMessage(imap.GetMessage(uid, !showPreview, false));
                                    var encryptedMessage = GlobalConfig.Encryptor.EncryptString(JsonConvert.SerializeObject(mailMessage));
                                    HttpContext.Cache.Insert(cacheKey, encryptedMessage);
                                    messages.Add(mailMessage);
                                }
                                else
                                {
                                    var decryptedMessage = GlobalConfig.Encryptor.DecryptString(mailMessageBytes);
                                    var mailMessage = JsonConvert.DeserializeObject<GmailMessage>(decryptedMessage);
                                    messages.Add(mailMessage);
                                }
                            }
                            var threads = new Dictionary<long, GmailMessage>();
                            var threadMessages = new Dictionary<long, List<long>>();
                            var threadCounts = new Dictionary<long, int>();
                            foreach (var m in messages.OrderByDescending(m => m.MessageDate))
                            {
                                var headers = m.Headers;
                                var gmailThreadId = long.Parse(headers["X-GM-THRID"]);

                                if (!threads.ContainsKey(gmailThreadId))
                                {
                                    threads.Add(gmailThreadId, m);
                                    threadCounts.Add(gmailThreadId, 1);
                                    threadMessages.Add(gmailThreadId, new List<long> {m.Uid});
                                }
                                else
                                {
                                    threadCounts[gmailThreadId] += 1;
                                    threadMessages[gmailThreadId].Add(m.Uid);
                                }
                            }

                            //Bundle threads
                            foreach (var thread in threads)
                            {
                                var messageDate = (thread.Value.MessageDate.Ticks > 0
                                    ? (timezoneOffset.HasValue
                                        ? thread.Value.MessageDate.ToUniversalTime().AddMinutes(timezoneOffset.Value)
                                        : thread.Value.MessageDate.ToUniversalTime())
                                    : new DateTime(1900, 1, 1));
                                var messageDateString = (DateTime.Compare(messageDate.Date, DateTime.Now.Date) == 0
                                    ? messageDate.ToShortTimeString()
                                    : messageDate.ToShortDateString());
                                var unread = !(thread.Value.MessageFlags.HasFlag(GmailMessage.Flags.Seen));
                                if (unread)
                                {
                                    unreadCount++;
                                }
                                output.Add(new GmailThread
                                {
                                    Subject = thread.Value.Subject,
                                    From =
                                        thread.Value.FromDisplayName +
                                        (threadCounts[thread.Key] > 1 ? " (" + threadCounts[thread.Key] + ")" : ""),
                                    ThreadIdHex = thread.Key.ToString("X").ToLower(),
                                    ThreadId = thread.Key,
                                    ThreadMessageIds = string.Join(",", threadMessages[thread.Key].ToArray()),
                                    Date = messageDateString,
                                    Preview = (showPreview ? getPreview(thread.Value.Body) : ""),
                                    Unread = unread,
                                    Important =
                                        (thread.Value.Headers.ContainsKey("X-GM-LABELS") &&
                                         thread.Value.Headers["X-GM-LABELS"].Equals("\"\\\\Important\""))
                                });
                            }
                            successful = true;
                        }
                    }
                }
            }
            return Json(
                new {Result = successful, Data = output, UnreadCount = unreadCount, Folders = folders.ToArray()},
                JsonRequestBehavior.AllowGet);
        }