Open Closed

email confirmation/ password reset not working after upgrading to 8.0 #7052


User avatar
0
cbogner85 created
  • ABP Framework version: v8.0.5
  • UI Type: MVC
  • Database System: EF Core (SQL Server)
  • Tiered (for MVC) or Auth Server Separated (for Angular): no

Hello,

we recently updated from ABP 7.3 to 8.0.5.

Since the update, the system no longer sends email confirmation and forgot password emails. Our system sends other status emails, which work. I noticed that under Tenants -> Setting Management there is now an option to "Allow changing email settings" and suspected that as the cause. After activation, I was able to update email settings within the tenants, but this didn't make any changes.

I can see that the AbpBackgroundJobs table is overflowing with failed email jobs:

Inside the application logfile, I see the following error:

Mailbox unavailable. The server response was: 5.7.0 The sender address used in the Mail From does not belong to your authenticated STRATO package.

Strangely, we no longer use Strato email addresses at all. We were using Strato, but switched about 2 years ago and of course changed the SMTP settings - it always worked and the other system emails also work.

I can't find definitions for Strato SMTP server anywhere - neither in the tenants' email settings nor in the database tables (AbpSettings, AbpSettingDefinitions).

Apparently there are some very old email settings cached somewhere, but I can't find out where. We don't use Redis and I have already tried restarting the server. There are also no email settings stored in the appsettings.json.

Additional information: We have a central login page for all tenants and therefore I have overwritten some ABP methods (LoginModel, ResetPasswordModel, SendSecurityCodeModel etc.) by simply deactivating the TenantFilter, searching for the user using the email address (a user cannot exist in multiple tenants) and setting the current tenant based on the user (CurrentTenant.Change(user.tenantId)). But I don't think this has anything to do with the problem, since - as written above - Strato's SMTP server addresses are not stored anywhere.

What is happening here?

Thanks in advance.

PS: In my development environment everthing works as expected.


12 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please check the AbpSettings table, the email configurations are stored in it.

  • User Avatar
    0
    cbogner85 created

    Hi maliming,

    thanks for you quick response. I already did that, no Strato SMTP settings were stored there:

    Restarted the server again last night, now it seems the cache (?) was refreshed, however, it still doesn't work. Now I get the following error:

    [ERR] Failure sending mail.
    System.Net.Mail.SmtpException: Failure sending mail.
     ---> System.Net.Sockets.SocketException (10061): A connection could not be established because the target computer refused to connect.
       at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
       at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
       at System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
    --- End of stack trace from previous location ---
       at System.Threading.Tasks.TaskToAsyncResult.End(IAsyncResult asyncResult)
       at System.Net.Sockets.TcpClient.EndConnect(IAsyncResult asyncResult)
       at System.Net.Mail.SmtpConnection.ConnectAndHandshakeAsyncResult.InitializeConnectionCallback(IAsyncResult result)
    --- End of stack trace from previous location ---
       at System.Net.Mail.SmtpClient.ConnectCallback(IAsyncResult result)
       --- End of inner exception stack trace ---
       at Volo.Abp.Emailing.Smtp.SmtpEmailSender.SendEmailAsync(MailMessage mail)
       at Volo.Abp.Emailing.EmailSenderBase.SendAsync(MailMessage mail, Boolean normalize)
       at Volo.Abp.Emailing.EmailSenderBase.SendAsync(String to, String subject, String body, Boolean isBodyHtml, AdditionalEmailSendingArgs additionalEmailSendingArgs)
       at Volo.Abp.Emailing.BackgroundEmailSendingJob.ExecuteAsync(BackgroundEmailSendingJobArgs args)
       at Volo.Abp.BackgroundJobs.BackgroundJobExecuter.ExecuteAsync(JobExecutionContext context)
    

    However, sending a test mail from email setting dialog works (as all other emails sent from my own code work, too).

    Did you see contents of AbpBackgroundJobs I posted above? Is it normal that "from" is null?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can override the SmtpEmailSender class to output the mail properties to the logs.

    Maybe it get the wrong values.

  • User Avatar
    0
    cbogner85 created

    Hi maliming,

    thanks for the hint. I'd like to try that, but I don't manage to override SmtpEmailSender. I tried the following:

        [Dependency(ReplaceServices = true)]
        [ExposeServices(typeof(ISmtpEmailSender), typeof(SmtpEmailSender), typeof(EmailSenderBase), typeof(CustomSmtpEmailSender))]
    
        public class CustomSmtpEmailSender : SmtpEmailSender
        {
            protected IAuditingManager AuditingManager { get; set; }
            public CustomSmtpEmailSender(ISmtpEmailSenderConfiguration smtpConfiguration, IBackgroundJobManager backgroundJobManager, IAuditingManager auditingManager) : base(smtpConfiguration, backgroundJobManager)
            {
                AuditingManager = auditingManager;
            }
    
            private async Task LogData()
            {
                using (var auditingScope = AuditingManager.BeginScope())
                {
                    string username = await SmtpConfiguration.GetUserNameAsync();
                    string password = await SmtpConfiguration.GetPasswordAsync();
                    if (string.IsNullOrEmpty(password))
                    {
                        password = "empty";
                    }
                    else
                    {
                        password = "hidden";
                    }
                    string host = await SmtpConfiguration.GetHostAsync();
                    int port = await SmtpConfiguration.GetPortAsync();
    
                    AuditingManager.Current.Log.Comments.Add(string.Format("Emailsettings: SMTP: {0}, Port:{1}, Username: {2}, Password: {3}", host, port, username, password));
                    await auditingScope.SaveAsync();
                }
            }
    
            protected async override Task SendEmailAsync(MailMessage mail)
            {
    
                await LogData();
                await base.SendEmailAsync(mail);
            }
    
            public async override Task SendAsync(MailMessage mail, bool normalize = true)
            {
                await LogData();
                await base.SendAsync(mail, normalize);
            }
    
            public async override Task SendAsync(string from, string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs additionalEmailSendingArgs = null)
            {
                await LogData();
                await base.SendAsync(from, to, subject, body, isBodyHtml, additionalEmailSendingArgs);
            }
    
            public async override Task SendAsync(string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs additionalEmailSendingArgs = null)
            {
                await LogData();
                await base.SendAsync(to, subject, body, isBodyHtml, additionalEmailSendingArgs);
            }
        }
    

    But no data is logged, I also tried to set breakpoints and found out that none of the overriden methods are reached when sending mails. What am I doing wrong? I have overriden other ABP services in the past using the same way and it worked.

    (Also tried to replace the service in WebModule using context.Services.Replace(ServiceDescriptor.Transient<SmtpEmailSender, CustomSmtpEmailSender>()); but didn't work either).

    Thanks for you support!

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The exposed interface is IEmailSender

     [Dependency(ReplaceServices = true)]
      [ExposeServices(typeof(IEmailSender), typeof(ISmtpEmailSender), typeof(SmtpEmailSender), typeof(EmailSenderBase), typeof(CustomSmtpEmailSender))]
      public class CustomSmtpEmailSender : SmtpEmailSender
    
  • User Avatar
    0
    cbogner85 created

    Thanks, that worked!

    Now the following error is logged:

    Setting value for 'Abp.Mailing.Smtp.UserName' is null or empty!

    Of course, it is not empty for any tenant. Therefore I also logged the current tenant id and found out that it's empty, too... so email settings are retrieved from the host instead of the current tenant. Since I need different email settings for tenants, I can't just define email settings on the host to make it working again.

    I further investigated ABP's source code. Mails are queued in AccountEmailer.cs, I extended it as well and logged the current tenant inside SendPasswortResetLinkAsync. Tenant id is correctly logged, and also in SmtpEmailSender's QueueAsync. But in SendAsync it is lost. It seems that the problem is in BackgroundJobManager. Maybe this is a bug?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You are right. I will fix the tenant-switch problem. 👍

    https://github.com/abpframework/abp/pull/19578

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    You can create a new class MyBackgroundEmailSendingJobArgs : IMultiTenant

    And use it in your QueueAsync method of CustomSmtpEmailSender.

  • User Avatar
    0
    cbogner85 created

    Hi maliming,

    thank you!

    Unfortunately, this doesn't work... if I create my own class MyBackgroundEmailSendingJobArgs, jobs fail because of the different name:

    Undefined background job for the job name: MyProject.Extensions.MyBackgroundEmailSendingJobArgs

    Also tried to create a BackgroundEmailSendingJobArgs in the same namespace (Volo.Abp.Emailing) , then jobs are recognized from the worker, but tenant is null again and it uses hosts email settings, although I set in my QueueAsync :(

       public async override Task QueueAsync(string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs additionalEmailSendingArgs = null)
       {
    
           if (!BackgroundJobManager.IsAvailable())
           {
               await SendAsync(to, subject, body, isBodyHtml, additionalEmailSendingArgs);
               return;
           }
    
           await BackgroundJobManager.EnqueueAsync(
               new BackgroundEmailSendingJobArgs   
               {
                   TenantId = CurrentTenant.Id,
                   To = to,
                   Subject = subject,
                   Body = body,
                   IsBodyHtml = isBodyHtml,
                   AdditionalEmailSendingArgs = additionalEmailSendingArgs
               }
           );
       }
    

    Anything I can do or do I have to wait for the next minor release? It's some kind of critical as people can't activate their accounts if email confirmation is required and we receive many support tickets from people who can't reset their passwords.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Undefined background job for the job name: MyProject.Extensions.MyBackgroundEmailSendingJobArgs

    Add your MyBackgroundEmailSendingJob class too.

    public class MyBackgroundEmailSendingJob : AsyncBackgroundJob<MyBackgroundEmailSendingJobArgs>, ITransientDependency
    {
        protected IEmailSender EmailSender { get; }
    
        public BackgroundEmailSendingJob(IEmailSender emailSender)
        {
            EmailSender = emailSender;
        }
    
        public async override Task ExecuteAsync(MyBackgroundEmailSendingJobArgs args)
        {
            // you can get correct tenant id here.
            
            if (args.From.IsNullOrWhiteSpace())
            {
                await EmailSender.SendAsync(args.To, args.Subject, args.Body, args.IsBodyHtml, args.AdditionalEmailSendingArgs);
            }
            else
            {
                await EmailSender.SendAsync(args.From!, args.To, args.Subject, args.Body, args.IsBodyHtml, args.AdditionalEmailSendingArgs);
            }
        }
    }
    
    
  • User Avatar
    0
    cbogner85 created

    Yes, now it works! Thank you very much for your blazing-fast replies!

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Good news!

Made with ❤️ on ABP v9.1.0-preview. Updated on November 01, 2024, 05:35