Refactored Test email service to provide the error message if it fails to the end user. (#1051)

This commit is contained in:
Joseph Milazzo 2022-02-09 07:14:51 -08:00 committed by GitHub
parent 9ce0aa39ce
commit edbb985405
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 21 deletions

View File

@ -92,7 +92,7 @@ namespace API.Controllers
[Authorize(Policy = "RequireAdminRole")] [Authorize(Policy = "RequireAdminRole")]
[HttpPost("test-email-url")] [HttpPost("test-email-url")]
public async Task<ActionResult<bool>> TestEmailServiceUrl(TestEmailDto dto) public async Task<ActionResult<EmailTestResultDto>> TestEmailServiceUrl(TestEmailDto dto)
{ {
return Ok(await _emailService.TestConnectivity(dto.Url)); return Ok(await _emailService.TestConnectivity(dto.Url));
} }

View File

@ -0,0 +1,10 @@
namespace API.DTOs.Email;
/// <summary>
/// Represents if Test Email Service URL was successful or not and if any error occured
/// </summary>
public class EmailTestResultDto
{
public bool Successful { get; set; }
public string ErrorMessage { get; set; }
}

View File

@ -3,8 +3,8 @@ using System.Threading.Tasks;
using API.Data; using API.Data;
using API.DTOs.Email; using API.DTOs.Email;
using API.Entities.Enums; using API.Entities.Enums;
using API.Services.Tasks;
using Flurl.Http; using Flurl.Http;
using Kavita.Common;
using Kavita.Common.EnvironmentInfo; using Kavita.Common.EnvironmentInfo;
using Kavita.Common.Helpers; using Kavita.Common.Helpers;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -16,9 +16,9 @@ public interface IEmailService
{ {
Task SendConfirmationEmail(ConfirmationEmailDto data); Task SendConfirmationEmail(ConfirmationEmailDto data);
Task<bool> CheckIfAccessible(string host); Task<bool> CheckIfAccessible(string host);
Task SendMigrationEmail(EmailMigrationDto data); Task<bool> SendMigrationEmail(EmailMigrationDto data);
Task SendPasswordResetEmail(PasswordResetEmailDto data); Task<bool> SendPasswordResetEmail(PasswordResetEmailDto data);
Task<bool> TestConnectivity(string emailUrl); Task<EmailTestResultDto> TestConnectivity(string emailUrl);
} }
public class EmailService : IEmailService public class EmailService : IEmailService
@ -40,12 +40,23 @@ public class EmailService : IEmailService
cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); cli.Settings.HttpClientFactory = new UntrustedCertClientFactory());
} }
public async Task<bool> TestConnectivity(string emailUrl) public async Task<EmailTestResultDto> TestConnectivity(string emailUrl)
{ {
FlurlHttp.ConfigureClient(emailUrl, cli => // FlurlHttp.ConfigureClient(emailUrl, cli =>
cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); // 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) public async Task SendConfirmationEmail(ConfirmationEmailDto data)
@ -64,16 +75,16 @@ public class EmailService : IEmailService
return await SendEmailWithGet(DefaultApiUrl + "/api/email/reachable?host=" + host); return await SendEmailWithGet(DefaultApiUrl + "/api/email/reachable?host=" + host);
} }
public async Task SendMigrationEmail(EmailMigrationDto data) public async Task<bool> SendMigrationEmail(EmailMigrationDto data)
{ {
var emailLink = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.EmailServiceUrl)).Value; 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<bool> SendPasswordResetEmail(PasswordResetEmailDto data)
{ {
var emailLink = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.EmailServiceUrl)).Value; 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<bool> SendEmailWithGet(string url) private static async Task<bool> SendEmailWithGet(string url)
@ -94,9 +105,9 @@ public class EmailService : IEmailService
return true; return true;
} }
} }
catch (Exception) catch (Exception ex)
{ {
return false; throw new KavitaException(ex.Message);
} }
return false; return false;
} }

View File

@ -4,10 +4,11 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr'; import { ToastrService } from 'ngx-toastr';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import { ConfirmService } from 'src/app/shared/confirm.service'; 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 { DirectoryPickerComponent, DirectoryPickerResult } from '../_modals/directory-picker/directory-picker.component';
import { ServerSettings } from '../_models/server-settings'; import { ServerSettings } from '../_models/server-settings';
@Component({ @Component({
selector: 'app-manage-settings', selector: 'app-manage-settings',
templateUrl: './manage-settings.component.html', templateUrl: './manage-settings.component.html',
@ -103,11 +104,11 @@ export class ManageSettingsComponent implements OnInit {
} }
testEmailServiceUrl() { testEmailServiceUrl() {
this.settingsService.testEmailServerSettings(this.settingsForm.get('emailServiceUrl')?.value || '').pipe(take(1)).subscribe(async (successful: boolean) => { this.settingsService.testEmailServerSettings(this.settingsForm.get('emailServiceUrl')?.value || '').pipe(take(1)).subscribe(async (result: EmailTestResult) => {
if (successful) { if (result.successful) {
this.toastr.success('Email Service Url validated'); this.toastr.success('Email Service Url validated');
} else { } else {
this.toastr.error('Email Service Url did not respond'); this.toastr.error('Email Service Url did not respond. ' + result.errorMessage);
} }
}, (err: any) => { }, (err: any) => {

View File

@ -1,9 +1,16 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { ServerSettings } from './_models/server-settings'; import { ServerSettings } from './_models/server-settings';
/**
* Used only for the Test Email Service call
*/
export interface EmailTestResult {
successful: boolean;
errorMessage: string;
}
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@ -30,7 +37,7 @@ export class SettingsService {
} }
testEmailServerSettings(emailUrl: string) { testEmailServerSettings(emailUrl: string) {
return this.http.post<boolean>(this.baseUrl + 'settings/test-email-url', {url: emailUrl}, {responseType: 'text' as 'json'}); return this.http.post<EmailTestResult>(this.baseUrl + 'settings/test-email-url', {url: emailUrl});
} }
getTaskFrequencies() { getTaskFrequencies() {