diff --git a/API/Controllers/SettingsController.cs b/API/Controllers/SettingsController.cs index ee95328d4..d42b775b2 100644 --- a/API/Controllers/SettingsController.cs +++ b/API/Controllers/SettingsController.cs @@ -92,7 +92,7 @@ namespace API.Controllers [Authorize(Policy = "RequireAdminRole")] [HttpPost("test-email-url")] - public async Task> TestEmailServiceUrl(TestEmailDto dto) + public async Task> TestEmailServiceUrl(TestEmailDto dto) { return Ok(await _emailService.TestConnectivity(dto.Url)); } diff --git a/API/DTOs/Email/EmailTestResultDto.cs b/API/DTOs/Email/EmailTestResultDto.cs new file mode 100644 index 000000000..a41a6027d --- /dev/null +++ b/API/DTOs/Email/EmailTestResultDto.cs @@ -0,0 +1,10 @@ +namespace API.DTOs.Email; + +/// +/// Represents if Test Email Service URL was successful or not and if any error occured +/// +public class EmailTestResultDto +{ + public bool Successful { get; set; } + public string ErrorMessage { get; set; } +} diff --git a/API/Services/EmailService.cs b/API/Services/EmailService.cs index 676e897b3..08d00d29d 100644 --- a/API/Services/EmailService.cs +++ b/API/Services/EmailService.cs @@ -3,8 +3,8 @@ using System.Threading.Tasks; using API.Data; using API.DTOs.Email; using API.Entities.Enums; -using API.Services.Tasks; using Flurl.Http; +using Kavita.Common; using Kavita.Common.EnvironmentInfo; using Kavita.Common.Helpers; using Microsoft.AspNetCore.Http; @@ -16,9 +16,9 @@ public interface IEmailService { Task SendConfirmationEmail(ConfirmationEmailDto data); Task CheckIfAccessible(string host); - Task SendMigrationEmail(EmailMigrationDto data); - Task SendPasswordResetEmail(PasswordResetEmailDto data); - Task TestConnectivity(string emailUrl); + Task SendMigrationEmail(EmailMigrationDto data); + Task SendPasswordResetEmail(PasswordResetEmailDto data); + Task TestConnectivity(string emailUrl); } public class EmailService : IEmailService @@ -40,12 +40,23 @@ public class EmailService : IEmailService cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); } - public async Task TestConnectivity(string emailUrl) + public async Task TestConnectivity(string emailUrl) { - FlurlHttp.ConfigureClient(emailUrl, cli => - cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); + // FlurlHttp.ConfigureClient(emailUrl, cli => + // cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); - return await SendEmailWithGet(emailUrl + "/api/email/test"); + var result = new EmailTestResultDto(); + try + { + result.Successful = await SendEmailWithGet(emailUrl + "/api/email/test"); + } + catch (KavitaException ex) + { + result.Successful = false; + result.ErrorMessage = ex.Message; + } + + return result; } public async Task SendConfirmationEmail(ConfirmationEmailDto data) @@ -64,16 +75,16 @@ public class EmailService : IEmailService return await SendEmailWithGet(DefaultApiUrl + "/api/email/reachable?host=" + host); } - public async Task SendMigrationEmail(EmailMigrationDto data) + public async Task SendMigrationEmail(EmailMigrationDto data) { var emailLink = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.EmailServiceUrl)).Value; - await SendEmailWithPost(emailLink + "/api/email/email-migration", data); + return await SendEmailWithPost(emailLink + "/api/email/email-migration", data); } - public async Task SendPasswordResetEmail(PasswordResetEmailDto data) + public async Task SendPasswordResetEmail(PasswordResetEmailDto data) { var emailLink = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.EmailServiceUrl)).Value; - await SendEmailWithPost(emailLink + "/api/email/email-password-reset", data); + return await SendEmailWithPost(emailLink + "/api/email/email-password-reset", data); } private static async Task SendEmailWithGet(string url) @@ -94,9 +105,9 @@ public class EmailService : IEmailService return true; } } - catch (Exception) + catch (Exception ex) { - return false; + throw new KavitaException(ex.Message); } return false; } diff --git a/UI/Web/src/app/admin/manage-settings/manage-settings.component.ts b/UI/Web/src/app/admin/manage-settings/manage-settings.component.ts index 7073b15ea..5de5a0ab5 100644 --- a/UI/Web/src/app/admin/manage-settings/manage-settings.component.ts +++ b/UI/Web/src/app/admin/manage-settings/manage-settings.component.ts @@ -4,10 +4,11 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ToastrService } from 'ngx-toastr'; import { take } from 'rxjs/operators'; import { ConfirmService } from 'src/app/shared/confirm.service'; -import { SettingsService } from '../settings.service'; +import { EmailTestResult, SettingsService } from '../settings.service'; import { DirectoryPickerComponent, DirectoryPickerResult } from '../_modals/directory-picker/directory-picker.component'; import { ServerSettings } from '../_models/server-settings'; + @Component({ selector: 'app-manage-settings', templateUrl: './manage-settings.component.html', @@ -103,11 +104,11 @@ export class ManageSettingsComponent implements OnInit { } testEmailServiceUrl() { - this.settingsService.testEmailServerSettings(this.settingsForm.get('emailServiceUrl')?.value || '').pipe(take(1)).subscribe(async (successful: boolean) => { - if (successful) { + this.settingsService.testEmailServerSettings(this.settingsForm.get('emailServiceUrl')?.value || '').pipe(take(1)).subscribe(async (result: EmailTestResult) => { + if (result.successful) { this.toastr.success('Email Service Url validated'); } else { - this.toastr.error('Email Service Url did not respond'); + this.toastr.error('Email Service Url did not respond. ' + result.errorMessage); } }, (err: any) => { diff --git a/UI/Web/src/app/admin/settings.service.ts b/UI/Web/src/app/admin/settings.service.ts index 01b7da5f1..ab29e4f86 100644 --- a/UI/Web/src/app/admin/settings.service.ts +++ b/UI/Web/src/app/admin/settings.service.ts @@ -1,9 +1,16 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { map } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; import { ServerSettings } from './_models/server-settings'; +/** + * Used only for the Test Email Service call + */ +export interface EmailTestResult { + successful: boolean; + errorMessage: string; +} + @Injectable({ providedIn: 'root' }) @@ -30,7 +37,7 @@ export class SettingsService { } testEmailServerSettings(emailUrl: string) { - return this.http.post(this.baseUrl + 'settings/test-email-url', {url: emailUrl}, {responseType: 'text' as 'json'}); + return this.http.post(this.baseUrl + 'settings/test-email-url', {url: emailUrl}); } getTaskFrequencies() {