예제 #1
0
        public static async Task <User> CreateAsync(string userHash, HoverDb db)
        {
            Db = db;
            User x = new User();
            await x.InitializeAsync(userHash);

            return(x);
        }
예제 #2
0
        //        [Newtonsoft.Json.JsonConstructor]

        public async Task <string> UserSignup(Settings settings, ILogger <UserController> logger, HoverDb db, IDataProtectionProvider provider)
        {
            Settings   = settings;
            Logger     = logger;
            Db         = db;
            _protector = provider.CreateProtector("Hover.Models.UserSignup");


            Task <string> callingCaptcha = ReCaptchErrorAsync(settings.CaptchaSecret);

            // Check input html page has pattern="[A-Za-z]+[A-Za-z -]+"
            name = System.Text.RegularExpressions.Regex.Matches(name, @"[A-Za-z]+[A-Za-z -]+").Cast <System.Text.RegularExpressions.Match>()
                   .Aggregate("", (s, e) => s + e.Value, s => s);

            email = email.ToLower();
            // userHash is a unique Key for a user (email)
            string userHash       = Hash.GetHash(email, Settings.HashSalt, Settings.IterationCount);
            string emailEncrypted = _protector.Protect(email);

            Logger.LogInformation($"UserSignup userHash= {userHash}, emailEncrypted= {emailEncrypted}");

            string captchaError = await callingCaptcha;

            if (captchaError != null)
            {
                return(captchaError);
            }


            // Call DataStore
            string oldEmailEncrypted = null, message = null;

            using (var cmd = Db.Hconn.CreateCommand())
            {
                await Db.ReadyConnection();

                cmd.CommandText = "UserNew";

                cmd.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter
                {
                    ParameterName = "@userHashIn",
                    DbType        = DbType.String,
                    Value         = userHash,
                });
                cmd.Parameters.AddWithValue("@emailEncrypted", emailEncrypted);
                cmd.Parameters.AddWithValue("@usernameIn", name);

                cmd.CommandType = System.Data.CommandType.StoredProcedure;

                var reader = await cmd.ExecuteReaderAsync();

                if (reader.Read())
                {
                    if (reader["oldEmailEncrypted"] != DBNull.Value)
                    {
                        oldEmailEncrypted = reader["oldEmailEncrypted"].ToString();
                    }
                    if (reader["message"] != DBNull.Value)
                    {
                        message = reader["message"].ToString();
                    }
                }
            }

            // if there was something to report, no email unless the extremely rare hash collision -> different email addresses with same hash
            if (oldEmailEncrypted != null && email != _protector.Unprotect(oldEmailEncrypted))
            {
                // It is almost impossible for a hash collision on email addresses, likely something else, needs attention
                Logger.LogCritical($"UserSignup {email} Not Saved, hash collision {userHash} !? {message}");
            }
            else if (message != null)
            {
                return(message);
            }


            // Send email
            var mineMessage = new MimeMessage();

            mineMessage.From.Add(new MailboxAddress(settings.MailboxAddressUpdateName, settings.MailboxAddressUpdateAddress));

            //   10/10 on mail-tester.com
            mineMessage.To.Add(new MailboxAddress(name, email));

            if (oldEmailEncrypted != null)
            {
                mineMessage.Bcc.Add(new MailboxAddress("hash collision!", settings.MailboxAddressPrivacyAddress));
            }

            // Can help lower spam rating
            mineMessage.Headers.Add("List-Unsubscribe", $"<mailto: {settings.MailboxAddressPrivacyAddress}?subject=unsubscribe{userHash}>");


            mineMessage.Subject = "Thank you for signing up " + name + ".";


            //     message.Body = new TextPart(MimeKit.Text.TextFormat.Html) { Text = string.Format(Mail.Templates.General.markup, name, userHash) }; // with only HTML Mime type

            var builder = new BodyBuilder
            {
                // Send both text and HTML
                TextBody = string.Format(Mail.Templates.Welcome.text, name, userHash, System.Net.WebUtility.UrlEncode(name)),
                HtmlBody = string.Format(Mail.Templates.Welcome.html, name, userHash, System.Net.WebUtility.UrlEncode(name))
            };

            mineMessage.Body = builder.ToMessageBody();

            using (var emailClient = new SmtpClient())
            {
                try
                {
                    emailClient.Connect(settings.EmailClientHost, settings.EmailClientPort, settings.EmailClientUseSsl);

                    emailClient.AuthenticationMechanisms.Remove("XOAUTH2");

                    emailClient.Authenticate(settings.EmailClientUserName, settings.EmailClientPassword);

                    await emailClient.SendAsync(mineMessage);
                }
                catch (Exception ex)
                {
                    // Catch email error, log it and return something user friendly
                    Logger.LogCritical($"email to { userHash } error : { ex.ToString() }");
                    return("We had a problem sending you an email. We will try again later.");
                }
                finally
                {
                    emailClient.Disconnect(true);
                }
            }

            return("Thank you for signing up " + name + ", an email has been sent to " + email);
        }