Example #1
0
        public async Task Start(StatusCb status, DataCb data, ProgressCb progress, bool compression = false)
        {
            try
            {
                status("Connecting...");
                if (await connect.Connect() != ConnectStatus.Ok)
                {
                    throw new ConnectionFailedException();
                }
                ImapCmd cmd = null;
                if (await connect.ConnectTls() == ConnectStatus.Failed)
                {
                    cmd = CreateImap(connect.stream);
                    if (await cmd.Run(new StarttlsCommand()) != ReturnCode.Ok)
                    {
                        throw new SslFailedException();
                    }
                }
                cmd = CreateImap(connect.stream);

                // initial Capability
                await cmd.Run(new NullCommand());

                // login to the server
                if (await cmd.Run(new LoginCommand(user, pswd)) != ReturnCode.Ok)
                {
                    throw new FailedLoginException();
                }
                status("Logged in to the email server");
                // check if compression is supported
                if (compression && await cmd.Run(new CapabilityCommand(new String[] { "compress=deflate" })) == ReturnCode.Ok &&
                    await cmd.Run(new DeflateCommand()) == ReturnCode.Ok)
                {
                    StreamReader reader = new StreamReader(new DeflateStream(connect.stream, CompressionMode.Decompress, true));
                    cmd = new ImapCmd(token, reader, connect.stream, true);
                    status("Compression enabled");
                }

                // get the list of mailboxes
                status("Fetching mailbox list...");
                mailboxes = await GetMailboxesList(cmd, status, progress);

                status("Downloading ...");
                progress(0);
                int   processed = 0;
                Regex rx_msgid  = new Regex("^message-id: ([^ \r\n]+)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                Func <String, String> getMsgId = (String message) =>
                {
                    int   len = message.Length > 5000 ? 5000 : message.Length;
                    Match m   = rx_msgid.Match(message, 0, len);
                    return(m.Success ? m.Groups[1].Value : "");
                };
                foreach (Mailbox mailbox in mailboxes)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    status("{0} - {1} messages: ", mailbox.name, mailbox.cnt);
                    if (mailbox.start < mailbox.cnt)
                    {
                        if (await cmd.Run(new SelectCommand(mailbox.name)) != ReturnCode.Ok)
                        {
                            throw new FailedException();
                        }

                        if (!GmailSpecial(mailbox.name))
                        {
                            if (await cmd.Run(new FetchCommand(FetchCommand.Fetch.Body,
                                                               async delegate(String message, String msgn)
                            {
                                mailbox.start = int.Parse(msgn);
                                String msgid = "";
                                if (host == "imap.gmail.com")
                                {
                                    msgid = getMsgId(message);
                                    messageid[msgid] = "";
                                }
                                progress((100.0 * (processed + int.Parse(msgn))) / messagesInAccount);
                                await data(mailbox.name, message, msgid, msgn);
                            }, mailbox.start)) != ReturnCode.Ok)
                            {
                                status(token.IsCancellationRequested ? "Download cancelled" : "No messages downloaded");
                            }
                        }
                        else
                        {
                            List <String> unique = new List <string>();
                            progress(0);
                            if (await cmd.Run(new FetchCommand(FetchCommand.Fetch.MessageID,
                                                               async delegate(String message, String msgn)
                            {
                                mailbox.start = int.Parse(msgn);
                                String msgid = getMsgId(message);
                                if (msgid != "" && messageid.ContainsKey(msgid))
                                {
                                    return;
                                }
                                else
                                {
                                    messageid[msgid] = "";
                                    unique.Add(msgn);
                                }
                                progress(100.0 * int.Parse(msgn) / mailbox.cnt);
                                await Task.Yield();
                            })) != ReturnCode.Ok)
                            {
                                progress(0);
                                status(token.IsCancellationRequested ? "Download cancelled" : "No messages downloaded, failed to get the list of unique messages");
                            }
                            else
                            {
                                progress(0);
                                status("Downloading {0} out of {1}", unique.Count, mailbox.cnt);
                                status("{0} - {1} messages: ", mailbox.name, unique.Count);
                                int downloaded = 0;
                                foreach (String n in unique)
                                {
                                    int num = int.Parse(n);
                                    if (await cmd.Run(new FetchCommand(FetchCommand.Fetch.Body,
                                                                       async delegate(String message, String msgn)
                                    {
                                        progress((100.0 * (processed + int.Parse(msgn))) / messagesInAccount);
                                        await data(mailbox.name, message, getMsgId(message), msgn);
                                        downloaded++;
                                    }, num, num)) != ReturnCode.Ok)
                                    {
                                        status("failed to download {0}", n);
                                        continue;
                                    }
                                }
                                if (token.IsCancellationRequested)
                                {
                                    status("Download cancelled");
                                }
                                if (unique.Count != downloaded)
                                {
                                    status("{0} out of {1} failed to download", unique.Count - downloaded, unique.Count);
                                }
                            }
                        }
                    }
                    processed    += mailbox.cnt;
                    mailbox.start = mailbox.cnt;
                }
                status("Download complete");
            }
            finally
            {
                connect.Close();
            }
        }
Example #2
0
        public async Task Start(StatusCb status, DataCb data, ProgressCb progress, bool compression=false)
        {
            try
            {
                status("Connecting...");
                if (await connect.Connect() != ConnectStatus.Ok)
                    throw new ConnectionFailedException();
                ImapCmd cmd = null;
                if (await connect.ConnectTls() == ConnectStatus.Failed)
                {
                    cmd = CreateImap(connect.stream);
                    if (await cmd.Run(new StarttlsCommand()) != ReturnCode.Ok)
                        throw new SslFailedException();
                }
                cmd = CreateImap(connect.stream);

                // initial Capability
                await cmd.Run(new NullCommand());

                // login to the server
                if (await cmd.Run(new LoginCommand(user, pswd)) != ReturnCode.Ok)
                    throw new FailedLoginException();
                status("Logged in to the email server");
                // check if compression is supported
                if (compression && await cmd.Run(new CapabilityCommand(new String[] { "compress=deflate" })) == ReturnCode.Ok &&
                    await cmd.Run(new DeflateCommand()) == ReturnCode.Ok)
                {
                    StreamReader reader = new StreamReader(new DeflateStream(connect.stream, CompressionMode.Decompress, true));
                    cmd = new ImapCmd(token, reader, connect.stream, true);
                    status("Compression enabled");
                }
          
                // get the list of mailboxes
                status("Fetching mailbox list...");
                mailboxes = await GetMailboxesList(cmd,status,progress);
                status("Downloading ...");
                progress(0);
                int processed = 0;
                Regex rx_msgid = new Regex("^message-id: ([^ \r\n]+)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                Func<String, String> getMsgId = (String message) =>
                {
                    int len = message.Length > 5000 ? 5000 : message.Length;
                    Match m = rx_msgid.Match(message, 0, len);
                    return (m.Success ? m.Groups[1].Value : "");
                };
                foreach (Mailbox mailbox in mailboxes)
                {
                    if (token.IsCancellationRequested)
                        return;
                    status("{0} - {1} messages: ", mailbox.name, mailbox.cnt);
                    if (mailbox.start < mailbox.cnt)
                    {
                        if (await cmd.Run(new SelectCommand(mailbox.name)) != ReturnCode.Ok)
                            throw new FailedException();

                        if (!GmailSpecial(mailbox.name))
                        {
                            if (await cmd.Run(new FetchCommand(FetchCommand.Fetch.Body,
                                async delegate (String message, String msgn)
                                {
                                    mailbox.start = int.Parse(msgn);
                                    String msgid = "";
                                    if (host == "imap.gmail.com")
                                    {
                                        msgid = getMsgId(message);
                                        messageid[msgid] = "";
                                    }
                                    progress((100.0 * (processed + int.Parse(msgn))) / messagesInAccount);
                                    await data(mailbox.name, message, msgid, msgn);
                                }, mailbox.start)) != ReturnCode.Ok)
                            {
                                status(token.IsCancellationRequested ? "Download cancelled" : "No messages downloaded");
                            }
                        }
                        else
                        {
                            List<String> unique = new List<string>();
                            progress(0);
                            if (await cmd.Run(new FetchCommand(FetchCommand.Fetch.MessageID,
                                async delegate (String message, String msgn)
                                {
                                    mailbox.start = int.Parse(msgn);
                                    String msgid = getMsgId(message);
                                    if (msgid != "" && messageid.ContainsKey(msgid))
                                        return;
                                    else
                                    {
                                        messageid[msgid] = "";
                                        unique.Add(msgn);
                                    }
                                    progress(100.0 * int.Parse(msgn) / mailbox.cnt);
                                    await Task.Yield();
                                })) != ReturnCode.Ok)
                            {
                                progress(0);
                                status(token.IsCancellationRequested ? "Download cancelled" : "No messages downloaded, failed to get the list of unique messages");
                            }
                            else
                            {
                                progress(0);
                                status("Downloading {0} out of {1}", unique.Count, mailbox.cnt);
                                status("{0} - {1} messages: ", mailbox.name, unique.Count);
                                int downloaded = 0;
                                foreach (String n in unique)
                                {
                                    int num = int.Parse(n);
                                    if (await cmd.Run(new FetchCommand(FetchCommand.Fetch.Body,
                                        async delegate (String message, String msgn)
                                        {
                                            progress((100.0 * (processed + int.Parse(msgn))) / messagesInAccount);
                                            await data(mailbox.name, message, getMsgId(message), msgn);
                                            downloaded++;
                                        }, num, num)) != ReturnCode.Ok)
                                    {
                                        status("failed to download {0}", n);
                                        continue;
                                    }
                                }
                                if (token.IsCancellationRequested)
                                    status("Download cancelled");
                                if (unique.Count != downloaded)
                                    status("{0} out of {1} failed to download", unique.Count-downloaded, unique.Count);
                            }
                        }
                    }
                    processed += mailbox.cnt;
                    mailbox.start = mailbox.cnt;
                }
                status("Download complete");
            }
            finally
            {
                connect.Close();
            }
        }