示例#1
0
        private IEnumerable <Email> GetErrorEmails()
        {
            List <Email> emails = new List <Email>();

            using (var ctx = new EmailImportDataContext())
            {
                foreach (var profile in Settings.MailboxProfiles.Values.Where(m => m.IsActive))
                {
                    try
                    {
                        var errors = from email in ctx.Emails
                                     where (email.MailboxGUID == profile.MailboxGUID) &&
                                     (email.InProgress == null || email.InProgress == false) &&
                                     (email.Status == "Error")
                                     select email;

                        emails.AddRange(errors.ToList().Where(e => e.ProcessedCount.GetValueOrDefault() > profile.MaximumRetries || (e.Errors != null && (String)e.Errors.Attribute("retry") == "false")));
                    }
                    catch (Exception e)
                    {
                        // Add custom data for logging purposes
                        e.Data.Add("MailboxGUID", profile.MailboxGUID);

                        // Log the error
                        ConfigLogger.Instance.LogError("EmailMonitor", e);
                    }
                }
            }

            return(emails);
        }
示例#2
0
        private IEnumerable <Email> GetEmails()
        {
            List <Email> emails = new List <Email>();

            using (var ctx = new EmailImportDataContext())
            {
                foreach (var profile in Settings.MailboxProfiles.Values.Where(m => m.IsActive))
                {
                    var retryTime = DateTime.Now.Subtract(profile.TimeBetweenRetries);

                    try
                    {
                        // Get email with status == null || (status == error && lastProcessed > timespan)
                        emails.AddRange((from email in ctx.Emails
                                         where (email.MailboxGUID == profile.MailboxGUID) &&
                                         (email.InProgress == null || email.InProgress == false) &&
                                         ((email.Status == null) ||
                                          (email.Status == "Error" && (email.EndTime == null || email.EndTime.Value < retryTime)))
                                         select email));
                    }
                    catch (Exception e)
                    {
                        // Add custom data for logging purposes
                        e.Data.Add("MailboxGUID", profile.MailboxGUID);

                        // Log the error
                        ConfigLogger.Instance.LogError("EmailMonitor", e);
                    }
                }
            }

            return(emails.OrderBy(e => e.EmailID));
        }
示例#3
0
        private IEnumerable <Email> GetConversionErrorEmails()
        {
            List <Email> emails = new List <Email>();

            using (var ctx = new EmailImportDataContext())
            {
                foreach (var profile in Settings.MailboxProfiles.Values.Where(m => m.IsActive))
                {
                    try
                    {
                        var errors = from email in ctx.Emails
                                     where (email.MailboxGUID == profile.MailboxGUID && profile.ProcessErrorBatch == true) &&
                                     (email.InProgress == null || email.InProgress == false) &&
                                     (email.Status == "Rejected" || email.Status == "Ignored")
                                     select email;

                        emails.AddRange(errors.ToList());
                    }
                    catch (Exception e)
                    {
                        // Add custom data for logging purposes
                        e.Data.Add("MailboxGUID", profile.MailboxGUID);

                        // Log the error
                        ConfigLogger.Instance.LogError("EmailMonitor", e);
                    }
                }
            }

            return(emails);
        }
示例#4
0
        public static void LoadMailboxProfiles()
        {
            MailboxProfiles.Clear();

            XmlSerializer serializer = new XmlSerializer(typeof(MailboxProfile));

            using (var ctx = new EmailImportDataContext())
            {
                foreach (var mailbox in ctx.Mailboxes)
                {
                    using (TextReader reader = new StringReader(mailbox.ProfileObject))
                    {
                        var profile = (MailboxProfile)serializer.Deserialize(reader);

                        if (profile.Enabled)
                        {
                            try
                            {
                                profile.ParseScript();
                            }
                            catch (Exception e)
                            {
                                ConfigLogger.Instance.LogError(e);
                            }

                            MailboxProfiles.Add(mailbox.MailboxGUID, profile);
                        }
                    }
                }
            }
        }
示例#5
0
        private void ResetInProgress()
        {
            using (var ctx = new EmailImportDataContext())
            {
                foreach (var email in ctx.Emails.Where(e => e.InProgress == true))
                {
                    email.InProgress = null;
                }

                ctx.SubmitChanges();
            }
        }
        private void UpdateStatus(EmailStatus status, XElement errors)
        {
            int count = 0;

            while (true)
            {
                try
                {
                    using (EmailImportDataContext ctx = new EmailImportDataContext())
                    {
                        var eml = ctx.Emails.Single(e => e.EmailID == email.EmailID);

                        if (status == EmailStatus.InProgress)
                        {
                            eml.InProgress = true;
                            eml.StartTime  = DateTime.Now;
                            eml.EndTime    = null;
                        }
                        else
                        {
                            eml.Status         = status.ToString();
                            eml.ProcessedCount = eml.ProcessedCount.GetValueOrDefault() + 1;
                            eml.EndTime        = DateTime.Now;
                            eml.InProgress     = null;
                            eml.Errors         = errors;
                        }

                        ctx.SubmitChanges();
                    }

                    break;
                }
                catch (Exception e)
                {
                    // Increment the retry counter
                    count++;

                    // Log the exception
                    ConfigLogger.Instance.Log(count < 5 ? LogSeverity.Warning : LogSeverity.Error, email.EmailID, e);

                    // Retry up to 5 times
                    if (count >= 5)
                    {
                        break;
                    }

                    // Sleep for a fraction
                    Thread.Sleep(50);
                }
            }
        }
示例#7
0
        private Boolean IsDuplicate(EmailImportDataContext ctx, Guid guid, MailMessage message, ref long emailID)
        {
            var subject = CreditCardHelper.ExistsCCNumber(message.Subject) ? CreditCardHelper.MaskCCNumbers(message.Subject, '#') : message.Subject;

            var email = ctx.Emails.FirstOrDefault(e => Object.Equals(e.MailboxGUID, guid) &&
                                                  Object.Equals(e.MessageID, message.MessageId) &&
                                                  Object.Equals(e.From, message.From.GetAddressOrDisplayName()) &&
                                                  Object.Equals(e.DateSent, message.DateSent()) &&
                                                  Object.Equals(e.DateReceived, message.DateReceived()) &&
                                                  Object.Equals(e.Subject, subject));

            if (email != null)
            {
                emailID = email.EmailID;
            }

            return(email != null);
        }
示例#8
0
        private void HouseKeeping()
        {
            ConfigLogger.Instance.LogInfo("EmailMonitor", "Performing house keeping tasks...");

            try
            {
                using (var ctx = new EmailImportDataContext())
                {
                    // Loop through each profile
                    foreach (var profile in Settings.MailboxProfiles.Values)
                    {
                        try
                        {
                            // Determine date to purge from based on retention setting
                            var date = DateTime.Today.AddDays(0 - Math.Abs(profile.StorageRetention));

                            // Get emails to be purged
                            var emails = ctx.Emails.Where(e => (e.MailboxGUID == profile.MailboxGUID) &&
                                                          (e.InProgress == null || e.InProgress == false) &&
                                                          (e.Status == "Complete" || e.Status == "Empty" || e.Status == "Rejected" || e.Status == "Ignored") &&
                                                          (e.EndTime != null && e.EndTime.Value < date)).ToList();

                            // Delete each email msg file
                            foreach (var email in emails)
                            {
                                File.Delete(email.MessageFilePath);
                            }

                            // Delete the email entries from the Emails table
                            ctx.Emails.DeleteAllOnSubmit(emails);

                            // Submit the changes
                            ctx.SubmitChanges();

                            // Log how many emails were deleted
                            ConfigLogger.Instance.LogInfo("EmailMonitor", String.Format("Deleted {0} stored email{1} from {2}.", emails.Count, emails.Count == 1 ? "" : "s", profile.Description));

                            // Remove empty folders from the storage path
                            RemoveEmptyFolders(profile.StoragePath);

                            // Archive path deletion
                            if (!String.IsNullOrWhiteSpace(profile.ArchivePath) && Directory.Exists(profile.ArchivePath))
                            {
                                // Determine date to purge from based on retention setting
                                date = DateTime.Today.AddDays(0 - Math.Abs(profile.ArchiveRetention));

                                // Delete dated archive folders earlier than the retention date
                                foreach (var folder in Directory.GetDirectories(profile.ArchivePath))
                                {
                                    DateTime dateValue;

                                    if (DateTime.TryParseExact(Path.GetFileName(folder), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out dateValue))
                                    {
                                        if (dateValue < date)
                                        {
                                            Directory.Delete(folder, true);

                                            ConfigLogger.Instance.LogInfo("EmailMonitor", String.Format("Deleted archive folder {0}.", folder));
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            // Add custom data for logging purposes
                            e.Data.Add("MailboxGUID", profile.MailboxGUID);

                            // Log the warning (not error)
                            ConfigLogger.Instance.LogWarning("EmailMonitor", e);
                        }
                    }
                }

                // Remove empty folders from the default storage path
                RemoveEmptyFolders(Settings.DefaultStoragePath);
            }
            catch (Exception e)
            {
                // We don't want housekeeping to cause a failure, but we want someone to
                // know about it so that they can investigate the issue
                ConfigLogger.Instance.LogWarning("EmailMonitor", e);
            }
        }
示例#9
0
        private int DownloadEmail(Imap imap, MailboxProfile profile, String storagePath)
        {
            int count = 0;

            // Build the MailQuery
            var query = new MailQuery(String.IsNullOrEmpty(profile.ImapQuery) ? "('Deleted' = 'False')" : String.Format("({0}&('Deleted' = 'False'))", profile.ImapQuery));

            // Get all messages matching to the query
            var infos = imap.ListMessages(query);

            // If there are any messages to process, then process them
            if (infos.Any())
            {
                ConfigLogger.Instance.LogInfo("ImapCollector", String.Format("Downloading {0} message{1} from {2}.", infos.Count, infos.Count == 1 ? "" : "s", profile.Description));

                // Download each message
                foreach (var info in infos)
                {
                    if (!timer.Enabled)
                    {
                        break;
                    }

                    // Just check to ensure its valid
                    if (info.Deleted || String.IsNullOrWhiteSpace(info.UniqueId))
                    {
                        continue;
                    }

                    // Track the start time for debug purposes
                    var start = DateTime.Now;

                    MailMessage message = null;

                    try
                    {
                        // Download the message
                        message = imap.FetchMessage(info.UniqueId);

                        // Calculate the time taken to fetch the message
                        var fetchTime = DateTime.Now.Subtract(start);

                        // Process the message (So long as the fetch succeeded)
                        if (message != null)
                        {
                            // Setup the data context
                            using (var ctx = new EmailImportDataContext())
                            {
                                long emailID = 0;

                                // Truncate the subject to avoid data commit errors
                                message.Subject = Truncate(message.Subject, 500);

                                // Check for duplicate
                                if (IsDuplicate(ctx, profile.MailboxGUID, message, ref emailID))
                                {
                                    // Log the duplicate error
                                    ConfigLogger.Instance.LogWarning("ImapCollector", String.Format("Message already downloaded, moved to duplicate folder (existing EmailID = {0}).", emailID));

                                    // Move the message to the duplicate sub folder
                                    imap.MoveMessage(info.UniqueId, "Duplicate", true, false);
                                }
                                else
                                {
                                    // Create an instance of the email database object
                                    var email = new Email();

                                    // Assign properties
                                    email.MailboxGUID  = profile.MailboxGUID;
                                    email.DateSent     = message.DateSent();
                                    email.DateReceived = message.DateReceived();
                                    email.From         = message.From.GetAddressOrDisplayName();
                                    email.MessageID    = message.MessageId;
                                    if (CreditCardHelper.ExistsCCNumber(message.Subject))
                                    {
                                        email.Subject = CreditCardHelper.MaskCCNumbers(message.Subject, '#');
                                    }
                                    else
                                    {
                                        email.Subject = message.Subject;
                                    }
                                    email.Timestamp = DateTime.Now;

                                    // Create the dated storage path
                                    var path = Path.Combine(storagePath, email.Timestamp.Value.ToString("yyyyMMdd"));
                                    FileSystemHelper.CreateDirectory(path);

                                    // Insert the new record
                                    ctx.Emails.InsertOnSubmit(email);

                                    // Submit the email (we need to get the email ID)
                                    using (TransactionScope scope = new TransactionScope())
                                    {
                                        // Initial submit of changes
                                        ctx.SubmitChanges();

                                        // Build the mail message file name
                                        email.MessageFilePath = Path.Combine(path, String.Format("{0:00000000}.eml", email.EmailID));

                                        // Save to disk (delete anything that already exists)
                                        message.Save(email.MessageFilePath, MessageFormat.Eml);

                                        // Get the batch number - THIS SHOULD NEVER HAPPEN IN A MULTI THREAD SCENARIO WITHOUT A LOCK
                                        var batchNumber = ctx.BatchNumbers.SingleOrDefault(b => b.Group == profile.Group);

                                        // If there is no batchNumber defined yet, create and insert one
                                        if (batchNumber == null)
                                        {
                                            batchNumber       = new BatchNumber();
                                            batchNumber.Group = profile.Group;
                                            ctx.BatchNumbers.InsertOnSubmit(batchNumber);
                                        }

                                        // Init to 0 if null
                                        if (!batchNumber.Value.HasValue)
                                        {
                                            batchNumber.Value = 0;
                                        }

                                        // Set the new batch number to this email
                                        email.BatchNumber = String.Format(String.IsNullOrWhiteSpace(profile.BatchNumberFormat) ? "{0:00000000}" : profile.BatchNumberFormat, ++batchNumber.Value);

                                        // Final submit of updates
                                        ctx.SubmitChanges();

                                        // Finally, commit to the database
                                        scope.Complete();
                                    }

                                    // Move the email to the archive (if this fails, but the download is complete this
                                    // will just result in a duplicate next time round if the deleted flag is not set)
                                    imap.MoveMessage(info.UniqueId, "Archive", true, false);

                                    // Log message level download stats
                                    ConfigLogger.Instance.LogDebug("ImapCollector", String.Format("Message downloaded (EmailID = {0}, Fetch Time = {1}s, Total Time = {2}s).", email.EmailID, (int)fetchTime.TotalSeconds, (int)DateTime.Now.Subtract(start).TotalSeconds));

                                    // Increment the download count
                                    count++;
                                }
                            }
                        }
                    }
                    catch (OutOfMemoryException)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        ConfigLogger.Instance.LogError("ImapCollector", e);
                    }
                    finally
                    {
                        if (message != null)
                        {
                            message.Dispose();
                        }
                    }
                }
            }

            return(count);
        }
示例#10
0
        static Settings()
        {
            #region General Settings

            using (var ctx = new EmailImportDataContext())
            {
                try
                {
                    ImapCollectorInterval = TimeSpan.Parse(ctx.Settings.Single(s => s.Name == "Interval.ImapCollector").Value);
                }
                catch
                {
                    ImapCollectorInterval = TimeSpan.FromMinutes(5);
                }

                try
                {
                    EmailMonitorInterval = TimeSpan.Parse(ctx.Settings.Single(s => s.Name == "Interval.EmailMonitor").Value);
                }
                catch
                {
                    EmailMonitorInterval = TimeSpan.FromMinutes(1);
                }

                try
                {
                    ConcurrencyLevel = int.Parse(ctx.Settings.Single(s => s.Name == "ConcurrencyLevel").Value);
                }
                catch
                {
                    ConcurrencyLevel = Environment.ProcessorCount;
                }

                try
                {
                    SmtpSizeLimit = int.Parse(ctx.Settings.Single(s => s.Name == "SmtpSizeLimit").Value) * 1024 * 1024;
                }
                catch
                { }

                try
                {
                    LiteViewerAuthorisedPCs = ctx.Settings.Single(s => s.Name == "LiteViewerAuthorisedPCs").Value;
                }
                catch
                {
                    LiteViewerAuthorisedPCs = null;
                }

                if (SmtpSizeLimit <= 0)
                {
                    SmtpSizeLimit = int.MaxValue;
                }

                var setting = ctx.Settings.SingleOrDefault(s => s.Name == "DefaultStoragePath");
                DefaultStoragePath = (setting == null) ? null : setting.Value;
                FileSystemHelper.CreateDirectory(DefaultStoragePath);

                setting = ctx.Settings.SingleOrDefault(s => s.Name == "DefaultEscalationEmail");
                DefaultEscalationEmail = (setting == null) ? null : setting.Value;

                if (String.IsNullOrWhiteSpace(DefaultEscalationEmail))
                {
                    throw new Exception("DefaultEscalationEmail setting must contain a valid email address.");
                }
            }

            #endregion

            #region Mailboxes

            MailboxProfiles = new Dictionary <Guid, MailboxProfile>();
            LoadMailboxProfiles();

            #endregion
        }