diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/IInvitationEmailSender.cs b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/IInvitationEmailSender.cs index 799242fb4..536ac9c07 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/IInvitationEmailSender.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/IInvitationEmailSender.cs @@ -12,6 +12,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation { public interface IInvitationEmailSender { + bool IsActive { get; } + Task SendNewUserEmailAsync(IUser assigner, IUser assignee, string appName); Task SendExistingUserEmailAsync(IUser assigner, IUser assignee, string appName); diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailEventConsumer.cs b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailEventConsumer.cs index 58111c21f..01211fcd2 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailEventConsumer.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailEventConsumer.cs @@ -55,6 +55,11 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation public async Task On(Envelope @event) { + if (!emailSender.IsActive) + { + return; + } + if (@event.Payload is AppContributorAssigned appContributorAssigned && appContributorAssigned.Actor.IsSubject) { var assignerId = appContributorAssigned.Actor.Identifier; diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailSender.cs b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailSender.cs index ac92cdc63..867111fb8 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailSender.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEmailSender.cs @@ -21,6 +21,11 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation private readonly ISemanticLog log; private readonly InvitationEmailTextOptions texts; + public bool IsActive + { + get { return true; } + } + public InvitationEmailSender( IOptions texts, IEmailSender emailSender, diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Invitation/NoopInvitationEmailSender.cs b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/NoopInvitationEmailSender.cs new file mode 100644 index 000000000..899d8bdb6 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Apps/Invitation/NoopInvitationEmailSender.cs @@ -0,0 +1,31 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Threading.Tasks; +using Squidex.Infrastructure.Tasks; +using Squidex.Shared.Users; + +namespace Squidex.Domain.Apps.Entities.Apps.Invitation +{ + public sealed class NoopInvitationEmailSender : IInvitationEmailSender + { + public bool IsActive + { + get { return false; } + } + + public Task SendExistingUserEmailAsync(IUser assigner, IUser assignee, string appName) + { + return TaskHelper.Done; + } + + public Task SendNewUserEmailAsync(IUser assigner, IUser assignee, string appName) + { + return TaskHelper.Done; + } + } +} diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index ea4130141..df0d018fd 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -156,18 +156,23 @@ namespace Squidex.Config.Domain { services.AddSingleton(Options.Create(emailOptions)); + services.Configure( + config.GetSection("email:invitations")); + services.AddSingletonAs() .As(); - services.AddSingletonAs() - .As(); - services.AddSingletonAs() .AsOptional(); - - services.Configure( - config.GetSection("email:invitations")); } + else + { + services.AddSingletonAs() + .AsOptional(); + } + + services.AddSingletonAs() + .As(); } private static void AddCommandPipeline(this IServiceCollection services) diff --git a/src/Squidex/appsettings.json b/src/Squidex/appsettings.json index 0c54dad3d..afb699604 100644 --- a/src/Squidex/appsettings.json +++ b/src/Squidex/appsettings.json @@ -89,11 +89,12 @@ /* * Always use SSL if possible. */ + "enableSsl": true, /* * The port to your email server. */ - "port": 587 + "port": 465 }, "invitiations": { /* diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InvitationEmailEventConsumerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InvitationEmailEventConsumerTests.cs index c2134ea1a..90d799c39 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InvitationEmailEventConsumerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InvitationEmailEventConsumerTests.cs @@ -31,6 +31,9 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation public InvitationEmailEventConsumerTests() { + A.CallTo(() => emailSender.IsActive) + .Returns(true); + sut = new InvitationEmailEventConsumer(emailSender, userResolver, log); } @@ -48,6 +51,26 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation .MustNotHaveHappened(); } + [Fact] + public async Task Should_not_send_email_if_sender_not_active() + { + var @event = Envelope.Create(CreateEvent(RefTokenType.Subject, true)); + + A.CallTo(() => emailSender.IsActive) + .Returns(false); + + A.CallTo(() => userResolver.FindByIdOrEmailAsync(assignerId)) + .Returns(Task.FromResult(null)); + + await sut.On(@event); + + A.CallTo(() => userResolver.FindByIdOrEmailAsync(A.Ignored)) + .MustNotHaveHappened(); + + A.CallTo(() => emailSender.SendNewUserEmailAsync(A.Ignored, A.Ignored, appName)) + .MustNotHaveHappened(); + } + [Fact] public async Task Should_not_send_email_if_assigner_not_found() {