11using System ;
22using System . Collections . Generic ;
3- using System . IO ;
43using System . Linq ;
54using System . Threading ;
65using System . Threading . Tasks ;
76using Azure ;
87using Azure . Communication . Email ;
9- using Azure . Communication . Email . Models ;
108using Azure . Core ;
119using FluentEmail . Core ;
1210using FluentEmail . Core . Interfaces ;
@@ -20,6 +18,13 @@ public class AzureEmailSender : ISender
2018{
2119 private EmailClient _emailClient ;
2220
21+ /// <summary>
22+ /// The priority header to use when specifying the importance of an email.
23+ /// Values: 1-High, 3-Normal (default), 5-Low
24+ /// https://sendgrid.com/blog/magic-email-headers/
25+ /// </summary>
26+ const string PriorityHeader = "X-Priority" ;
27+
2328 /// <summary>
2429 /// Initializes a new instance of <see cref="AzureEmailSender"/>
2530 /// </summary>
@@ -96,8 +101,10 @@ public async Task<SendResponse> SendAsync(IFluentEmail email, CancellationToken?
96101
97102 var emailRecipients = new EmailRecipients ( toRecipients , ccRecipients , bccRecipients ) ;
98103
99- var sender = $ "{ email . Data . FromAddress . Name } <{ email . Data . FromAddress . EmailAddress } >";
100- var emailMessage = new EmailMessage ( sender , emailContent , emailRecipients ) ;
104+ // Azure Email Sender doesn't allow us to specify the 'from' display name (instead the sender name is defined in the blade configuration)
105+ // var sender = $"{email.Data.FromAddress.Name} <{email.Data.FromAddress.EmailAddress}>";
106+ var sender = email . Data . FromAddress . EmailAddress ;
107+ var emailMessage = new EmailMessage ( sender , emailRecipients , emailContent ) ;
101108
102109 if ( email . Data . ReplyToAddresses . Any ( a => ! string . IsNullOrWhiteSpace ( a . EmailAddress ) ) )
103110 {
@@ -111,7 +118,7 @@ public async Task<SendResponse> SendAsync(IFluentEmail email, CancellationToken?
111118 {
112119 foreach ( var header in email . Data . Headers )
113120 {
114- emailMessage . CustomHeaders . Add ( new EmailCustomHeader ( header . Key , header . Value ) ) ;
121+ emailMessage . Headers . Add ( header . Key , header . Value ) ;
115122 }
116123 }
117124
@@ -123,19 +130,19 @@ public async Task<SendResponse> SendAsync(IFluentEmail email, CancellationToken?
123130 }
124131 }
125132
126- emailMessage . Importance = email . Data . Priority switch
133+ emailMessage . Headers . Add ( PriorityHeader , ( email . Data . Priority switch
127134 {
128- Priority . High => EmailImportance . High ,
129- Priority . Normal => EmailImportance . Normal ,
130- Priority . Low => EmailImportance . Low ,
131- _ => EmailImportance . Normal
132- } ;
135+ Priority . High => 1 ,
136+ Priority . Normal => 3 ,
137+ Priority . Low => 5 ,
138+ _ => 3
139+ } ) . ToString ( ) ) ;
140+
133141
134142 try
135143 {
136- var sendEmailResult = ( await _emailClient . SendAsync ( emailMessage , token ?? CancellationToken . None ) ) . Value ;
137-
138- var messageId = sendEmailResult . MessageId ;
144+ EmailSendOperation sendOperation = await _emailClient . SendAsync ( WaitUntil . Started , emailMessage , token ?? CancellationToken . None ) ;
145+ var messageId = sendOperation . Id ;
139146 if ( string . IsNullOrWhiteSpace ( messageId ) )
140147 {
141148 return new SendResponse
@@ -147,32 +154,21 @@ public async Task<SendResponse> SendAsync(IFluentEmail email, CancellationToken?
147154 // We want to verify that the email was sent.
148155 // The maximum time we will wait for the message status to be sent/delivered is 2 minutes.
149156 var cancellationToken = new CancellationTokenSource ( TimeSpan . FromMinutes ( 2 ) ) ;
150- SendStatusResult sendStatusResult ;
151- do
152- {
153- sendStatusResult = await _emailClient . GetSendStatusAsync ( messageId , cancellationToken . Token ) ;
154-
155- if ( sendStatusResult . Status != SendStatus . Queued )
156- {
157- break ;
158- }
159-
160- await Task . Delay ( TimeSpan . FromSeconds ( 10 ) , cancellationToken . Token ) ;
161- } while ( ! cancellationToken . IsCancellationRequested ) ;
157+ var sendStatusResult = sendOperation . WaitForCompletion ( cancellationToken . Token ) . Value ;
162158
163- if ( cancellationToken . IsCancellationRequested )
159+ if ( sendStatusResult . Status == EmailSendStatus . Succeeded )
164160 {
165161 return new SendResponse
166162 {
167- ErrorMessages = new List < string > { "Failed to send email, timed out while getting status." }
163+ MessageId = messageId
168164 } ;
169165 }
170166
171- if ( sendStatusResult . Status == SendStatus . OutForDelivery )
167+ if ( cancellationToken . IsCancellationRequested )
172168 {
173169 return new SendResponse
174170 {
175- MessageId = messageId
171+ ErrorMessages = new List < string > { "Failed to send email, timed out while getting status." }
176172 } ;
177173 }
178174
@@ -189,17 +185,7 @@ public async Task<SendResponse> SendAsync(IFluentEmail email, CancellationToken?
189185 } ;
190186 }
191187 }
192-
193- private async Task < EmailAttachment > ConvertAttachment ( Attachment attachment ) =>
194- new ( attachment . Filename , attachment . ContentType ,
195- await GetAttachmentAsBase64String ( attachment . Data ) ) ;
196188
197- private async Task < string > GetAttachmentAsBase64String ( Stream stream )
198- {
199- using var ms = new MemoryStream ( ) ;
200-
201- await stream . CopyToAsync ( ms ) ;
202-
203- return Convert . ToBase64String ( ms . ToArray ( ) ) ;
204- }
205- }
189+ private async Task < EmailAttachment > ConvertAttachment ( Attachment attachment ) =>
190+ new ( attachment . Filename , attachment . ContentType , await BinaryData . FromStreamAsync ( attachment . Data ) ) ;
191+ }
0 commit comments