mirror of
https://github.com/bitwarden/server
synced 2026-01-07 19:13:50 +00:00
feat(marketing-initiated-premium): (Auth) [PM-27541] Add optional marketing param to email verification link (#6604)
Adds an optional `&fromMarketing=premium` query parameter to the verification email link. Feature flag: `"pm-26140-marketing-initiated-premium-flow"`
This commit is contained in:
@@ -15,11 +15,13 @@ public class RegisterVerifyEmail : BaseMailModel
|
||||
// so we must land on a redirect connector which will redirect to the finish signup page.
|
||||
// Note 3: The use of a fragment to indicate the redirect url is to prevent the query string from being logged by
|
||||
// proxies and servers. It also helps reduce open redirect vulnerabilities.
|
||||
public string Url => string.Format("{0}/redirect-connector.html#finish-signup?token={1}&email={2}&fromEmail=true",
|
||||
public string Url => string.Format("{0}/redirect-connector.html#finish-signup?token={1}&email={2}&fromEmail=true{3}",
|
||||
WebVaultUrl,
|
||||
Token,
|
||||
Email);
|
||||
Email,
|
||||
!string.IsNullOrEmpty(FromMarketing) ? $"&fromMarketing={FromMarketing}" : string.Empty);
|
||||
|
||||
public string Token { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string FromMarketing { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@ namespace Bit.Core.Auth.UserFeatures.Registration;
|
||||
|
||||
public interface ISendVerificationEmailForRegistrationCommand
|
||||
{
|
||||
public Task<string?> Run(string email, string? name, bool receiveMarketingEmails);
|
||||
public Task<string?> Run(string email, string? name, bool receiveMarketingEmails, string? fromMarketing);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class SendVerificationEmailForRegistrationCommand : ISendVerificationEmai
|
||||
|
||||
}
|
||||
|
||||
public async Task<string?> Run(string email, string? name, bool receiveMarketingEmails)
|
||||
public async Task<string?> Run(string email, string? name, bool receiveMarketingEmails, string? fromMarketing)
|
||||
{
|
||||
if (_globalSettings.DisableUserRegistration)
|
||||
{
|
||||
@@ -92,7 +92,7 @@ public class SendVerificationEmailForRegistrationCommand : ISendVerificationEmai
|
||||
// If the user doesn't exist, create a new EmailVerificationTokenable and send the user
|
||||
// an email with a link to verify their email address
|
||||
var token = GenerateToken(email, name, receiveMarketingEmails);
|
||||
await _mailService.SendRegistrationVerificationEmailAsync(email, token);
|
||||
await _mailService.SendRegistrationVerificationEmailAsync(email, token, fromMarketing);
|
||||
}
|
||||
|
||||
// User exists but we will return a 200 regardless of whether the email was sent or not; so return null
|
||||
|
||||
@@ -78,7 +78,7 @@ public class HandlebarsMailService : IMailService
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public async Task SendRegistrationVerificationEmailAsync(string email, string token)
|
||||
public async Task SendRegistrationVerificationEmailAsync(string email, string token, string? fromMarketing)
|
||||
{
|
||||
var message = CreateDefaultMessage("Verify Your Email", email);
|
||||
var model = new RegisterVerifyEmail
|
||||
@@ -86,7 +86,8 @@ public class HandlebarsMailService : IMailService
|
||||
Token = WebUtility.UrlEncode(token),
|
||||
Email = WebUtility.UrlEncode(email),
|
||||
WebVaultUrl = _globalSettings.BaseServiceUri.Vault,
|
||||
SiteName = _globalSettings.SiteName
|
||||
SiteName = _globalSettings.SiteName,
|
||||
FromMarketing = WebUtility.UrlEncode(fromMarketing),
|
||||
};
|
||||
await AddMessageContentAsync(message, "Auth.RegistrationVerifyEmail", model);
|
||||
message.MetaData.Add("SendGridBypassListManagement", true);
|
||||
|
||||
@@ -38,7 +38,7 @@ public interface IMailService
|
||||
/// <returns>Task</returns>
|
||||
Task SendFreeOrgOrFamilyOrgUserWelcomeEmailAsync(User user, string familyOrganizationName);
|
||||
Task SendVerifyEmailEmailAsync(string email, Guid userId, string token);
|
||||
Task SendRegistrationVerificationEmailAsync(string email, string token);
|
||||
Task SendRegistrationVerificationEmailAsync(string email, string token, string? fromMarketing);
|
||||
Task SendTrialInitiationSignupEmailAsync(
|
||||
bool isExistingUser,
|
||||
string email,
|
||||
|
||||
@@ -26,7 +26,7 @@ public class NoopMailService : IMailService
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendRegistrationVerificationEmailAsync(string email, string hint)
|
||||
public Task SendRegistrationVerificationEmailAsync(string email, string hint, string? fromMarketing)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
@@ -109,8 +109,12 @@ public class AccountsController : Controller
|
||||
[HttpPost("register/send-verification-email")]
|
||||
public async Task<IActionResult> PostRegisterSendVerificationEmail([FromBody] RegisterSendVerificationEmailRequestModel model)
|
||||
{
|
||||
// Only pass fromMarketing if the feature flag is enabled
|
||||
var isMarketingFeatureEnabled = _featureService.IsEnabled(FeatureFlagKeys.MarketingInitiatedPremiumFlow);
|
||||
var fromMarketing = isMarketingFeatureEnabled ? model.FromMarketing : null;
|
||||
|
||||
var token = await _sendVerificationEmailForRegistrationCommand.Run(model.Email, model.Name,
|
||||
model.ReceiveMarketingEmails);
|
||||
model.ReceiveMarketingEmails, fromMarketing);
|
||||
|
||||
if (token != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user