Open Closed

MFA email code is not sent after migration to ABP 10.4.1 #10801


User avatar
0
csm created

After migrating our application to ABP 10.4.1, MFA email verification codes are no longer sent.

SMTP configuration has been verified and email sending works in other parts of the application. MFA is enabled, EmailConfirmed is true, and the user is correctly redirected to the security code verification page. However, no MFA security code email is generated or delivered.

This issue did not occur before the migration.

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

5 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • In ABP 10.x the email 2FA code is only sent if the user actually has an available/verified 2FA provider. For the Email provider this effectively means: the user’s email must be verified (and similarly for SMS the phone must be verified). If the user doesn’t have a usable provider, ABP/Identity can still redirect to the “enter security code” step, but no code is generated/sent.

    • Fix (verify from DB/UI, not only what you “expect” logically):

      1. Open Identity > Users > (your user) > Personal info and ensure the email has the Verified label.
      2. If it’s not verified, verify it (or re-send confirmation and confirm).
      3. Then re-try the login flow; the email 2FA code should be generated and sent.
    • Also ensure you didn’t accidentally end up with NullEmailSender in your environment (a common “works elsewhere / not here” symptom after migrations is that one host (AuthServer / HttpApi.Host) is still using a null sender, while another host sends fine). In ABP solutions, the 2FA email is sent by the AuthServer/Host that performs the login, so SMTP must be configured there too.

    Reference behavior in ABP docs (this is the key rule that blocks sending the code):

    • “Why don't users receive a verification code even 2FA enabled? … This is because the user does not have a verified e-mail or phone number … Ensure that Verified label next to email or phone number …”
      https://abp.io/docs/latest/modules/identity/two-factor-authentication

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    2FA got some changes in 10.4, so before pointing at SMTP let's narrow down exactly where it stops. Two things to keep in mind while you check:

    • In 10.4 the email 2FA code is generated and stored on the user record server-side, so generating the code now writes to the database. If that step throws, you end up with "no code" and the email is never reached — so the server log at the moment you submit the security-code page is the key signal.
    • The 2FA email is queued as a background job. In a tiered / separated setup the login host (Auth Server) usually only enqueues it, while a separate worker host actually sends it — so which host enqueues vs. which host runs the worker and has SMTP both matter.

    Could you share:

    1. Which UI (MVC / Angular / Blazor) and whether it's tiered / Auth Server separated. After you pick Email and click Submit, do you stay on the same page with an error, or does the code-entry page appear? On MVC, the URL you land on; on Angular/Blazor, the HTTP status and response body of the request that fires when you click Submit.
    2. Which version you upgraded from, which database, and whether user sharing / shared accounts is enabled.
    3. In the same environment and tenant, do password reset / email confirmation emails actually arrive after the upgrade (not just show a success page)?
    4. Which background job provider you use, and — if tiered — which host enqueues vs. runs the worker. Is the email job showing up as pending, failed, or never created?
    5. Have you customized the Email 2FA token provider, the account emailer, the email sender, or the background job manager?

    The server log at the submit step plus the answers above will tell us whether it stops at code generation, at enqueue, or at the actual SMTP send. If the default logs aren't detailed enough, enable Debug-level logging first: https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    csm created

    Hi,

    Here are the details:

    • UI: MVC Razor.
    • Upgrade: from ABP 8.x to ABP 10.4.1.
    • Database: SQL Server.
    • No customization has been made for the MFA/2FA flow. We are using the default ABP implementation.
    • No customization has been made to the Email 2FA token provider, account emailer, email sender, or background job manager.

    Regarding background jobs, I can see entries in the AbpBackgroundJobs table. Emails are expected to be processed by the internal background worker. The web project depends on the AbpBackgroundJobsModule.

    The application redirects correctly to the VerifySecurityCode page after selecting Email and submitting the form, but the 2FA email is not received.

    We are also experiencing the same issue with Email Confirmation emails.

    At this point, the application logs no longer contain any errors related to email sending or MFA.

    Could you confirm whether any additional configuration is required in ABP 10.4.1 for email background jobs? Also, is a dedicated worker application now required for processing email jobs, or should the internal background worker still be sufficient? In ABP 8, this was working without a separate worker.

    Best regards,

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • No, ABP 10.4.1 does not require a dedicated worker app just to send emails. The built-in background job worker can process email jobs inside the same web host, as long as background job execution is actually enabled and there is no NullEmailSender replacement in that host.

    • In your case the key signal is: Email Confirmation is also not sent. That strongly indicates this is not “MFA-specific”, but rather one of these common post-migration causes:

      1. The host that enqueues/processes the job is using NullEmailSender (often added under #if DEBUG in the host module, or effectively happening due to environment/config differences after migration).
      2. Background jobs are being written to AbpBackgroundJobs, but not executed (job worker not running, disabled, or running in a different process than you think).

    What to do (verified ABP behavior)

    1. Check for NullEmailSender replacement in your web host (the app that runs the login/registration pages)
      • Search in your Host/AuthServer module for code like:
    #if DEBUG
         context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>());
         #endif
    
    • If your app is running with a configuration where that code is active, emails will never be sent (they’ll be swallowed/logged).
    • This exact pitfall is confirmed in an ABP support answer: the host can be configured to replace the sender with NullEmailSender in debug builds.
      (Link in sources)
    1. Confirm the background job is actually being executed

      • Since you already see rows in AbpBackgroundJobs, verify they are not just accumulating.
      • If the rows remain in a “pending/not processed” state (or never get deleted/updated), then the worker isn’t running.
      • In a single-host MVC app, the same web host should both enqueue and process jobs if enabled.
    2. Make sure SMTP settings are configured for the same host that executes the jobs

      • In ABP, email sending is integrated with the background job system (“send emails via background jobs”). So SMTP must be available where the background job runs.
      • If you have multiple hosts/environments, ensure the one processing jobs has the SMTP settings too.
    3. Re-check 2FA email provider prerequisites (only after email sending is fixed)

      • Email 2FA codes require the email to be verified/confirmed; ABP’s 2FA doc explicitly calls out that users won’t receive a code if the email/phone isn’t verified.

    Sources

    • https://abp.io/docs/latest/framework/infrastructure/emailing
    • https://abp.io/docs/latest/framework/infrastructure/background-jobs
    • https://abp.io/docs/latest/modules/identity/two-factor-authentication
    • https://abp.io/support/questions/9016

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    For a single (non-tiered) host, nothing new is required — it enqueues and drains its own jobs, same as v8. In the 10.4.1 tiered template, AuthServer and Web.Host don't execute background jobs; HttpApi.Host does. So the first question is: single host, or separated? That decides which process should be draining the queue.

    Look at the rows that should be getting processed — IsAbandoned = 0 and NextTryTime already due:

    select top 50 Id, JobName, ApplicationName, TryCount, LastTryTime, NextTryTime, IsAbandoned, CreationTime
    from AbpBackgroundJobs
    order by CreationTime desc;
    
    • TryCount = 0 / LastTryTime null on a due row that's been sitting a while → no attempt has been persisted. Usually that means it hasn't run, but the same state also shows while a job is executing, hung, or the host exited mid-run — TryCount is only written back on a failed attempt, and on success the row is deleted.
    • TryCount > 0 → at least one attempt failed and was written back (deserialization, DI, or the email sender / SMTP) — that shows up in the logs. IsAbandoned = 1 means the framework stopped retrying it.
    • NextTryTime in the future → not due yet, so it's waiting rather than stuck (an initial enqueue delay when TryCount = 0, a retry backoff when TryCount > 0).

    If due rows just sit there unprocessed, check the host that's supposed to drain them (HttpApi.Host in the tiered template):

    1. AbpBackgroundJobOptions.IsJobExecutionEnabled and AbpBackgroundWorkerOptions.IsEnabled aren't set to false on that host — either one stops the worker from starting, with no error. The tiered template sets IsJobExecutionEnabled = false on AuthServer/Web.Host, so check it wasn't carried over to the wrong project during the upgrade.
    2. The enqueuing host and the processing host resolve to the same database. Background jobs use the AbpBackgroundJobs connection string and fall back to Default — if the processing host points at a different DB, it drains a different AbpBackgroundJobs table while the rows you're looking at just sit.
    3. ApplicationName (new since v8): the worker only takes rows whose ApplicationName matches its own AbpBackgroundJobWorkerOptions.ApplicationName. Defaults are null on both sides and match; if you set it, or point several apps at the same table, compare the ApplicationName column on the stuck rows with that host's value.
    4. If you use a distributed lock provider (e.g. Redis) or run more than one instance: the worker takes a lock before draining, and if that lock stays held with no instance actually draining, the queue stalls with nothing logged.

    If none of that stands out, the fastest way for us to spot it is the project — a minimal reproduction where the jobs pile up, in a private GitHub repo (invite https://github.com/maliming) or zipped to liming.ma@volosoft.com.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on October 05, 2026, 11:32
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.