Exemple #1
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            string[] parts = TextUtils.SplitQuotedString(args, ' ', true);

            string refName = IMAP_Utils.DecodeMailbox(parts[0]);
            string folder  = IMAP_Utils.DecodeMailbox(parts[1]);

            // mailbox name is "", return delimiter and root
            if (folder == String.Empty)
            {
                var root = refName.Split(new char[] { '/' })[0];
                return(Task.FromResult(new List <ImapResponse>
                {
                    new ImapResponse(ResultLine.LIST(root, '/', null))
                }));
            }

            // Match the full mailbox pattern
            var folderPattern = folder.Replace("*", ".*").Replace("%", "[^/]*");
            var pattern       = $"^{refName}{folderPattern}$";

            var user   = Data.GlobalDb.Users.Get(session.AuthenticatedUserIdentity.Name);
            var result = new List <ImapResponse>();

            foreach (var each in GetAllFolders(user))
            {
                if (System.Text.RegularExpressions.Regex.IsMatch(each.Name, pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase))
                {
                    result.Add(new ImapResponse(Response(each.Name, '/', each.Attributes)));
                }
            }

            return(Task.FromResult(result));
        }
Exemple #2
0
 public Task <List <ImapResponse> > Execute(ImapSession session, string args)
 {
     return(Task.FromResult(new List <ImapResponse>
     {
         new ImapResponse(ResultLine.CAPABILITY(session.Capabilities))
     }));
 }
Exemple #3
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var spl        = args.Split(new char[] { ' ' }, 2);
            var subCommand = spl[0].ToUpperInvariant();
            List <ImapResponse> result;

            switch (subCommand)
            {
            case "FETCH":
                result = FetchCommand.FetchResponse.GenerateByUid(session.MailDb, session.SelectFolder, spl[1]);
                break;

            case "STORE":
                result = STORE.ExecuteByUid(session.MailDb, session.SelectFolder, spl[1]);
                break;

            case "COPY":
                result = COPY.ExecuteByUid(session.MailDb, session.SelectFolder, spl[1]);
                break;

            case "MOVE":
                result = MOVE.ExecuteByUid(session.MailDb, session.SelectFolder, spl[1]);
                break;

            case "SEARCH":
                result = SearchCommand.Search.ExecuteByUid(session.MailDb, session.SelectFolder, spl[1]);
                break;

            default:
                throw new Exception("Not support for UID " + subCommand);
            }

            return(Task.FromResult(result));
        }
Exemple #4
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var parts = TextUtils.SplitQuotedString(args, ' ', false, 2);

            var fromName = IMAP_Utils.DecodeMailbox(TextUtils.UnQuoteString(parts[0]));
            var toName   = IMAP_Utils.DecodeMailbox(TextUtils.UnQuoteString(parts[1]));

            if (Folder.ReservedFolder.Any(o => fromName.StartsWith(o.Value, StringComparison.OrdinalIgnoreCase)))
            {
                throw new CommandException("NO", "Can not rename reservered folders");
            }

            var folder = session.MailDb.Folders.Get(fromName);

            if (folder == null)
            {
                throw new CommandException("NO", "Folder is not found");
            }

            if (Folder.ReservedFolder.Any(o => toName.StartsWith(o.Value, StringComparison.OrdinalIgnoreCase)))
            {
                throw new CommandException("NO", "Can not rename folder to be under reservered folders");
            }

            if (session.MailDb.Folders.Get(Folder.ToId(toName)) != null)
            {
                throw new CommandException("NO", "Folder with new name already exist");
            }

            session.MailDb.Folders.Rename(folder, toName);

            return(this.NullResult());
        }
Exemple #5
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            List <ImapResponse> result = new List <ImapResponse>();

            if (session.SelectFolder == null)
            {
                return(this.NullResult());
            }

            var deletedSeqNo = session.SelectFolder.EXPUNGE();

            foreach (var item in deletedSeqNo)
            {
                result.Add(new ImapResponse(ResultLine.EXPUNGE(item)));
            }

            session.SelectFolder.Stat = session.MailDb.Messages.GetStat(session.SelectFolder.Folder);

            var stat = session.SelectFolder.Stat;

            result.Add(new ImapResponse(ResultLine.EXISTS(stat.Exists)));
            result.Add(new ImapResponse(ResultLine.RECENT(stat.Recent)));

            result.Add(new ImapResponse(ResultLine.UIDNEXT(stat.NextUid)));

            result.Add(new ImapResponse(ResultLine.UIDVALIDAITY(stat.FolderUid)));

            return(Task.FromResult(result));
        }
Exemple #6
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var folderName = IMAP_Utils.DecodeMailbox(TextUtils.UnQuoteString(args));

            if (Folder.ReservedFolder.Any(o => folderName.StartsWith(o.Value, StringComparison.OrdinalIgnoreCase)))
            {
                throw new CommandException("NO", "Can not delete reservered folders");
            }

            var folder = session.MailDb.Folders.Get(folderName);

            if (folder == null)
            {
                throw new CommandException("NO", "Folder is not found");
            }

            // Todo: Remove messages

            // Remove folder
            session.MailDb.Folders.Delete(folder);

            if (session.SelectFolder.FolderId == folder.Id)
            {
                session.SelectFolder = null;
            }

            return(this.NullResult());
        }
Exemple #7
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var result = new   List <ImapResponse>()
            {
                new ImapResponse("* BYE IMAP4rev1 Server logging out")
            };

            return(Task.FromResult(result));
        }
Exemple #8
0
 public static async Task SendResponse(ImapSession session, List <ImapResponse> response)
 {
     if (response != null && response.Count() > 0)
     {
         foreach (var item in response)
         {
             // send partial response..
             await SendResponse(session, item);
         }
     }
 }
Exemple #9
0
 public static async Task SendResponse(ImapSession session, ImapResponse response)
 {
     if (response.Line == null)
     {
         await session.Stream.WriteAsync(response.Binary);
     }
     else
     {
         await session.Stream.WriteLineAsync(response.Line);
     }
 }
Exemple #10
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            List <ImapResponse> result = new List <ImapResponse>();

            var deletedSeqNo = session.SelectFolder.EXPUNGE();

            foreach (var item in deletedSeqNo)
            {
                result.Add(new ImapResponse(ResultLine.EXPUNGE(item)));
            }
            return(Task.FromResult(result));
        }
Exemple #11
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            if (string.IsNullOrEmpty(args))
            {
                throw new Exception("User Or Password not provided");
            }

            string[] user_pass = TextUtils.SplitQuotedString(args, ' ', true);
            if (user_pass.Length != 2)
            {
                throw new Exception("Error in arguments");
            }

            Guid OrganizationId = default(Guid);    // user may have multiple orgs.

            string username = user_pass[0];

            if (username.IndexOf("@") > -1 && Utility.AddressUtility.IsValidEmailAddress(username))
            {
                var emailadd = Utility.AddressUtility.GetEmailAddress(username);

                if (emailadd == null)
                {
                    throw new Exception("LOGIN Failed");
                }
                else
                {
                    username       = Data.GlobalDb.Users.GetUserName(emailadd.UserId);
                    OrganizationId = emailadd.OrgId;
                }
            }

            var user = Kooboo.Data.GlobalDb.Users.Validate(username, user_pass[1]);

            if (user == null)
            {
                throw new Exception("LOGIN Failed");
            }


            if (OrganizationId == default(Guid))
            {
                OrganizationId = user.CurrentOrgId;
            }

            session.AuthenticatedUserIdentity = new GenericIdentity(user.UserName, "IMAP-LOGIN");

            session.MailDb = Kooboo.Mail.Factory.DBFactory.UserMailDb(user.Id, OrganizationId);

            return(this.NullResult());
        }
Exemple #12
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            if (session.IsSecureConnection)
            {
                throw new CommandException("NO", "Already in secure connection");
            }

            if (session.Server.SslMode != SslMode.StartTLS)
            {
                throw new CommandException("NO", "StartTLS not supported");
            }

            throw new StartTlsException();
        }
Exemple #13
0
        // RFC 3501 6.3.1. SELECT Command.

        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            string[] parts = TextUtils.SplitQuotedString(args, ' ');
            if (parts.Length >= 2)
            {
                // At moment we don't support UTF-8 mailboxes.
                if (Lib.Helper.StringHelper.IsSameValue(parts[1], "(UTF8)"))
                {
                    throw new CommandException("NO", "UTF8 name not supported");
                }
                else
                {
                    throw new CommandException("BAD", "Argument error");
                }
            }

            List <ImapResponse> Result = new List <ImapResponse>();

            string foldername = TextUtils.UnQuoteString(IMAP_Utils.DecodeMailbox(args));

            var parsedfolder = Kooboo.Mail.Utility.FolderUtility.ParseFolder(foldername);

            session.SelectFolder = new SelectFolder(foldername, session.MailDb);

            var stat = session.SelectFolder.Stat;

            session.MailDb.Messages.UpdateRecentByMaxId(stat.LastestMsgId);

            Result.Add(new ImapResponse(ResultLine.EXISTS(stat.Exists)));
            Result.Add(new ImapResponse(ResultLine.RECENT(stat.Recent)));

            if (stat.FirstUnSeen > -1)
            {
                Result.Add(new ImapResponse(ResultLine.UNSEEN(stat.FirstUnSeen)));
            }

            Result.Add(new ImapResponse(ResultLine.UIDNEXT(stat.NextUid)));

            Result.Add(new ImapResponse(ResultLine.UIDVALIDAITY(stat.FolderUid)));

            Result.Add(new ImapResponse(ResultLine.FLAGS(Setting.SupportFlags.ToList())));

            return(Task.FromResult(Result));
        }
Exemple #14
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var folderName = TextUtils.UnQuoteString(IMAP_Utils.DecodeMailbox(args));

            if (Folder.ReservedFolder.Any(o => folderName.StartsWith(o.Value, StringComparison.OrdinalIgnoreCase)))
            {
                throw new CommandException("NO", "Reserved folders are always subscribed");
            }

            var folder = session.MailDb.Folders.Get(folderName);

            if (folder == null)
            {
                throw new CommandException("NO", "No such a folder");
            }

            session.MailDb.Folders.Subscribe(folder);

            return(this.NullResult());
        }
Exemple #15
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var folderName = IMAP_Utils.DecodeMailbox(TextUtils.UnQuoteString(args));

            if (Folder.ReservedFolder.Any(o => folderName.StartsWith(o.Value, StringComparison.OrdinalIgnoreCase)))
            {
                throw new CommandException("NO", "Can not create folder under reservered folders");
            }

            var folderId = Folder.ToId(folderName);

            if (session.MailDb.Folders.Get(folderId) != null)
            {
                throw new CommandException("NO", "Folder already exist");
            }

            session.MailDb.Folders.Add(folderName);

            return(this.NullResult());
        }
Exemple #16
0
        public async Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var appendArgs = ParseArgs(args);

            if (appendArgs == null)
            {
                throw new CommandException("BAD", "Error in arguments");
            }

            await session.Stream.WriteLineAsync("+ Continue");

            var bytes = await session.Stream.ReadAsync(appendArgs.Size);

            var content = SmtpUtility.GetString(bytes);

            await session.Stream.ReadLineAsync();

            var message = MessageUtility.ParseMeta(content);

            message.FolderId = session.SelectFolder.FolderId;
            message.UserId   = session.MailDb.UserId;

            var folderName = session.SelectFolder.Folder.ToLower();

            if (folderName == "sent" || folderName == "drafts")
            {
                var user    = Data.GlobalDb.Users.Get(session.MailDb.UserId);
                var orgDb   = Kooboo.Mail.Factory.DBFactory.OrgDb(user.CurrentOrgId);
                var address = orgDb.EmailAddress.Get(Mail_t_Mailbox.Parse(message.From).Address);
                if (address != null)
                {
                    message.AddressId = address.Id;
                }
            }
            session.MailDb.Messages.Add(message, content);

            return(null);
        }
Exemple #17
0
 public Task <List <ImapResponse> > Execute(ImapSession session, string args)
 {
     return(Task.FromResult(ExecuteBySeqNo(session.MailDb, session.SelectFolder, args)));
 }
Exemple #18
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            session.SelectFolder.EXPUNGE();

            return(this.NullResult());
        }
Exemple #19
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var result = FetchCommand.FetchResponse.GenerateBySeqId(session.MailDb, session.SelectFolder, args);

            return(Task.FromResult(result));
        }
Exemple #20
0
        public Task <List <ImapResponse> > Execute(ImapSession session, string args)
        {
            var result = SearchCommand.Search.ExecuteBySeqNo(session.MailDb, session.SelectFolder, args);

            return(Task.FromResult(result));
        }
Exemple #21
0
 public static Task ResponseEnd(ImapSession session, string RequestTag, string TagResult, string message)
 {
     return(session.Stream.WriteLineAsync(RequestTag + " " + TagResult + " " + message));
 }
Exemple #22
0
 public Task <List <ImapResponse> > Execute(ImapSession session, string args)
 {
     return(this.NullResult());
 }
Exemple #23
0
        public static async Task Execute(ImapSession session, string RequestTag, string CommandName, string arg)
        {
            var command = GetCommand(CommandName);

            if (command == null)
            {
                await ResponseEnd(session, RequestTag, "NO", CommandName + " Command Not Supported");

                return;
            }

            if (command.RequireAuth && !session.IsAuthenticated)
            {
                await ResponseEnd(session, RequestTag, "NO", CommandName + " Authentication required");

                return;
            }

            if (command.RequireFolder && session.SelectFolder == null)
            {
                await ResponseEnd(session, RequestTag, "NO", CommandName + " Command requires Select state");

                return;
            }

            if (command.RequireTwoPartCommand)
            {
                string[] parts = TextUtils.SplitQuotedString(arg, ' ', true);
                if (parts.Length != 2)
                {
                    await ResponseEnd(session, RequestTag, "BAD", "Error in arguments, " + arg);

                    return;
                }
            }

            try
            {
                var response = await command.Execute(session, arg);
                await SendResponse(session, response);

                var message = new StringBuilder();
                if (!String.IsNullOrEmpty(command.AdditionalResponse))
                {
                    message.Append(command.AdditionalResponse).Append(" ");
                }
                message.Append(CommandName).Append(" Command Completed!");

                await ResponseEnd(session, RequestTag, "OK", message.ToString());
            }
            catch (StartTlsException)
            {
                await session.Stream.WriteLineAsync($"{RequestTag} OK Begin TLS negotiation now");

                await session.StartSecureConnection();
            }
            catch (SessionCloseException ex)
            {
                await SendResponse(session, ex.Response);
                await ResponseEnd(session, RequestTag, "OK", $"{CommandName} Command Completed!");

                throw;
            }
            catch (CommandException ex)
            {
                if (ex.Tag == null)
                {
                    ex.Tag = "BAD";
                }
                await ResponseEnd(session, RequestTag, ex.Tag, ex.ErrorMessage);
            }
            catch (Exception ex)
            {
                await ResponseEnd(session, RequestTag, "BAD", ex.Message);
            }
        }
Exemple #24
0
 public Task <List <ImapResponse> > Execute(ImapSession session, string args)
 {
     return(Task.FromResult(Execute(session.MailDb, args)));
 }
Exemple #25
0
        private void HandleClientMessage(object agrument)
        {
            //một phiên làm việc với một client
            TcpClient client     = (TcpClient)agrument;
            string    clientIP   = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
            string    clientPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port.ToString();

            // try-cacth lỗi client
            try
            {
                // khởi tạo luồng đọc ghi
                StreamReader  sr = new StreamReader(client.GetStream());
                StreamWriter  sw = new StreamWriter(client.GetStream());
                NetworkStream ns = client.GetStream();
                // cài đặt timeout = 30 phút
                sr.BaseStream.ReadTimeout = 1800000;
                // tạo sessionImap
                ImapSession session  = new ImapSession();
                string      msg      = "t";
                string      resposed = session.GetResposed("default");
                //
                int    msgLength;
                byte[] encryptMsgLength = new byte[16];

                sw.WriteLine(resposed);
                sw.Flush();
                // kiểm tra client đang kết nối
                while (client.Connected)
                {
                    // try-cacth timeout
                    try
                    {
                        if (session.GetStartTLS())
                        {
                            // đọc kích thước chuỗi mã hóa được gửi từ client
                            ns.Read(encryptMsgLength, 0, 16);
                            if (!Int32.TryParse(session.DecryptWithDefaultKey_IV(encryptMsgLength), out msgLength))
                            {
                                break;
                            }
                            byte[] encryptCommand = new byte[msgLength];
                            // đọc thông điệp mã hóa
                            ns.Read(encryptCommand, 0, msgLength);
                            byte[] encResponse  = session.GetEncrytionResponse(encryptCommand);
                            byte[] numSendBytes = session.EncryptWithDefaultKey_IV(encResponse.Length.ToString());
                            // gửi đi trước thông tin mã hóa chứa độ dài của thông điệp mã hóa cần gửi
                            ns.Write(numSendBytes, 0, 16);
                            ns.Flush();
                            // gửi thông điệp dưới dạng mã hóa
                            ns.Write(encResponse, 0, encResponse.Length);
                            ns.Flush();

                            // in console server
                            Console.WriteLine("Messages is Encrypted");
                        }
                        else
                        {
                            msg = sr.ReadLine(); // có thể sinh ra exception trong winform xảy ra khi client đột ngột ngắt kết nối
                            if (msg == null)
                            {
                                break;              //msg = null khi client đột ngột ngắt kết nối chỉ trên console
                            }
                            // trả lời lại các lệnh của client trong session hiện tại
                            // in console server
                            Console.WriteLine(msg);
                            resposed = session.GetResposed(msg);
                            if (resposed == "")
                            {
                                continue;
                            }
                            sw.WriteLine(resposed);
                            sw.Flush();

                            // in console server
                            Console.WriteLine(resposed);
                        }

                        sr.BaseStream.ReadTimeout = 1800000;
                        if (session.GetState() == "Logout")
                        {
                            break;
                        }
                    }
                    catch (IOException ex)
                    {
                        Console.WriteLine(ex.Message);
                        sr.Dispose();
                        sr.Close();
                        sw.Dispose();
                        sw.Close();
                        ns.Dispose();
                        ns.Close();
                        // thông báo timeout cho client
                        sw.WriteLine("* BYE connection timed out");
                        sw.Flush();
                        break;
                    }
                }
                Console.WriteLine(clientIP + " : " + clientPort + " disconnected");
                // giải phóng stream và TCPclient connection
                client.Dispose();
                client.Close();
                sr.Dispose();
                sr.Close();
                sw.Dispose();
                sw.Close();
                ns.Dispose();
                ns.Close();
                clientconnectionList.Remove(client);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                client.Dispose();
                client.Close();
                clientconnectionList.Remove(client);
                Console.WriteLine(clientIP + " : " + clientPort + " disconnected");
            }
        }