Example #1
0
        public async Task <bool> UsernameIsAvailable(string username, string subjectId = null)
        {
            // In this user store, usernames are restricted to email addresses
            if (!EmailAddressChecker.EmailIsValid(username))
            {
                return(false);
            }
            var response = await GetUserByUsernameAsync(username);

            if (response.IsOk)
            {
                return(response.Result.SubjectId == subjectId);
            }
            return(true);
        }
 private bool IsValidEmailAddress(string sendTo)
 {
     return(EmailAddressChecker.EmailIsValid(sendTo));
 }
Example #3
0
        public async Task <WebStatus> SendOneTimeCodeAsync(SendCodeInputModel model)
        {
            _logger.LogDebug("Begin send one time code for {0}", model.Username);

            if (!ApplicationIdIsNullOrValid(model.ApplicationId))
            {
                return(WebStatus.Error(_localizer["Invalid application id."], HttpStatusCode.BadRequest));
            }

            // Note: Need to keep messages generic as to not reveal whether an account exists or not.
            var usernameIsValidEmail = EmailAddressChecker.EmailIsValid(model.Username);
            var defaultMessage       = usernameIsValidEmail
                ? _localizer["Message sent. Please check your email."]
                : _localizer["We sent a code to the email address asociated with your account (if found). Please check your email."];

            // If the username provide is not an email address or phone number, tell the user "we sent you a code if you have an account"
            var userResponse = await _userStore.GetUserByUsernameAsync(model.Username);

            if (userResponse.HasError)
            {
                _logger.LogDebug("User not found");

                if (!usernameIsValidEmail)
                {
                    _logger.LogError("No valid email address found for user {0}", model.Username);
                    return(WebStatus.Success(defaultMessage)); // generic message prevent account enumeration
                }

                var result = await _messageService.SendAccountNotFoundMessageAsync(model.ApplicationId, model.Username);

                if (result.HasError)
                {
                    return(ServerError(result.Text));
                }
                // the fact that the user doesn't have an account is communicated privately via email
                await _eventNotificationService.NotifyEventAsync(model.Username, EventType.AccountNotFound);

                return(WebStatus.Success(defaultMessage)); // generic message prevent account enumeration
            }

            var user = userResponse.Result;

            _logger.LogDebug("User found");

            if (!EmailAddressChecker.EmailIsValid(user.Email))
            {
                _logger.LogError("No valid email address found for user {0}", model.Username);
                return(WebStatus.Success(defaultMessage)); // generic message prevent account enumeration
            }

            var oneTimeCodeResponse = await _oneTimeCodeService.GetOneTimeCodeAsync(
                user.Email,
                TimeSpan.FromMinutes(_options.OneTimeCodeValidityMinutes),
                model.NextUrl);

            switch (oneTimeCodeResponse.Status.StatusCode)
            {
            case GetOneTimeCodeStatusCode.Success:
                var status = await _messageService.SendOneTimeCodeAndLinkMessageAsync(model.ApplicationId,
                                                                                      model.Username, oneTimeCodeResponse.Result.ShortCode, oneTimeCodeResponse.Result.LongCode);

                await _eventNotificationService.NotifyEventAsync(model.Username, EventType.RequestOneTimeCode);

                if (status.IsOk)
                {
                    status = Status.Success(defaultMessage);
                }
                SetNonce(oneTimeCodeResponse.Result.ClientNonce);
                return(new WebStatus(status));

            case GetOneTimeCodeStatusCode.TooManyRequests:
                return(WebStatus.Error(_localizer["Please wait a few minutes before requesting a new code."], HttpStatusCode.TooManyRequests));

            case GetOneTimeCodeStatusCode.ServiceFailure:
            default:
                return(ServerError(_localizer["Hmm. Something went wrong. Please try again."]));
            }
        }
Example #4
0
        /// <summary>
        /// Send an email
        /// </summary>
        /// <param name="email">contents of the email to send</param>
        /// <returns>send email task</returns>
        public async Task SendEmail(IEmail email)
        {
            // check the email addresses
            if (email.To == null || email.To.Count < 1)
            {
                this.log.LogException("got empty email address list");
            }

            foreach (string to in email.To)
            {
                if (!EmailAddressChecker.IsValidEmail(to))
                {
                    this.log.LogException("got bad email address: " + to);
                }
            }

            // create a new message
            SendGridMessage myMessage = new SendGridMessage();

            // assign the from address
            myMessage.From = new EmailAddress(email.FromAddress, email.FromName);

            // assign the recipients
            foreach (string emailAddress in email.To)
            {
                myMessage.AddTo(emailAddress);
            }

            // assign the subject
            myMessage.Subject = email.Subject;

            // assign the body of the email
            myMessage.HtmlContent      = email.HtmlBody;
            myMessage.PlainTextContent = email.TextBody;

            // assign the footer of the email
            myMessage.SetFooterSetting(true, email.HtmlFooter, email.TextFooter);

            // email reporting features
            myMessage.SetClickTracking(true, false);       // weekly stats of which links users opened in our emails
            myMessage.SetOpenTracking(true, string.Empty); // weekly stats of how many of our emails were opened

            // set email category. All e-mails must have category in place.
            string category = null;

            PropertyInfo[] properties = email.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo property in properties)
            {
                if (property.Name == "Category")
                {
                    object categoryPropObj = property.GetValue(email, null);
                    if (categoryPropObj == null)
                    {
                        this.log.LogException(new ArgumentException("Each email message must have a category. Please set one."));
                    }

                    category = categoryPropObj.ToString();
                }
            }

            if (!string.IsNullOrWhiteSpace(category))
            {
                myMessage.AddCategory(category); // email stats will be bucketed by reportingCategory
            }

            // send it
            SendGridClient client = new SendGridClient(this.sendGridKey);

            this.log.LogInformation("Sending email from:" + email.FromAddress + ", to:" + string.Join(",", email.To.ToArray()) + " subject:" + email.Subject);
            Response response = await client.SendEmailAsync(myMessage);

            if (response.StatusCode != System.Net.HttpStatusCode.Accepted && response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                this.log.LogException(new Exception("Got " + response.StatusCode.ToString() + " status code from Sendgrid"));
            }
        }