22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
44using System ;
5+ using System . Collections . ObjectModel ;
56using System . Collections . Generic ;
67using System . Globalization ;
78using System . Linq ;
89using System . Net . Mail ;
910using System . Text ;
11+ using System . Threading . Tasks ;
1012using AnglicanGeek . MarkdownMailer ;
1113using NuGet . Services . Validation ;
1214using NuGet . Services . Validation . Issues ;
@@ -15,9 +17,11 @@ namespace NuGetGallery.Services
1517{
1618 public class CoreMessageService : ICoreMessageService
1719 {
18- protected CoreMessageService ( )
19- {
20- }
20+ private static readonly ReadOnlyCollection < TimeSpan > RetryDelays = Array . AsReadOnly ( new [ ] {
21+ TimeSpan . FromSeconds ( 0.1 ) ,
22+ TimeSpan . FromSeconds ( 1 ) ,
23+ TimeSpan . FromSeconds ( 10 )
24+ } ) ;
2125
2226 public CoreMessageService ( IMailSender mailSender , ICoreMessageServiceConfiguration coreConfiguration )
2327 {
@@ -28,7 +32,7 @@ public CoreMessageService(IMailSender mailSender, ICoreMessageServiceConfigurati
2832 public IMailSender MailSender { get ; protected set ; }
2933 public ICoreMessageServiceConfiguration CoreConfiguration { get ; protected set ; }
3034
31- public void SendPackageAddedNotice ( Package package , string packageUrl , string packageSupportUrl , string emailSettingsUrl , IEnumerable < string > warningMessages = null )
35+ public async Task SendPackageAddedNoticeAsync ( Package package , string packageUrl , string packageSupportUrl , string emailSettingsUrl , IEnumerable < string > warningMessages = null )
3236 {
3337 bool hasWarnings = warningMessages != null && warningMessages . Any ( ) ;
3438
@@ -63,12 +67,12 @@ [change your email notification settings]({emailSettingsUrl}).
6367
6468 if ( mailMessage . To . Any ( ) )
6569 {
66- SendMessage ( mailMessage ) ;
70+ await SendMessageAsync ( mailMessage ) ;
6771 }
6872 }
6973 }
7074
71- public void SendPackageAddedWithWarningsNotice ( Package package , string packageUrl , string packageSupportUrl , IEnumerable < string > warningMessages )
75+ public async Task SendPackageAddedWithWarningsNoticeAsync ( Package package , string packageUrl , string packageSupportUrl , IEnumerable < string > warningMessages )
7276 {
7377 var subject = $ "[{ CoreConfiguration . GalleryOwner . DisplayName } ] Package pushed with warnings - { package . PackageRegistration . Id } { package . Version } ";
7478 var warningMessagesPlaceholder = Environment . NewLine + string . Join ( Environment . NewLine , warningMessages ) ;
@@ -87,12 +91,12 @@ public void SendPackageAddedWithWarningsNotice(Package package, string packageUr
8791
8892 if ( mailMessage . To . Any ( ) )
8993 {
90- SendMessage ( mailMessage ) ;
94+ await SendMessageAsync ( mailMessage ) ;
9195 }
9296 }
9397 }
9498
95- public void SendPackageValidationFailedNotice ( Package package , PackageValidationSet validationSet , string packageUrl , string packageSupportUrl , string announcementsUrl , string twitterUrl )
99+ public async Task SendPackageValidationFailedNoticeAsync ( Package package , PackageValidationSet validationSet , string packageUrl , string packageSupportUrl , string announcementsUrl , string twitterUrl )
96100 {
97101 var validationIssues = validationSet . GetValidationIssues ( ) ;
98102
@@ -133,7 +137,7 @@ public void SendPackageValidationFailedNotice(Package package, PackageValidation
133137
134138 if ( mailMessage . To . Any ( ) )
135139 {
136- SendMessage ( mailMessage , copySender : false ) ;
140+ await SendMessageAsync ( mailMessage ) ;
137141 }
138142 }
139143 }
@@ -169,7 +173,7 @@ private static string ParseValidationIssue(ValidationIssue validationIssue, stri
169173 }
170174 }
171175
172- public void SendValidationTakingTooLongNotice ( Package package , string packageUrl )
176+ public async Task SendValidationTakingTooLongNoticeAsync ( Package package , string packageUrl )
173177 {
174178 string subject = "[{0}] Package validation taking longer than expected - {1} {2}" ;
175179 string body = "It is taking longer than expected for your package [{1} {2}]({3}) to get published.\n \n " +
@@ -201,7 +205,7 @@ public void SendValidationTakingTooLongNotice(Package package, string packageUrl
201205
202206 if ( mailMessage . To . Any ( ) )
203207 {
204- SendMessage ( mailMessage , copySender : false ) ;
208+ await SendMessageAsync ( mailMessage ) ;
205209 }
206210 }
207211 }
@@ -231,30 +235,54 @@ protected static void AddOwnersSubscribedToPackagePushedNotification(PackageRegi
231235 }
232236 }
233237
234- protected void SendMessage ( MailMessage mailMessage )
238+ protected virtual async Task SendMessageAsync ( MailMessage mailMessage )
235239 {
236- SendMessage ( mailMessage , copySender : false ) ;
240+ int attempt = 0 ;
241+ bool success = false ;
242+ while ( ! success )
243+ {
244+ try
245+ {
246+ await AttemptSendMessageAsync ( mailMessage , attempt + 1 ) ;
247+ success = true ;
248+ }
249+ catch ( SmtpException )
250+ {
251+ if ( attempt < RetryDelays . Count )
252+ {
253+ await Task . Delay ( RetryDelays [ attempt ] ) ;
254+ attempt ++ ;
255+ }
256+ else
257+ {
258+ throw ;
259+ }
260+ }
261+ }
237262 }
238263
239- virtual protected void SendMessage ( MailMessage mailMessage , bool copySender )
264+ protected virtual Task AttemptSendMessageAsync ( MailMessage mailMessage , int attemptNumber )
240265 {
266+ // AnglicanGeek.MarkdownMailer doesn't have an async overload
241267 MailSender . Send ( mailMessage ) ;
242- if ( copySender )
268+ return Task . CompletedTask ;
269+ }
270+
271+ protected async Task SendMessageToSenderAsync ( MailMessage mailMessage )
272+ {
273+ using ( var senderCopy = new MailMessage (
274+ CoreConfiguration . GalleryOwner ,
275+ mailMessage . ReplyToList . First ( ) ) )
243276 {
244- var senderCopy = new MailMessage (
245- CoreConfiguration . GalleryOwner ,
246- mailMessage . ReplyToList . First ( ) )
247- {
248- Subject = mailMessage . Subject + " [Sender Copy]" ,
249- Body = string . Format (
250- CultureInfo . CurrentCulture ,
251- "You sent the following message via {0}: {1}{1}{2}" ,
252- CoreConfiguration . GalleryOwner . DisplayName ,
253- Environment . NewLine ,
254- mailMessage . Body ) ,
255- } ;
277+ senderCopy . Subject = mailMessage . Subject + " [Sender Copy]" ;
278+ senderCopy . Body = string . Format (
279+ CultureInfo . CurrentCulture ,
280+ "You sent the following message via {0}: {1}{1}{2}" ,
281+ CoreConfiguration . GalleryOwner . DisplayName ,
282+ Environment . NewLine ,
283+ mailMessage . Body ) ;
256284 senderCopy . ReplyToList . Add ( mailMessage . ReplyToList . First ( ) ) ;
257- MailSender . Send ( senderCopy ) ;
285+ await SendMessageAsync ( senderCopy ) ;
258286 }
259287 }
260288 }
0 commit comments