Exemplo n.º 1
0
        public void SendNotice(string emailAddress, ErrorNotificationModel notification)
        {
            string notificationType = String.Concat(notification.TypeName, " Occurrence");

            if (notification.IsNew)
            {
                notificationType = String.Concat("New ", notification.TypeName);
            }
            else if (notification.IsRegression)
            {
                notificationType = String.Concat(notification.TypeName, " Regression");
            }

            if (notification.IsCritical)
            {
                notificationType = String.Concat("Critical ", notificationType);
            }

            notification.BaseUrl          = Settings.Current.BaseURL;
            notification.NotificationType = notificationType;

            MailMessage msg = _emailGenerator.GenerateMessage(notification, "Notice");

            msg.To.Add(emailAddress);
            msg.Headers.Add("X-Mailer-Machine", Environment.MachineName);
            msg.Headers.Add("X-Mailer-Date", DateTime.Now.ToString());
            SendMessage(msg);
        }
Exemplo n.º 2
0
 public Task SendNoticeAsync(string emailAddress, ErrorNotificationModel notification)
 {
     return(Task.Run(() => SendNotice(emailAddress, notification)));
 }
Exemplo n.º 3
0
 public Task SendNoticeAsync(string emailAddress, ErrorNotificationModel notification)
 {
     return(Task.Delay(0));
 }
Exemplo n.º 4
0
        private object ProcessNotification(IMessage <ErrorNotification> message)
        {
            int emailsSent = 0;
            ErrorNotification errorNotification = message.GetBody();

            Log.Trace().Message("Process notification: project={0} error={1} stack={2}", errorNotification.ProjectId, errorNotification.ErrorId, errorNotification.ErrorStackId).Write();

            var project = _projectRepository.GetByIdCached(errorNotification.ProjectId);

            if (project == null)
            {
                Log.Error().Message("Could not load project {0}.", errorNotification.ProjectId).Write();
                return(null);
            }
            Log.Trace().Message("Loaded project: name={0}", project.Name).Write();

            var organization = _organizationRepository.GetByIdCached(project.OrganizationId);

            if (organization == null)
            {
                Log.Error().Message("Could not load organization {0}.", project.OrganizationId).Write();
                return(null);
            }
            Log.Trace().Message("Loaded organization: name={0}", organization.Name).Write();

            var stack = _stackRepository.GetById(errorNotification.ErrorStackId);

            if (stack == null)
            {
                Log.Error().Message("Could not load stack {0}.", errorNotification.ErrorStackId).Write();
                return(null);
            }

            if (!organization.HasPremiumFeatures)
            {
                Log.Trace().Message("Skipping because organization does not have premium features.").Write();
                return(null);
            }

            if (stack.DisableNotifications || stack.IsHidden)
            {
                Log.Trace().Message("Skipping because stack notifications are disabled or it's hidden.").Write();
                return(null);
            }

            Log.Trace().Message("Loaded stack: title={0}", stack.Title).Write();
            int totalOccurrences = stack.TotalOccurrences;

            // after the first 5 occurrences, don't send a notification for the same stack more then once every 15 minutes
            var lastTimeSent = _cacheClient.Get <DateTime>(String.Concat("NOTIFICATION_THROTTLE_", errorNotification.ErrorStackId));

            if (totalOccurrences > 5 && !errorNotification.IsRegression && lastTimeSent != DateTime.MinValue &&
                lastTimeSent > DateTime.Now.AddMinutes(-15))
            {
                Log.Info().Message("Skipping message because of throttling: last sent={0} occurrences={1}", lastTimeSent, totalOccurrences).Write();
                return(null);
            }

            foreach (var kv in project.NotificationSettings)
            {
                var settings = kv.Value;
                Log.Trace().Message("Processing notification: user={0}", kv.Key).Write();

                var user = _userRepository.GetById(kv.Key);
                if (user == null || String.IsNullOrEmpty(user.EmailAddress))
                {
                    Log.Error().Message("Could not load user {0} or blank email address {1}.", kv.Key, user != null ? user.EmailAddress : "").Write();
                    continue;
                }

                if (!user.IsEmailAddressVerified)
                {
                    Log.Info().Message("User {0} with email address {1} has not been verified.", kv.Key, user != null ? user.EmailAddress : "").Write();
                    continue;
                }

                if (!user.EmailNotificationsEnabled)
                {
                    Log.Trace().Message("User {0} with email address {1} has email notifications disabled.", kv.Key, user != null ? user.EmailAddress : "").Write();
                    continue;
                }

                if (!user.OrganizationIds.Contains(project.OrganizationId))
                {
                    // TODO: Should this notification setting be deleted?
                    Log.Error().Message("Unauthorized user: project={0} user={1} organization={2} error={3}", project.Id, kv.Key,
                                        project.OrganizationId, errorNotification.ErrorId).Write();
                    continue;
                }

                Log.Trace().Message("Loaded user: email={0}", user.EmailAddress).Write();

                bool shouldReportOccurrence    = settings.Mode != NotificationMode.None;
                bool shouldReportCriticalError = settings.ReportCriticalErrors && errorNotification.IsCritical;
                bool shouldReportRegression    = settings.ReportRegressions && errorNotification.IsRegression;

                Log.Trace().Message("Settings: mode={0} critical={1} regression={2} 404={3} bots={4}",
                                    settings.Mode, settings.ReportCriticalErrors,
                                    settings.ReportRegressions, settings.Report404Errors,
                                    settings.ReportKnownBotErrors).Write();
                Log.Trace().Message("Should process: occurrence={0} critical={1} regression={2}",
                                    shouldReportOccurrence, shouldReportCriticalError,
                                    shouldReportRegression).Write();

                if (settings.Mode == NotificationMode.New && !errorNotification.IsNew)
                {
                    shouldReportOccurrence = false;
                    Log.Trace().Message("Skipping because message is not new.").Write();
                }

                // check for 404s if the user has elected to not report them
                if (shouldReportOccurrence && settings.Report404Errors == false && errorNotification.Code == "404")
                {
                    shouldReportOccurrence = false;
                    Log.Trace().Message("Skipping because message is 404.").Write();
                }

                // check for known bots if the user has elected to not report them
                if (shouldReportOccurrence && settings.ReportKnownBotErrors == false &&
                    !String.IsNullOrEmpty(errorNotification.UserAgent))
                {
                    ClientInfo info = null;
                    try {
                        info = Parser.GetDefault().Parse(errorNotification.UserAgent);
                    } catch (Exception ex) {
                        Log.Warn().Project(errorNotification.ProjectId).Message("Unable to parse user agent {0}. Exception: {1}",
                                                                                errorNotification.UserAgent, ex.Message).Write();
                    }

                    if (info != null && info.Device.IsSpider)
                    {
                        shouldReportOccurrence = false;
                        Log.Trace().Message("Skipping because message is bot.").Write();
                    }
                }

                // stack being set to send all will override all other settings
                if (!shouldReportOccurrence && !shouldReportCriticalError && !shouldReportRegression)
                {
                    continue;
                }

                var model = new ErrorNotificationModel(errorNotification)
                {
                    ProjectName      = project.Name,
                    TotalOccurrences = totalOccurrences
                };

                // don't send notifications in non-production mode to email addresses that are not on the outbound email list.
                if (Settings.Current.WebsiteMode != WebsiteMode.Production &&
                    !Settings.Current.AllowedOutboundAddresses.Contains(v => user.EmailAddress.ToLowerInvariant().Contains(v)))
                {
                    Log.Trace().Message("Skipping because email is not on the outbound list and not in production mode.").Write();
                    continue;
                }

                Log.Trace().Message("Sending email to {0}...", user.EmailAddress).Write();
                _mailer.SendNotice(user.EmailAddress, model);
                emailsSent++;
                Log.Trace().Message("Done sending email.").Write();
            }

            // if we sent any emails, mark the last time a notification for this stack was sent.
            if (emailsSent > 0)
            {
                _cacheClient.Set(String.Concat("NOTIFICATION_THROTTLE_", errorNotification.ErrorStackId), DateTime.Now, DateTime.Now.AddMinutes(15));
            }

            return(null);
        }
Exemplo n.º 5
0
 public void SendNotice(string emailAddress, ErrorNotificationModel notification)
 {
 }