Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 4c90b75

Browse files
author
Scott Bommarito
authored
Integrate NuGet.SupportRequests.Notifications with NuGet.Services.Messaging.Email (#606)
1 parent 66ad4bc commit 4c90b75

10 files changed

Lines changed: 96 additions & 91 deletions

src/NuGet.SupportRequests.Notifications/Configuration/InitializationConfiguration.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,24 @@ namespace NuGet.SupportRequests.Notifications
66
public class InitializationConfiguration
77
{
88
/// <summary>
9-
/// Obsolete: replace with IcM configuration
9+
/// Connection string to email publisher job's service bus.
1010
/// </summary>
11-
public string PagerDutyAccountName { get; set; }
11+
public string EmailPublisherConnectionString { get; set; }
1212

1313
/// <summary>
14-
/// Obsolete: replace with IcM configuration
14+
/// Name of the email publisher job's service bus topic.
1515
/// </summary>
16-
public string PagerDutyApiKey { get; set; }
16+
public string EmailPublisherTopicName { get; set; }
1717

1818
/// <summary>
19-
/// SMTP configuration.
19+
/// Obsolete: replace with incident API configuration
2020
/// </summary>
21-
public string SmtpUri { get; set; }
21+
public string PagerDutyAccountName { get; set; }
22+
23+
/// <summary>
24+
/// Obsolete: replace with incident API configuration
25+
/// </summary>
26+
public string PagerDutyApiKey { get; set; }
2227

2328
/// <summary>
2429
/// Email address to which the weekly report is sent.

src/NuGet.SupportRequests.Notifications/NuGet.SupportRequests.Notifications.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
<Compile Include="PagerDutyClient.cs" />
6565
<Compile Include="ScheduledTaskFactory.cs" />
6666
<Compile Include="SqlQuery.cs" />
67+
<Compile Include="SupportRequestNotificationEmailBuilder.cs" />
6768
<Compile Include="Templates\NotificationTemplateProvider.cs" />
6869
<Compile Include="Templates\HtmlSnippets.cs" />
6970
<Compile Include="Templates\HtmlPlaceholders.cs" />
@@ -106,12 +107,12 @@
106107
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
107108
<PrivateAssets>all</PrivateAssets>
108109
</PackageReference>
109-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions">
110-
<Version>1.0.0</Version>
111-
</PackageReference>
112110
<PackageReference Include="Newtonsoft.Json">
113111
<Version>9.0.1</Version>
114112
</PackageReference>
113+
<PackageReference Include="NuGet.Services.Messaging.Email">
114+
<Version>2.32.0</Version>
115+
</PackageReference>
115116
</ItemGroup>
116117
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
117118
<PropertyGroup>

src/NuGet.SupportRequests.Notifications/Services/MessagingService.cs

Lines changed: 12 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,26 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Net;
6-
using System.Net.Mail;
5+
using System.Threading.Tasks;
76
using Microsoft.Extensions.Logging;
8-
using NuGet.Jobs;
7+
using NuGet.Services.Messaging.Email;
98

109
namespace NuGet.SupportRequests.Notifications.Services
1110
{
1211
internal class MessagingService
1312
{
14-
private readonly MailAddress _fromAddress;
1513
private readonly ILogger<MessagingService> _logger;
16-
private readonly string _smtpUri;
17-
private SmtpClient _smtpClient;
14+
private readonly IMessageService _messageService;
1815

19-
private const string _noreplyAddress = "NuGet Gallery <[email protected]>";
20-
21-
public MessagingService(ILoggerFactory loggerFactory, string smtpUri)
16+
public MessagingService(IMessageService messageService, ILogger<MessagingService> logger)
2217
{
23-
if (loggerFactory == null)
24-
{
25-
throw new ArgumentNullException(nameof(loggerFactory));
26-
}
27-
28-
if (smtpUri == null)
29-
{
30-
throw new ArgumentNullException(nameof(smtpUri));
31-
}
32-
33-
_logger = loggerFactory.CreateLogger<MessagingService>();
34-
_fromAddress = new MailAddress(_noreplyAddress);
35-
_smtpUri = smtpUri;
18+
_messageService = messageService ?? throw new ArgumentNullException(nameof(messageService));
19+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
3620
}
3721

38-
internal void SendNotification(
22+
internal async Task SendNotification(
3923
string subject,
40-
string body,
24+
string htmlBody,
4125
DateTime referenceTime,
4226
string targetEmailAddress)
4327
{
@@ -46,67 +30,23 @@ internal void SendNotification(
4630
throw new ArgumentException(nameof(subject));
4731
}
4832

49-
if (string.IsNullOrEmpty(body))
33+
if (string.IsNullOrEmpty(htmlBody))
5034
{
51-
throw new ArgumentException(nameof(body));
35+
throw new ArgumentException(nameof(htmlBody));
5236
}
5337

5438
if (string.IsNullOrEmpty(targetEmailAddress))
5539
{
5640
throw new ArgumentException(nameof(targetEmailAddress));
5741
}
5842

59-
var targetAddress = new MailAddress(targetEmailAddress);
60-
using (var mailMessage = new MailMessage())
61-
{
62-
mailMessage.Subject = subject;
63-
mailMessage.From = _fromAddress;
64-
mailMessage.ReplyToList.Add(_fromAddress);
65-
mailMessage.Body = body;
66-
mailMessage.To.Add(targetAddress);
67-
68-
SendMessage(mailMessage);
69-
}
43+
var builder = new SupportRequestNotificationEmailBuilder(subject, htmlBody, targetEmailAddress);
44+
await _messageService.SendMessageAsync(builder);
7045

7146
_logger.LogInformation(
7247
"Successfully sent notification '{NotificationType}' for reference time '{ReferenceTimeUtc}'",
7348
subject,
7449
referenceTime.ToShortDateString());
7550
}
76-
77-
private void SendMessage(MailMessage mailMessage)
78-
{
79-
var smtpClient = GetOrCreateSmtpClient();
80-
81-
var alternateHtmlView = AlternateView.CreateAlternateViewFromString(mailMessage.Body, null, "text/html");
82-
mailMessage.AlternateViews.Add(alternateHtmlView);
83-
84-
smtpClient.Send(mailMessage);
85-
}
86-
87-
private SmtpClient GetOrCreateSmtpClient()
88-
{
89-
if (_smtpClient != null)
90-
{
91-
return _smtpClient;
92-
}
93-
94-
var smtpUri = new SmtpUri(new Uri(_smtpUri));
95-
_smtpClient = new SmtpClient();
96-
_smtpClient.Host = smtpUri.Host;
97-
_smtpClient.Port = smtpUri.Port;
98-
_smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
99-
_smtpClient.EnableSsl = smtpUri.Secure;
100-
101-
if (!string.IsNullOrEmpty(smtpUri.UserName))
102-
{
103-
_smtpClient.UseDefaultCredentials = false;
104-
_smtpClient.Credentials = new NetworkCredential(
105-
smtpUri.UserName,
106-
smtpUri.Password);
107-
}
108-
109-
return _smtpClient;
110-
}
11151
}
11252
}

src/NuGet.SupportRequests.Notifications/Settings/dev.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"Initialization": {
33
"PagerDutyAccountName": "nuget",
44
"PagerDutyApiKey": "$$Dev-PagerDuty-ApiKey$$",
5-
"SmtpUri": "#{Jobs.supportrequests.notifications.SmtpUri}",
5+
"EmailPublisherConnectionString": "Endpoint=sb://nugetdev.servicebus.windows.net/;SharedAccessKeyName=enqueuer;SharedAccessKey=$$Dev-ServiceBus-SharedAccessKey-EmailPublisher-Enqueuer$$",
6+
"EmailPublisherTopicName": "email-publisher",
67
"TargetEmailAddress": "#{Jobs.supportrequests.notifications.weeklysummarynotification.TargetEmailAddress}"
78
},
89

src/NuGet.SupportRequests.Notifications/Settings/int.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"Initialization": {
33
"PagerDutyAccountName": "nuget",
44
"PagerDutyApiKey": "$$Int-PagerDuty-ApiKey$$",
5-
"SmtpUri": "#{Jobs.supportrequests.notifications.SmtpUri}",
5+
"EmailPublisherConnectionString": "Endpoint=sb://nugetint.servicebus.windows.net/;SharedAccessKeyName=enqueuer;SharedAccessKey=$$Int-ServiceBus-SharedAccessKey-EmailPublisher-Enqueuer$$",
6+
"EmailPublisherTopicName": "email-publisher",
67
"TargetEmailAddress": "#{Jobs.supportrequests.notifications.weeklysummarynotification.TargetEmailAddress}"
78
},
89

src/NuGet.SupportRequests.Notifications/Settings/prod.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"Initialization": {
33
"PagerDutyAccountName": "nuget",
44
"PagerDutyApiKey": "$$Prod-PagerDuty-ApiKey$$",
5-
"SmtpUri": "#{Jobs.supportrequests.notifications.SmtpUri}",
5+
"EmailPublisherConnectionString": "Endpoint=sb://nugetprod.servicebus.windows.net/;SharedAccessKeyName=enqueuer;SharedAccessKey=$$Prod-ServiceBus-SharedAccessKey-EmailPublisher-Enqueuer$$",
6+
"EmailPublisherTopicName": "email-publisher",
67
"TargetEmailAddress": "#{Jobs.supportrequests.notifications.weeklysummarynotification.TargetEmailAddress}"
78
},
89

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Net.Mail;
6+
using NuGet.Services.Messaging.Email;
7+
8+
namespace NuGet.SupportRequests.Notifications
9+
{
10+
public class SupportRequestNotificationEmailBuilder : IEmailBuilder
11+
{
12+
public SupportRequestNotificationEmailBuilder(
13+
string subject,
14+
string htmlBody,
15+
string targetEmailAddress)
16+
{
17+
_subject = subject
18+
?? throw new ArgumentNullException(nameof(subject));
19+
_htmlBody = htmlBody
20+
?? throw new ArgumentNullException(nameof(htmlBody));
21+
_targetAddress = new MailAddress(
22+
targetEmailAddress ?? throw new ArgumentNullException(nameof(targetEmailAddress)));
23+
}
24+
25+
public static MailAddress NoReplyAddress = new MailAddress("NuGet Gallery <[email protected]>");
26+
public MailAddress Sender => NoReplyAddress;
27+
28+
private MailAddress _targetAddress;
29+
public IEmailRecipients GetRecipients()
30+
{
31+
return new EmailRecipients(to: new[] { _targetAddress });
32+
}
33+
34+
private readonly string _subject;
35+
public string GetSubject()
36+
{
37+
return _subject;
38+
}
39+
40+
private readonly string _htmlBody;
41+
public string GetBody(EmailFormat format)
42+
{
43+
// We only create an HTML version of the body for now.
44+
// Ideally we would create a plaintext fallback as well, and return a different version of the body based on the format.
45+
// For now, however, returning an HTML body as the plaintext fallback is better than having a completely empty plaintext fallback.
46+
return _htmlBody;
47+
}
48+
}
49+
}

src/NuGet.SupportRequests.Notifications/Tasks/OnCallDailyNotificationTask.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protected override async Task<OnCallDailyNotification> BuildNotification(
5252
return new OnCallDailyNotification(referenceTime, unresolvedIssues, targetEmailAddress);
5353
}
5454

55-
protected override string BuildNotificationBody(string template, OnCallDailyNotification notification)
55+
protected override string BuildNotificationHtmlBody(string template, OnCallDailyNotification notification)
5656
{
5757
var result = template;
5858
var referenceTimeLabel = notification.ReferenceTime.ToString("dd/MM/yy");

src/NuGet.SupportRequests.Notifications/Tasks/SupportRequestsNotificationScheduledTask.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using System.Data.SqlClient;
66
using System.Threading.Tasks;
77
using Microsoft.Extensions.Logging;
8+
using NuGet.Services.Messaging;
9+
using NuGet.Services.Messaging.Email;
10+
using NuGet.Services.ServiceBus;
811
using NuGet.SupportRequests.Notifications.Notifications;
912
using NuGet.SupportRequests.Notifications.Services;
1013
using NuGet.SupportRequests.Notifications.Templates;
@@ -33,25 +36,29 @@ protected SupportRequestsNotificationScheduledTask(
3336
throw new ArgumentNullException(nameof(loggerFactory));
3437
}
3538

36-
_messagingService = new MessagingService(loggerFactory, configuration.SmtpUri);
39+
var serializer = new ServiceBusMessageSerializer();
40+
var topicClient = new TopicClientWrapper(configuration.EmailPublisherConnectionString, configuration.EmailPublisherTopicName);
41+
var enqueuer = new EmailMessageEnqueuer(topicClient, serializer, loggerFactory.CreateLogger<EmailMessageEnqueuer>());
42+
var messageService = new AsynchronousEmailMessageService(enqueuer);
43+
_messagingService = new MessagingService(messageService, loggerFactory.CreateLogger<MessagingService>());
3744

3845
_supportRequestRepository = new SupportRequestRepository(loggerFactory, openSupportRequestSqlConnectionAsync);
3946
}
4047

4148
protected abstract Task<TNotification> BuildNotification(SupportRequestRepository supportRequestRepository, DateTime referenceTime);
4249

43-
protected abstract string BuildNotificationBody(string template, TNotification notification);
50+
protected abstract string BuildNotificationHtmlBody(string template, TNotification notification);
4451

4552
public async Task RunAsync()
4653
{
4754
var referenceTime = DateTime.UtcNow.Date;
4855
var notification = await BuildNotification(_supportRequestRepository, referenceTime);
4956
var template = NotificationTemplateProvider.Get(notification.TemplateName);
50-
var body = BuildNotificationBody(template, notification);
57+
var htmlBody = BuildNotificationHtmlBody(template, notification);
5158

52-
_messagingService.SendNotification(
59+
await _messagingService.SendNotification(
5360
notification.Subject,
54-
body,
61+
htmlBody,
5562
referenceTime,
5663
notification.TargetEmailAddress);
5764
}

src/NuGet.SupportRequests.Notifications/Tasks/WeeklySummaryNotificationTask.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ protected override async Task<WeeklySummaryNotification> BuildNotification(
7373
topSupportRequestReasonsLastWeek);
7474
}
7575

76-
protected override string BuildNotificationBody(string template, WeeklySummaryNotification notification)
76+
protected override string BuildNotificationHtmlBody(string template, WeeklySummaryNotification notification)
7777
{
7878

7979
var newIssuesTrendPct = notification.GetNewIssuesTrendPct();

0 commit comments

Comments
 (0)