protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken) { string code; string callbackUrl; MailboxAddress address; UserPasswordResetRequestedEvent userPasswordResetRequestedEvent; switch (evt) { case UserRegisteredEvent userRegisteredEvent: Logs.PayServer.LogInformation( $"A new user just registered {userRegisteredEvent.User.Email} {(userRegisteredEvent.Admin ? "(admin)" : "")}"); if (!userRegisteredEvent.User.EmailConfirmed && userRegisteredEvent.User.RequiresEmailConfirmation) { code = await _userManager.GenerateEmailConfirmationTokenAsync(userRegisteredEvent.User); callbackUrl = _generator.EmailConfirmationLink(userRegisteredEvent.User.Id, code, userRegisteredEvent.RequestUri.Scheme, new HostString(userRegisteredEvent.RequestUri.Host, userRegisteredEvent.RequestUri.Port), userRegisteredEvent.RequestUri.PathAndQuery); userRegisteredEvent.CallbackUrlGenerated?.SetResult(new Uri(callbackUrl)); address = userRegisteredEvent.User.GetMailboxAddress(); (await _emailSenderFactory.GetEmailSender()).SendEmailConfirmation(address, callbackUrl); } else if (!await _userManager.HasPasswordAsync(userRegisteredEvent.User)) { userPasswordResetRequestedEvent = new UserPasswordResetRequestedEvent() { CallbackUrlGenerated = userRegisteredEvent.CallbackUrlGenerated, User = userRegisteredEvent.User, RequestUri = userRegisteredEvent.RequestUri }; goto passwordSetter; } else { userRegisteredEvent.CallbackUrlGenerated?.SetResult(null); } break; case UserPasswordResetRequestedEvent userPasswordResetRequestedEvent2: userPasswordResetRequestedEvent = userPasswordResetRequestedEvent2; passwordSetter: code = await _userManager.GeneratePasswordResetTokenAsync(userPasswordResetRequestedEvent.User); var newPassword = await _userManager.HasPasswordAsync(userPasswordResetRequestedEvent.User); callbackUrl = _generator.ResetPasswordCallbackLink(userPasswordResetRequestedEvent.User.Id, code, userPasswordResetRequestedEvent.RequestUri.Scheme, new HostString(userPasswordResetRequestedEvent.RequestUri.Host, userPasswordResetRequestedEvent.RequestUri.Port), userPasswordResetRequestedEvent.RequestUri.PathAndQuery); userPasswordResetRequestedEvent.CallbackUrlGenerated?.SetResult(new Uri(callbackUrl)); address = userPasswordResetRequestedEvent.User.GetMailboxAddress(); (await _emailSenderFactory.GetEmailSender()) .SendSetPasswordConfirmation(address, callbackUrl, newPassword); break; } }
public async Task <IActionResult> ForgotPassword(ForgotPasswordViewModel model) { if (ModelState.IsValid) { var user = await _userManager.FindByEmailAsync(model.Email); if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) { // Don't reveal that the user does not exist or is not confirmed return(RedirectToAction(nameof(ForgotPasswordConfirmation))); } // For more information on how to enable account confirmation and password reset please // visit https://go.microsoft.com/fwlink/?LinkID=532713 var code = await _userManager.GeneratePasswordResetTokenAsync(user); var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme); _EmailSenderFactory.GetEmailSender().SendEmail(model.Email, "Reset Password", $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>"); return(RedirectToAction(nameof(ForgotPasswordConfirmation))); } // If we got this far, something failed, redisplay form return(View(model)); }
protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken) { switch (evt) { case UserRegisteredEvent userRegisteredEvent: Logs.PayServer.LogInformation($"A new user just registered {userRegisteredEvent.User.Email} {(userRegisteredEvent.Admin ? "(admin)" : "")}"); if (!userRegisteredEvent.User.EmailConfirmed && userRegisteredEvent.User.RequiresEmailConfirmation) { var code = await _userManager.GenerateEmailConfirmationTokenAsync(userRegisteredEvent.User); var callbackUrl = _generator.EmailConfirmationLink(userRegisteredEvent.User.Id, code, userRegisteredEvent.RequestUri.Scheme, new HostString(userRegisteredEvent.RequestUri.Host, userRegisteredEvent.RequestUri.Port), userRegisteredEvent.RequestUri.PathAndQuery); _emailSenderFactory.GetEmailSender() .SendEmailConfirmation(userRegisteredEvent.User.Email, callbackUrl); } break; } }
protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken) { if (evt is InvoiceEvent invoiceEvent) { var type = WebhookSender.GetWebhookEvent(invoiceEvent); if (type is null) { return; } var store = await _storeRepository.FindStore(invoiceEvent.Invoice.StoreId); var blob = store.GetStoreBlob(); if (blob.EmailRules?.Any() is true) { var actionableRules = blob.EmailRules.Where(rule => rule.Trigger == type.Type).ToList(); if (actionableRules.Any()) { var sender = await _emailSenderFactory.GetEmailSender(invoiceEvent.Invoice.StoreId); foreach (UIStoresController.StoreEmailRule actionableRule in actionableRules) { var recipients = (actionableRule.To?.Split(",", StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>()) .Select(o => { MailboxAddressValidator.TryParse(o, out var mb); return(mb); }) .Where(o => o != null) .ToList(); if (actionableRule.CustomerEmail && MailboxAddressValidator.TryParse(invoiceEvent.Invoice.Metadata.BuyerEmail, out var bmb)) { recipients.Add(bmb); } var i = GreenfieldInvoiceController.ToModel(invoiceEvent.Invoice, _linkGenerator, null); sender.SendEmail(recipients.ToArray(), null, null, Interpolator(actionableRule.Subject, i), Interpolator(actionableRule.Body, i)); } } } } }
public async Task <IActionResult> SendEmailFromStore(string storeId, [FromBody] SendEmailRequest request) { var store = HttpContext.GetStoreData(); if (store == null) { return(this.CreateAPIError(404, "store-not-found", "The store was not found")); } var emailSender = await _emailSenderFactory.GetEmailSender(storeId); if (emailSender is null) { return(this.CreateAPIError(404, "smtp-not-configured", "Store does not have an SMTP server configured.")); } emailSender.SendEmail(request.Email, request.Subject, request.Body); return(Ok()); }
public async Task <IActionResult> SendVerificationEmail(IndexViewModel model) { if (!ModelState.IsValid) { return(View(nameof(Index), model)); } var user = await _userManager.GetUserAsync(User); if (user == null) { throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); var callbackUrl = _linkGenerator.EmailConfirmationLink(user.Id, code, Request.Scheme, Request.Host, Request.PathBase); (await _EmailSenderFactory.GetEmailSender()).SendEmailConfirmation(user.GetMailboxAddress(), callbackUrl); TempData[WellKnownTempData.SuccessMessage] = "Verification email sent. Please check your email."; return(RedirectToAction(nameof(Index))); }
public async Task <IActionResult> SendVerificationEmail(IndexViewModel model) { if (!ModelState.IsValid) { return(View(model)); } var user = await _userManager.GetUserAsync(User); if (user == null) { throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); var email = user.Email; _EmailSenderFactory.GetEmailSender().SendEmailConfirmation(email, callbackUrl); StatusMessage = "Verification email sent. Please check your email."; return(RedirectToAction(nameof(Index))); }
public async Task <IActionResult> SendVerificationEmail(IndexViewModel model) { if (!ModelState.IsValid) { return(View(model)); } var user = await _userManager.GetUserAsync(User); if (user == null) { throw new ApplicationException($"No se puede cargar usuario con ID '{_userManager.GetUserId(User)}'."); } var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); var email = user.Email; _EmailSenderFactory.GetEmailSender().SendEmailConfirmation(email, callbackUrl); StatusMessage = "El mensaje de verificación ha sido enviado. Por favor revise su correo electrónico."; return(RedirectToAction(nameof(Index))); }
public async Task <IActionResult> SendEmailFromStore(string storeId, [FromBody] SendEmailRequest request) { var store = HttpContext.GetStoreData(); if (store == null) { return(this.CreateAPIError(404, "store-not-found", "The store was not found")); } if (!MailboxAddressValidator.TryParse(request.Email, out var to)) { ModelState.AddModelError(nameof(request.Email), "Invalid email"); return(this.CreateValidationError(ModelState)); } var emailSender = await _emailSenderFactory.GetEmailSender(storeId); if (emailSender is null) { return(this.CreateAPIError(404, "smtp-not-configured", "Store does not have an SMTP server configured.")); } emailSender.SendEmail(to, request.Subject, request.Body); return(Ok()); }
void Notify(InvoiceEntity invoice, int?eventCode = null, string name = null) { CancellationTokenSource cts = new CancellationTokenSource(10000); if (!String.IsNullOrEmpty(invoice.NotificationEmail)) { // just extracting most important data for email body, merchant should query API back for full invoice based on Invoice.Id var ipn = new { invoice.Id, invoice.Status, invoice.StoreId }; // TODO: Consider adding info on ItemDesc and payment info (amount) var emailBody = NBitcoin.JsonConverters.Serializer.ToString(ipn); _EmailSenderFactory.GetEmailSender(invoice.StoreId).SendEmail( invoice.NotificationEmail, $"BtcPayServer Invoice Notification - ${invoice.StoreId}", emailBody); } if (string.IsNullOrEmpty(invoice.NotificationURL)) { return; } var invoiceStr = NBitcoin.JsonConverters.Serializer.ToString(new ScheduledJob() { TryCount = 0, Invoice = invoice, EventCode = eventCode, Message = name }); if (!string.IsNullOrEmpty(invoice.NotificationURL)) { _JobClient.Schedule(() => NotifyHttp(invoiceStr), TimeSpan.Zero); } }
public async Task <IActionResult> Register(RegisterViewModel model, string returnUrl = null, bool logon = true) { ViewData["ReturnUrl"] = returnUrl; ViewData["Logon"] = logon.ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); ViewData["AllowIsAdmin"] = _Options.AllowAdminRegistration; var policies = await _SettingsRepository.GetSettingAsync <PoliciesSettings>() ?? new PoliciesSettings(); if (policies.LockSubscription && !User.IsInRole(Roles.ServerAdmin)) { return(RedirectToAction(nameof(HomeController.Index), "Home")); } if (ModelState.IsValid) { var user = new ApplicationUser { UserName = model.Email, Email = model.Email, RequiresEmailConfirmation = policies.RequiresConfirmedEmail }; var result = await _userManager.CreateAsync(user, model.Password); if (result.Succeeded) { var admin = await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin); Logs.PayServer.LogInformation($"A new user just registered {user.Email} {(admin.Count == 0 ? "(admin)" : "")}"); if (admin.Count == 0 || (model.IsAdmin && _Options.AllowAdminRegistration)) { await _RoleManager.CreateAsync(new IdentityRole(Roles.ServerAdmin)); await _userManager.AddToRoleAsync(user, Roles.ServerAdmin); if (_Options.DisableRegistration) { // Once the admin user has been created lock subsequent user registrations (needs to be disabled for unit tests that require multiple users). policies.LockSubscription = true; await _SettingsRepository.UpdateSetting(policies); } } var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); RegisteredUserId = user.Id; _EmailSenderFactory.GetEmailSender().SendEmailConfirmation(model.Email, callbackUrl); if (!policies.RequiresConfirmedEmail) { if (logon) { await _signInManager.SignInAsync(user, isPersistent : false); } return(RedirectToLocal(returnUrl)); } else { TempData["StatusMessage"] = "Account created, please confirm your email"; return(View()); } } AddErrors(result); } // If we got this far, something failed, redisplay form return(View(model)); }
async Task Notify(InvoiceEntity invoice, InvoiceEvent invoiceEvent, bool extendedNotification, bool sendMail) { var dto = invoice.EntityToDTO(); var notification = new InvoicePaymentNotificationEventWrapper() { Data = new InvoicePaymentNotification() { Id = dto.Id, Currency = dto.Currency, CurrentTime = dto.CurrentTime, ExceptionStatus = dto.ExceptionStatus, ExpirationTime = dto.ExpirationTime, InvoiceTime = dto.InvoiceTime, PosData = dto.PosData, Price = dto.Price, Status = dto.Status, BuyerFields = invoice.RefundMail == null ? null : new Newtonsoft.Json.Linq.JObject() { new JProperty("buyerEmail", invoice.RefundMail) }, PaymentSubtotals = dto.PaymentSubtotals, PaymentTotals = dto.PaymentTotals, AmountPaid = dto.AmountPaid, ExchangeRates = dto.ExchangeRates, OrderId = dto.OrderId }, Event = new InvoicePaymentNotificationEvent() { Code = (int)invoiceEvent.EventCode, Name = invoiceEvent.Name }, ExtendedNotification = extendedNotification, NotificationURL = invoice.NotificationURL?.AbsoluteUri }; // For lightning network payments, paid, confirmed and completed come all at once. // So despite the event is "paid" or "confirmed" the Status of the invoice is technically complete // This confuse loggers who think their endpoint get duplicated events // So here, we just override the status expressed by the notification if (invoiceEvent.Name == InvoiceEvent.Confirmed) { notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Confirmed); } if (invoiceEvent.Name == InvoiceEvent.PaidInFull) { notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Paid); } ////////////////// // We keep backward compatibility with bitpay by passing BTC info to the notification // we don't pass other info, as it is a bad idea to use IPN data for logic processing (can be faked) var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike) && !string.IsNullOrEmpty(c.Address)); if (btcCryptoInfo != null) { #pragma warning disable CS0618 notification.Data.Rate = dto.Rate; notification.Data.Url = dto.Url; notification.Data.BTCDue = dto.BTCDue; notification.Data.BTCPaid = dto.BTCPaid; notification.Data.BTCPrice = dto.BTCPrice; #pragma warning restore CS0618 } if (sendMail && !String.IsNullOrEmpty(invoice.NotificationEmail)) { var json = NBitcoin.JsonConverters.Serializer.ToString(notification); var store = await _StoreRepository.FindStore(invoice.StoreId); var storeName = store.StoreName ?? "BTCPay Server"; var emailBody = $"Store: {storeName}<br>" + $"Invoice ID: {notification.Data.Id}<br>" + $"Status: {notification.Data.Status}<br>" + $"Amount: {notification.Data.Price} {notification.Data.Currency}<br>" + $"<br><details><summary>Details</summary><pre>{json}</pre></details>"; (await _EmailSenderFactory.GetEmailSender(invoice.StoreId)).SendEmail( invoice.NotificationEmail, $"{storeName} Invoice Notification - ${invoice.StoreId}", emailBody); } if (invoice.NotificationURL != null) { _Queue.Enqueue(invoice.Id, (cancellationToken) => NotifyHttp(new ScheduledJob() { TryCount = 0, Notification = notification }, cancellationToken)); } }
void Notify(InvoiceEntity invoice, InvoiceEvent invoiceEvent, bool extendedNotification) { var dto = invoice.EntityToDTO(_NetworkProvider); var notification = new InvoicePaymentNotificationEventWrapper() { Data = new InvoicePaymentNotification() { Id = dto.Id, Currency = dto.Currency, CurrentTime = dto.CurrentTime, ExceptionStatus = dto.ExceptionStatus, ExpirationTime = dto.ExpirationTime, InvoiceTime = dto.InvoiceTime, PosData = dto.PosData, Price = dto.Price, Status = dto.Status, BuyerFields = invoice.RefundMail == null ? null : new Newtonsoft.Json.Linq.JObject() { new JProperty("buyerEmail", invoice.RefundMail) }, PaymentSubtotals = dto.PaymentSubtotals, PaymentTotals = dto.PaymentTotals, AmountPaid = dto.AmountPaid, ExchangeRates = dto.ExchangeRates, }, Event = new InvoicePaymentNotificationEvent() { Code = invoiceEvent.EventCode, Name = invoiceEvent.Name }, ExtendedNotification = extendedNotification, NotificationURL = invoice.NotificationURL }; // For lightning network payments, paid, confirmed and completed come all at once. // So despite the event is "paid" or "confirmed" the Status of the invoice is technically complete // This confuse loggers who think their endpoint get duplicated events // So here, we just override the status expressed by the notification if (invoiceEvent.Name == InvoiceEvent.Confirmed) { notification.Data.Status = InvoiceState.ToString(InvoiceStatus.Confirmed); } if (invoiceEvent.Name == InvoiceEvent.PaidInFull) { notification.Data.Status = InvoiceState.ToString(InvoiceStatus.Paid); } ////////////////// // We keep backward compatibility with bitpay by passing BTC info to the notification // we don't pass other info, as it is a bad idea to use IPN data for logic processing (can be faked) var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike)); if (btcCryptoInfo != null) { #pragma warning disable CS0618 notification.Data.Rate = dto.Rate; notification.Data.Url = dto.Url; notification.Data.BTCDue = dto.BTCDue; notification.Data.BTCPaid = dto.BTCPaid; notification.Data.BTCPrice = dto.BTCPrice; #pragma warning restore CS0618 } CancellationTokenSource cts = new CancellationTokenSource(10000); if (!String.IsNullOrEmpty(invoice.NotificationEmail)) { var emailBody = NBitcoin.JsonConverters.Serializer.ToString(notification); _EmailSenderFactory.GetEmailSender(invoice.StoreId).SendEmail( invoice.NotificationEmail, $"BtcPayServer Invoice Notification - ${invoice.StoreId}", emailBody); } if (string.IsNullOrEmpty(invoice.NotificationURL) || !Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute)) { return; } var invoiceStr = NBitcoin.JsonConverters.Serializer.ToString(new ScheduledJob() { TryCount = 0, Notification = notification }); if (!string.IsNullOrEmpty(invoice.NotificationURL)) { _JobClient.Schedule(() => NotifyHttp(invoiceStr), TimeSpan.Zero); } }
private async Task <bool> IsEmailConfigured(string storeId) { return((await(_emailSenderFactory.GetEmailSender(storeId) as EmailSender)?.GetEmailSettings())?.IsComplete() is true); }