Skip to content

Commit adb455f

Browse files
committed
Merge remote-tracking branch 'AlejandroCano/EmailSenderRefactor'
# Conflicts: # Signum.Engine.Extensions/Mailing/AsyncEmailSender.cs # Signum.Engine.Extensions/Mailing/EmailSenderConfigurationLogic.cs # Signum.Engine.Extensions/Mailing/Senders/MicrosoftGraphSender.cs # Signum.React.Extensions/Mailing/Templates/EmailSenderConfiguration.tsx
2 parents 723cddb + 3c3942d commit adb455f

19 files changed

+282
-180
lines changed

Signum.Engine.Extensions/Authorization/AzureADLogic.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Microsoft.Graph;
22
using Microsoft.Graph.Auth;
3-
using Signum.Engine.Mailing;
3+
using Signum.Engine.Mailing.Senders;
44
using Signum.Engine.Scheduler;
55
using Signum.Entities.Authorization;
66
using Signum.Utilities.Reflection;

Signum.Engine.Extensions/Mailing/AsyncEmailSender.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public static void StartAsyncEmailSender()
123123
{
124124
using (var tr = Transaction.ForceNew())
125125
{
126-
EmailLogic.SenderManager.Send(email);
126+
EmailLogic.SendMail(email);
127127
tr.Commit();
128128
}
129129
}

Signum.Engine.Extensions/Mailing/EmailLogic.cs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using Microsoft.AspNetCore.StaticFiles;
99
using Signum.Entities.Basics;
1010
using Signum.Entities.Files;
11+
using Signum.Engine.Mailing.Senders;
12+
using Signum.Utilities;
1113

1214
namespace Signum.Engine.Mailing;
1315

@@ -23,7 +25,15 @@ public static EmailConfigurationEmbedded Configuration
2325
get { return getConfiguration(); }
2426
}
2527

26-
public static IEmailSenderManager SenderManager = null!;
28+
static Func<EmailTemplateEntity?, Lite<Entity>?, EmailMessageEntity?, EmailSenderConfigurationEntity> getEmailSenderConfiguration = null!;
29+
30+
public static Polymorphic<Func<EmailSenderServiceConfigurationEntity, EmailSenderConfigurationEntity, BaseEmailSender>> EmailSenders = new ();
31+
public static BaseEmailSender GetEmailSender(EmailMessageEntity email)
32+
{
33+
var template = email.Template?.Try(t => EmailTemplateLogic.EmailTemplatesLazy.Value.GetOrThrow(t));
34+
var config = getEmailSenderConfiguration(template, email.Target, email);
35+
return EmailSenders.Invoke(config.Service, config);
36+
}
2737

2838
internal static void AssertStarted(SchemaBuilder sb)
2939
{
@@ -59,12 +69,17 @@ public static void Start(
5969
e.Sent,
6070
e.Target,
6171
e.Package,
72+
e.SentBy,
6273
e.Exception,
6374
});
6475

6576
PermissionAuthLogic.RegisterPermissions(AsyncEmailSenderPermission.ViewAsyncEmailSenderPanel);
6677

67-
SenderManager = new EmailSenderManager(getEmailSenderConfiguration);
78+
EmailLogic.getEmailSenderConfiguration = getEmailSenderConfiguration;
79+
80+
EmailSenders.Register((SmtpEntity s, EmailSenderConfigurationEntity c) => new SmtpSender(c, s));
81+
EmailSenders.Register((MicrosoftGraphEntity s, EmailSenderConfigurationEntity c) => new MicrosoftGraphSender(c, s));
82+
EmailSenders.Register((ExchangeWebServiceEntity s, EmailSenderConfigurationEntity c) => new ExchangeWebServiceSender(c, s));
6883

6984
EmailGraph.Register();
7085

@@ -133,18 +148,19 @@ public static EmailMessageEntity WithAttachment(this EmailMessageEntity email, F
133148
public static void SendMail(this IEmailModel model)
134149
{
135150
foreach (var email in model.CreateEmailMessage())
136-
SenderManager.Send(email);
151+
GetEmailSender(email).Send(email);
137152
}
138153

139154
public static void SendMail(this Lite<EmailTemplateEntity> template, ModifiableEntity entity)
140155
{
141156
foreach (var email in template.CreateEmailMessage(entity))
142-
SenderManager.Send(email);
157+
GetEmailSender(email).Send(email);
143158
}
144159

145160
public static void SendMail(this EmailMessageEntity email)
146161
{
147-
SenderManager.Send(email);
162+
var template = email.Template?.Try(t => EmailTemplateLogic.EmailTemplatesLazy.Value.GetOrThrow(t));
163+
GetEmailSender(email).Send(email);
148164
}
149165

150166
public static void SendMailAsync(this IEmailModel model)
@@ -278,7 +294,7 @@ public static void Register()
278294
CanBeModified = true,
279295
FromStates = { EmailMessageState.Created, EmailMessageState.Draft, EmailMessageState.ReadyToSend, EmailMessageState.Outdated },
280296
ToStates = { EmailMessageState.Sent },
281-
Execute = (m, _) => EmailLogic.SenderManager.Send(m)
297+
Execute = (m, _) => EmailLogic.GetEmailSender(m).Send(m)
282298
}.Register();
283299

284300

@@ -312,12 +328,6 @@ public static void Register()
312328
}
313329
}
314330

315-
public interface IEmailSenderManager
316-
{
317-
void Send(EmailMessageEntity email);
318-
}
319-
320-
321331
public static class MimeMapping
322332
{
323333
public static string GetMimeType(string fileName)

Signum.Engine.Extensions/Mailing/EmailPackageLogic.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public void Execute(ExecutingProcess executingProcess)
137137
{
138138
using (var tr = Transaction.ForceNew())
139139
{
140-
EmailLogic.SenderManager.Send(m);
140+
EmailLogic.SendMail(m);
141141
tr.Commit();
142142
}
143143
executingProcess.ProgressChanged(counter, emails.Count);

Signum.Engine.Extensions/Mailing/EmailSenderConfigurationLogic.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public static class EmailSenderConfigurationLogic
1414

1515
public static void Start(SchemaBuilder sb, Func<string, string>? encryptPassword = null, Func<string, string>? decryptPassword = null)
1616
{
17+
sb.Settings.AssertImplementedBy((EmailSenderConfigurationEntity o) => o.Service, typeof(SmtpEntity));
18+
sb.Settings.AssertImplementedBy((EmailSenderConfigurationEntity o) => o.Service, typeof(ExchangeWebServiceEntity));
19+
sb.Settings.AssertImplementedBy((EmailSenderConfigurationEntity o) => o.Service, typeof(MicrosoftGraphEntity));
20+
1721
if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
1822
{
1923
if (encryptPassword != null)
@@ -28,13 +32,7 @@ public static void Start(SchemaBuilder sb, Func<string, string>? encryptPassword
2832
Entity = s,
2933
s.Id,
3034
s.Name,
31-
s.SMTP!.DeliveryMethod,
32-
s.SMTP!.Network!.Host,
33-
s.SMTP!.PickupDirectoryLocation,
34-
s.Exchange!.ExchangeVersion,
35-
s.Exchange!.Url,
36-
s.MicrosoftGraph!.UseActiveDirectoryConfiguration,
37-
s.MicrosoftGraph!.Azure_ApplicationID,
35+
s.Service
3836
});
3937

4038
SmtpConfigCache = sb.GlobalLazy(() => Database.Query<EmailSenderConfigurationEntity>().ToDictionary(a => a.ToLite()),
@@ -46,20 +44,27 @@ public static void Start(SchemaBuilder sb, Func<string, string>? encryptPassword
4644
CanBeModified = true,
4745
Execute = (sc, _) => { },
4846
}.Register();
47+
48+
new Graph<EmailSenderConfigurationEntity>.ConstructFrom<EmailSenderConfigurationEntity>(EmailSenderConfigurationOperation.Clone)
49+
{
50+
Construct = (sc, _) => sc.Clone()
51+
52+
}.Register();
53+
4954
}
5055
}
5156

5257
public static SmtpClient GenerateSmtpClient(this Lite<EmailSenderConfigurationEntity> config)
5358
{
54-
return config.RetrieveFromCache().SMTP.ThrowIfNull("No SMTP config").GenerateSmtpClient();
59+
return (config.RetrieveFromCache().Service as SmtpEntity).ThrowIfNull("No SMTP config").GenerateSmtpClient();
5560
}
5661

5762
public static EmailSenderConfigurationEntity RetrieveFromCache(this Lite<EmailSenderConfigurationEntity> config)
5863
{
5964
return SmtpConfigCache.Value.GetOrThrow(config);
6065
}
6166

62-
public static SmtpClient GenerateSmtpClient(this SmtpEmbedded config)
67+
public static SmtpClient GenerateSmtpClient(this SmtpEntity config)
6368
{
6469
if (config.DeliveryMethod != SmtpDeliveryMethod.Network)
6570
{
Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
using Signum.Entities.Mailing;
22

3-
namespace Signum.Engine.Mailing;
4-
5-
public partial class EmailSenderManager : IEmailSenderManager
6-
{
7-
private Func<EmailTemplateEntity?, Lite<Entity>?, EmailMessageEntity?, EmailSenderConfigurationEntity> getEmailSenderConfiguration;
8-
9-
public EmailSenderManager(Func<EmailTemplateEntity?, Lite<Entity>?, EmailMessageEntity?, EmailSenderConfigurationEntity> getEmailSenderConfiguration)
10-
{
11-
this.getEmailSenderConfiguration = getEmailSenderConfiguration;
12-
}
13-
3+
namespace Signum.Engine.Mailing.Senders;
4+
5+
public abstract class BaseEmailSender
6+
{
7+
8+
EmailSenderConfigurationEntity senderConfig;
9+
protected BaseEmailSender(EmailSenderConfigurationEntity senderConfig)
10+
11+
{
12+
this.senderConfig = senderConfig;
13+
}
14+
1415
public virtual void Send(EmailMessageEntity email)
1516
{
1617
using (OperationLogic.AllowSave<EmailMessageEntity>())
@@ -29,6 +30,7 @@ public virtual void Send(EmailMessageEntity email)
2930

3031
email.State = EmailMessageState.Sent;
3132
email.Sent = Clock.Now;
33+
email.SentBy = senderConfig.ToLite();
3234
email.Save();
3335
}
3436
catch (Exception ex)
@@ -55,25 +57,5 @@ public virtual void Send(EmailMessageEntity email)
5557
}
5658
}
5759

58-
protected virtual void SendInternal(EmailMessageEntity email)
59-
{
60-
var template = email.Template?.Try(t => EmailTemplateLogic.EmailTemplatesLazy.Value.GetOrThrow(t));
61-
62-
var config = getEmailSenderConfiguration(template, email.Target, email);
63-
64-
if (config.SMTP != null)
65-
{
66-
SendSMTP(email, config.SMTP);
67-
}
68-
else if (config.Exchange != null)
69-
{
70-
SendExchangeWebService(email, config.Exchange);
71-
}
72-
else if (config.MicrosoftGraph != null)
73-
{
74-
SendMicrosoftGraph(email, config.MicrosoftGraph);
75-
}
76-
else
77-
throw new InvalidOperationException("No way to send email found");
78-
}
60+
protected abstract void SendInternal(EmailMessageEntity email);
7961
}

Signum.Engine.Extensions/Mailing/EmailSenderManager.Exchange.cs renamed to Signum.Engine.Extensions/Mailing/Senders/ExchangeSender.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
using Signum.Engine.Authorization;
33
using Signum.Engine.Files;
44
using Microsoft.Exchange.WebServices.Data;
5+
6+
namespace Signum.Engine.Mailing.Senders;
57

6-
namespace Signum.Engine.Mailing;
7-
8-
public partial class EmailSenderManager : IEmailSenderManager
8+
public class ExchangeWebServiceSender : BaseEmailSender
99
{
10-
protected virtual void SendExchangeWebService(EmailMessageEntity email, ExchangeWebServiceEmbedded exchange)
10+
ExchangeWebServiceEntity exchange;
11+
12+
public ExchangeWebServiceSender(EmailSenderConfigurationEntity senderConfig, ExchangeWebServiceEntity service) : base(senderConfig)
13+
{
14+
exchange = service;
15+
}
16+
17+
protected override void SendInternal(EmailMessageEntity email)
1118
{
1219
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
1320
service.UseDefaultCredentials = exchange.UseDefaultCredentials;

Signum.Engine.Extensions/Mailing/EmailSenderManager.MicrosoftGraph.cs renamed to Signum.Engine.Extensions/Mailing/Senders/MicrosoftGraphSender.cs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,28 @@
88
using System.IO;
99
using System.Net.Http;
1010
using System.Net.Http.Headers;
11+
using Entity = Signum.Entities.Entity;
1112

12-
namespace Signum.Engine.Mailing;
13+
namespace Signum.Engine.Mailing.Senders;
1314

1415
//https://jatindersingh81.medium.com/c-code-to-to-send-emails-using-microsoft-graph-api-2a90da6d648a
1516
//https://www.jeancloud.dev/2020/06/05/using-microsoft-graph-as-smtp-server.html
16-
public partial class EmailSenderManager : IEmailSenderManager
17+
public class MicrosoftGraphSender : BaseEmailSender
1718
{
1819
public static long MicrosoftGraphFileSizeLimit = 3 * 1024 * 1024;
19-
protected virtual void SendMicrosoftGraph(EmailMessageEntity email, MicrosoftGraphEmbedded microsoftGraph)
20+
MicrosoftGraphEntity microsoftGraph;
21+
22+
public MicrosoftGraphSender(EmailSenderConfigurationEntity senderConfig, MicrosoftGraphEntity service) : base(senderConfig)
23+
{
24+
microsoftGraph = service;
25+
}
26+
27+
protected override void SendInternal(EmailMessageEntity email)
2028
{
2129
try
2230
{
2331
var authProvider = microsoftGraph.GetAuthProvider();
24-
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
32+
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
2533

2634

2735
var bigAttachments = email.Attachments.Where(a => a.File.FileLength > MicrosoftGraphFileSizeLimit).ToList();
@@ -59,13 +67,13 @@ protected virtual void SendMicrosoftGraph(EmailMessageEntity email, MicrosoftGra
5967

6068
if (!fileUploadTask.UploadSucceeded)
6169
throw new InvalidOperationException("Upload of big files to Microsoft Graph didn't succeed");
62-
}
70+
}
6371

6472
user.MailFolders["Drafts"].Messages[newMessage.Id].Send().Request().PostAsync().Wait();
6573
}
6674
}
6775
catch(AggregateException e)
68-
{
76+
{
6977
var only = e.InnerExceptions.Only();
7078
if(only != null)
7179
{
@@ -111,13 +119,13 @@ private IMessageAttachmentsCollectionPage GetAttachments(MList<EmailAttachmentEm
111119
foreach (var a in attachments)
112120
{
113121
if(a.File.FileLength <= MicrosoftGraphFileSizeLimit)
114-
result.Add(new FileAttachment
115-
{
116-
ContentId = a.ContentId,
117-
Name = a.File.FileName,
118-
ContentType = MimeMapping.GetMimeType(a.File.FileName),
119-
ContentBytes = a.File.GetByteArray(),
120-
});
122+
result.Add(new FileAttachment
123+
{
124+
ContentId = a.ContentId,
125+
Name = a.File.FileName,
126+
ContentType = MimeMapping.GetMimeType(a.File.FileName),
127+
ContentBytes = a.File.GetByteArray(),
128+
});
121129
}
122130
return result;
123131
}
@@ -162,7 +170,7 @@ public static IDisposable OverrideAuthenticationProvider(IAuthenticationProvider
162170
return new Disposable(() => AuthenticationProvider.Value = old);
163171
}
164172

165-
public static IAuthenticationProvider GetAuthProvider(this MicrosoftGraphEmbedded microsoftGraph, string[]? scopes = null)
173+
public static IAuthenticationProvider GetAuthProvider(this MicrosoftGraphEntity microsoftGraph, string[]? scopes = null)
166174
{
167175
if (AuthenticationProvider.Value is var ap && ap != null)
168176
return ap;

Signum.Engine.Extensions/Mailing/EmailSenderManager.SMTP.cs renamed to Signum.Engine.Extensions/Mailing/Senders/SmtpSender.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,28 @@
22
using Signum.Entities.Mailing;
33
using Signum.Engine.Authorization;
44
using Signum.Engine.Files;
5+
6+
namespace Signum.Engine.Mailing.Senders;
57

6-
namespace Signum.Engine.Mailing;
8+
public class SmtpSender: BaseEmailSender
9+
{
10+
11+
SmtpEntity smtp;
12+
13+
public SmtpSender(EmailSenderConfigurationEntity senderConfig, SmtpEntity service) : base(senderConfig)
14+
{
15+
smtp = service;
16+
}
17+
18+
protected override void SendInternal(EmailMessageEntity email)
19+
{
20+
System.Net.Mail.MailMessage message = CreateMailMessage(email);
21+
22+
using (HeavyProfiler.Log("SMTP-Send"))
23+
smtp.GenerateSmtpClient().Send(message);
24+
}
725

8-
public partial class EmailSenderManager : IEmailSenderManager
9-
{
10-
protected virtual void SendSMTP(EmailMessageEntity email, SmtpEmbedded smtp)
11-
{
12-
System.Net.Mail.MailMessage message = CreateMailMessage(email);
13-
14-
using (HeavyProfiler.Log("SMTP-Send"))
15-
smtp.GenerateSmtpClient().Send(message);
16-
}
17-
18-
protected virtual MailMessage CreateMailMessage(EmailMessageEntity email)
26+
MailMessage CreateMailMessage(EmailMessageEntity email)
1927
{
2028
System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage()
2129
{
@@ -47,7 +55,8 @@ protected virtual MailMessage CreateMailMessage(EmailMessageEntity email)
4755
message.Bcc.AddRange(email.Recipients.Where(r => r.Kind == EmailRecipientKind.Bcc).Select(r => r.ToMailAddress()).ToList());
4856

4957
return message;
50-
}
58+
}
59+
5160
}
5261

5362
public static class SmtpExtensions

Signum.Entities.Extensions/Mailing/EmailMessage.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public EmailMessageEntity()
3131

3232
public DateTime? Sent { get; set; }
3333

34+
public Lite<EmailSenderConfigurationEntity>? SentBy { get; set; }
35+
3436
public DateTime? ReceptionNotified { get; set; }
3537

3638
[DbType(Size = int.MaxValue)]

0 commit comments

Comments
 (0)