- 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)
-
0
hi
Please check the
AbpSettings
table, the email configurations are stored in it. -
0
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" isnull
? -
0
hi
You can override the
SmtpEmailSender
class to output the mail properties to the logs.Maybe it get the wrong values.
-
0
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!
-
0
hi
The exposed interface is
IEmailSender
[Dependency(ReplaceServices = true)] [ExposeServices(typeof(IEmailSender), typeof(ISmtpEmailSender), typeof(SmtpEmailSender), typeof(EmailSenderBase), typeof(CustomSmtpEmailSender))] public class CustomSmtpEmailSender : SmtpEmailSender
-
0
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 insideSendPasswortResetLinkAsync
. Tenant id is correctly logged, and also in SmtpEmailSender'sQueueAsync
. But inSendAsync
it is lost. It seems that the problem is inBackgroundJobManager
. Maybe this is a bug? -
0
hi
You are right. I will fix the tenant-switch problem. 👍
https://github.com/abpframework/abp/pull/19578
-
0
You can create a new class
MyBackgroundEmailSendingJobArgs : IMultiTenant
And use it in your
QueueAsync
method ofCustomSmtpEmailSender
. -
0
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 myQueueAsync
:(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.
-
0
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); } } }
-
0
Yes, now it works! Thank you very much for your blazing-fast replies!
-
0
Good news!