Esempio n. 1
0
        async Task <List <Mailbox> > GetMailboxesList(ImapCmd cmd, StatusCb status, ProgressCb progress)
        {
            List <Mailbox> mailboxes = new List <Mailbox>();

            if (await cmd.Run(new ListCommand(async delegate(String mailbox, String ctx)
                                              { await Task.Yield(); mailboxes.Add(new Mailbox(mailbox)); })) != ReturnCode.Ok)
            {
                throw new FailedException();
            }
            mailboxes.Sort((Mailbox m1, Mailbox m2) => {
                bool g1 = GmailSpecial(m1.name);
                bool g2 = GmailSpecial(m2.name);
                if (g1 && g2)
                {
                    return(String.Compare(m2.name, m1.name)); // reverse
                }
                else if (g1)
                {
                    return(1);
                }
                else if (g2)
                {
                    return(-1);
                }
                else
                {
                    return(String.Compare(m1.name, m2.name));
                }
            });
            for (int i = 0; i < mailboxes.Count; i++)
            {
                await cmd.Run(new StatusCommand(mailboxes[i].name, async delegate(String cnt, String ctx)
                {
                    await Task.Yield();
                    status("{0} - {1}", mailboxes[i].name, cnt);
                    mailboxes[i].cnt = int.Parse(cnt);
                    messagesInAccount += int.Parse(cnt);
                }));
            }
            status("Total messages: {0}", messagesInAccount);
            Dictionary <String, int> downloaded = await CheckResume(status, progress);

            foreach (String mbox in downloaded.Keys)
            {
                mailboxes.ForEach((Mailbox m) => {
                    if (m.name == mbox)
                    {
                        m.start = downloaded[mbox] > 0 ? downloaded[mbox] : 1;
                    }
                });
            }

            return(mailboxes);
        }
Esempio n. 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();
            }
        }