11//
2- // Copyright (c) 2004-2021 Jaroslaw Kowalski <[email protected] >, Kim Christensen, Julian Verdurmen 2+ // Copyright (c) 2004-2022 Jaroslaw Kowalski <[email protected] >, Kim Christensen, Julian Verdurmen 33//
44// All rights reserved.
55//
3434using System ;
3535using System . Collections . Generic ;
3636using System . ComponentModel ;
37+ using System . Diagnostics . CodeAnalysis ;
3738using System . Text ;
3839using MailKit . Net . Smtp ;
3940using MailKit . Security ;
@@ -80,8 +81,12 @@ namespace NLog.MailKit
8081 /// <code lang="C#" source="examples/targets/Configuration API/Mail/Buffered/Example.cs" />
8182 /// </example>
8283 [ Target ( "Mail" ) ]
84+ [ SuppressMessage ( "ReSharper" , "RedundantStringFormatCall" ) ]
8385 public class MailTarget : TargetWithLayoutHeaderAndFooter
8486 {
87+ private static readonly Encoding DefaultEncoding = System . Text . Encoding . UTF8 ;
88+ private const SecureSocketOptions DefaultSecureSocketOption = SecureSocketOptions . StartTlsWhenAvailable ;
89+
8590 private const string RequiredPropertyIsEmptyFormat = "After the processing of the MailTarget's '{0}' property it appears to be empty. The email message will not be sent." ;
8691
8792 /// <summary>
@@ -94,10 +99,10 @@ public MailTarget()
9499 {
95100 Body = "${message}${newline}" ;
96101 Subject = "Message from NLog on ${machinename}" ;
97- Encoding = Encoding . UTF8 ;
102+ Encoding = DefaultEncoding ;
98103 SmtpPort = 25 ;
99104 SmtpAuthentication = SmtpAuthenticationMode . None ;
100- SecureSocketOption = SecureSocketOptions . StartTlsWhenAvailable ;
105+ SecureSocketOption = DefaultSecureSocketOption ;
101106 Timeout = 10000 ;
102107 }
103108
@@ -143,7 +148,8 @@ public MailTarget(string name) : this()
143148 /// </summary>
144149 /// <value>A value of <c>true</c> if new lines should be added; otherwise, <c>false</c>.</value>
145150 /// <docgen category='Layout Options' order='99' />
146- public bool AddNewLines { get ; set ; }
151+ [ DefaultValue ( false ) ]
152+ public Layout < bool > AddNewLines { get ; set ; }
147153
148154 /// <summary>
149155 /// Gets or sets the mail subject.
@@ -170,14 +176,14 @@ public Layout Body
170176 /// </summary>
171177 /// <docgen category='Layout Options' order='20' />
172178 [ DefaultValue ( "UTF8" ) ]
173- public Encoding Encoding { get ; set ; }
179+ public Layout < Encoding > Encoding { get ; set ; }
174180
175181 /// <summary>
176182 /// Gets or sets a value indicating whether to send message as HTML instead of plain text.
177183 /// </summary>
178184 /// <docgen category='Layout Options' order='11' />
179185 [ DefaultValue ( false ) ]
180- public bool Html { get ; set ; }
186+ public Layout < bool > Html { get ; set ; }
181187
182188 /// <summary>
183189 /// Gets or sets SMTP Server to be used for sending.
@@ -190,16 +196,16 @@ public Layout Body
190196 /// </summary>
191197 /// <docgen category='SMTP Options' order='11' />
192198 [ DefaultValue ( "None" ) ]
193- public SmtpAuthenticationMode SmtpAuthentication { get ; set ; }
199+ public Layout < SmtpAuthenticationMode > SmtpAuthentication { get ; set ; }
194200
195201 /// <summary>
196- /// Gets or sets the username used to connect to SMTP server (used when SmtpAuthentication is set to "basic").
202+ /// Gets or sets the username used to connect to SMTP server (used when <see cref=" SmtpAuthentication"/> is set to "basic").
197203 /// </summary>
198204 /// <docgen category='SMTP Options' order='12' />
199205 public Layout SmtpUserName { get ; set ; }
200206
201207 /// <summary>
202- /// Gets or sets the password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic").
208+ /// Gets or sets the password used to authenticate against SMTP server (used when <see cref=" SmtpAuthentication"/> is set to "basic").
203209 /// </summary>
204210 /// <docgen category='SMTP Options' order='13' />
205211 public Layout SmtpPassword { get ; set ; }
@@ -212,31 +218,31 @@ public Layout Body
212218 /// <docgen category='SMTP Options' order='14' />
213219 /// .
214220 [ DefaultValue ( false ) ]
215- public bool EnableSsl { get ; set ; }
221+ public Layout < bool > EnableSsl { get ; set ; }
216222
217223 /// <summary>
218224 /// Provides a way of specifying the SSL and/or TLS encryption
219225 ///
220226 /// If <see cref="EnableSsl" /> is <c>true</c>, then <see cref="SecureSocketOptions.SslOnConnect" /> will be used.
221227 /// </summary>
222- [ DefaultValue ( SecureSocketOptions . StartTlsWhenAvailable ) ]
228+ [ DefaultValue ( DefaultSecureSocketOption ) ]
223229 [ CLSCompliant ( false ) ]
224- public SecureSocketOptions SecureSocketOption { get ; set ; }
230+ public Layout < SecureSocketOptions > SecureSocketOption { get ; set ; }
225231
226232 /// <summary>
227233 /// Gets or sets the port number that SMTP Server is listening on.
228234 /// </summary>
229235 /// <docgen category='SMTP Options' order='15' />
230236 [ DefaultValue ( 25 ) ]
231- public int SmtpPort { get ; set ; }
237+ public Layout < int > SmtpPort { get ; set ; }
232238
233239 /// <summary>
234240 /// Gets or sets a value indicating whether SmtpClient should ignore invalid certificate.
235241 /// </summary>
236242 /// <docgen category='SMTP Options' order='16' />
237243 /// .
238244 [ DefaultValue ( false ) ]
239- public bool SkipCertificateValidation { get ; set ; }
245+ public Layout < bool > SkipCertificateValidation { get ; set ; }
240246
241247 /// <summary>
242248 /// Gets or sets the priority used for sending mails.
@@ -248,22 +254,22 @@ public Layout Body
248254 /// </summary>
249255 /// <remarks>Only happens when <see cref="Html" /> is set to true.</remarks>
250256 [ DefaultValue ( false ) ]
251- public bool ReplaceNewlineWithBrTagInHtml { get ; set ; }
257+ public Layout < bool > ReplaceNewlineWithBrTagInHtml { get ; set ; }
252258
253259 /// <summary>
254260 /// Gets or sets a value indicating the SMTP client timeout.
255261 /// </summary>
256- /// <remarks>Warning: zero is not infinit waiting</remarks>
262+ /// <remarks>Warning: zero is not infinite waiting</remarks>
257263 [ DefaultValue ( 10000 ) ]
258- public int Timeout { get ; set ; }
264+ public Layout < int > Timeout { get ; set ; }
259265
260266 /// <summary>
261267 /// Renders the logging event message and adds it to the internal ArrayList of log messages.
262268 /// </summary>
263269 /// <param name="logEvent">The logging event.</param>
264270 protected override void Write ( AsyncLogEventInfo logEvent )
265271 {
266- Write ( ( IList < AsyncLogEventInfo > ) new [ ] { logEvent } ) ;
272+ Write ( new [ ] { logEvent } ) ;
267273 }
268274
269275 /// <summary>
@@ -289,9 +295,10 @@ protected override void InitializeTarget()
289295 InternalLogger . Debug ( "Init mailtarget with mailkit" ) ;
290296 CheckRequiredParameters ( ) ;
291297
292- if ( SmtpAuthentication == SmtpAuthenticationMode . Ntlm )
298+ var smtpAuthentication = RenderLogEvent ( SmtpAuthentication , LogEventInfo . CreateNullEvent ( ) ) ;
299+ if ( smtpAuthentication == SmtpAuthenticationMode . Ntlm )
293300 {
294- throw new NLogConfigurationException ( "Ntlm not yet supported" ) ;
301+ throw new NLogConfigurationException ( "NTLM not yet supported" ) ;
295302 }
296303
297304 base . InitializeTarget ( ) ;
@@ -321,26 +328,29 @@ private void ProcessSingleMailMessage(IList<AsyncLogEventInfo> events)
321328 using ( var client = new SmtpClient ( ) )
322329 {
323330 CheckRequiredParameters ( ) ;
324- client . Timeout = Timeout ;
331+ client . Timeout = RenderLogEvent ( Timeout , lastEvent ) ;
325332
326333 var renderedHost = SmtpServer . Render ( lastEvent ) ;
327334 if ( string . IsNullOrEmpty ( renderedHost ) )
328335 {
329- throw new NLogRuntimeException ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ;
336+ throw new NLogRuntimeException ( string . Format ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ) ;
330337 }
331338
332- var secureSocketOptions = EnableSsl ? SecureSocketOptions . SslOnConnect : SecureSocketOption ;
333- InternalLogger . Debug ( "Sending mail to {0} using {1}:{2} (socket option={3})" , message . To , renderedHost , SmtpPort , secureSocketOptions ) ;
339+ var enableSsl = RenderLogEvent ( EnableSsl , lastEvent ) ;
340+ var secureSocketOptions = enableSsl ? SecureSocketOptions . SslOnConnect : RenderLogEvent ( SecureSocketOption , lastEvent , DefaultSecureSocketOption ) ;
341+ var smtpPort = RenderLogEvent ( SmtpPort , lastEvent ) ;
342+ InternalLogger . Debug ( "Sending mail to {0} using {1}:{2} (socket option={3})" , message . To , renderedHost , smtpPort , secureSocketOptions ) ;
334343 InternalLogger . Trace ( " Subject: '{0}'" , message . Subject ) ;
335344 InternalLogger . Trace ( " From: '{0}'" , message . From ) ;
336345
337- if ( SkipCertificateValidation )
346+ var skipCertificateValidation = RenderLogEvent ( SkipCertificateValidation , lastEvent ) ;
347+ if ( skipCertificateValidation )
338348 {
339349 client . ServerCertificateValidationCallback += ( s , cert , chain , sslPolicyErrors ) => true ;
340350 }
341351
342352
343- client . Connect ( renderedHost , SmtpPort , secureSocketOptions ) ;
353+ client . Connect ( renderedHost , smtpPort , secureSocketOptions ) ;
344354 InternalLogger . Trace ( " Connecting succesfull" ) ;
345355
346356 // Note: since we don't have an OAuth2 token, disable
@@ -349,7 +359,8 @@ private void ProcessSingleMailMessage(IList<AsyncLogEventInfo> events)
349359
350360 // Note: only needed if the SMTP server requires authentication
351361
352- if ( SmtpAuthentication == SmtpAuthenticationMode . Basic )
362+ var smtpAuthentication = RenderLogEvent ( SmtpAuthentication , LogEventInfo . CreateNullEvent ( ) ) ;
363+ if ( smtpAuthentication == SmtpAuthenticationMode . Basic )
353364 {
354365 var userName = SmtpUserName ? . Render ( lastEvent ) ;
355366 var password = SmtpPassword ? . Render ( lastEvent ) ;
@@ -397,10 +408,11 @@ private void ProcessSingleMailMessage(IList<AsyncLogEventInfo> events)
397408 private StringBuilder CreateBodyBuffer ( IEnumerable < AsyncLogEventInfo > events , LogEventInfo firstEvent , LogEventInfo lastEvent )
398409 {
399410 var bodyBuffer = new StringBuilder ( ) ;
411+ var addNewLines = RenderLogEvent ( AddNewLines , firstEvent , false ) ;
400412 if ( Header != null )
401413 {
402414 bodyBuffer . Append ( Header . Render ( firstEvent ) ) ;
403- if ( AddNewLines )
415+ if ( addNewLines )
404416 {
405417 bodyBuffer . Append ( "\n " ) ;
406418 }
@@ -409,7 +421,7 @@ private StringBuilder CreateBodyBuffer(IEnumerable<AsyncLogEventInfo> events, Lo
409421 foreach ( var eventInfo in events )
410422 {
411423 bodyBuffer . Append ( Layout . Render ( eventInfo . LogEvent ) ) ;
412- if ( AddNewLines )
424+ if ( addNewLines )
413425 {
414426 bodyBuffer . Append ( "\n " ) ;
415427 }
@@ -418,7 +430,7 @@ private StringBuilder CreateBodyBuffer(IEnumerable<AsyncLogEventInfo> events, Lo
418430 if ( Footer != null )
419431 {
420432 bodyBuffer . Append ( Footer . Render ( lastEvent ) ) ;
421- if ( AddNewLines )
433+ if ( addNewLines )
422434 {
423435 bodyBuffer . Append ( "\n " ) ;
424436 }
@@ -431,17 +443,17 @@ private void CheckRequiredParameters()
431443 {
432444 if ( SmtpServer == null )
433445 {
434- throw new NLogConfigurationException ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ;
446+ throw new NLogConfigurationException ( string . Format ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ) ;
435447 }
436448
437449 if ( From == null )
438450 {
439- throw new NLogConfigurationException ( RequiredPropertyIsEmptyFormat , nameof ( From ) ) ;
451+ throw new NLogConfigurationException ( string . Format ( RequiredPropertyIsEmptyFormat , nameof ( From ) ) ) ;
440452 }
441453 }
442454
443455 /// <summary>
444- /// Create key for grouping. Needed for multiple events in one mailmessage
456+ /// Create key for grouping. Needed for multiple events in one mail message
445457 /// </summary>
446458 /// <param name="logEvent">event for rendering layouts </param>
447459 /// <returns>string to group on</returns>
@@ -456,7 +468,7 @@ private string GetSmtpSettingsKey(LogEventInfo logEvent)
456468 AppendLayout ( sb , logEvent , SmtpServer ) ;
457469 AppendLayout ( sb , logEvent , SmtpPassword ) ;
458470 AppendLayout ( sb , logEvent , SmtpUserName ) ;
459-
471+
460472 return sb . ToString ( ) ;
461473 }
462474
@@ -476,7 +488,7 @@ private static void AppendLayout(StringBuilder sb, LogEventInfo logEvent, Layout
476488 }
477489
478490 /// <summary>
479- /// Create the mailmessage with the addresses, properties and body.
491+ /// Create the mail message with the addresses, properties and body.
480492 /// </summary>
481493 private MimeMessage CreateMailMessage ( LogEventInfo lastEvent , string body )
482494 {
@@ -486,7 +498,7 @@ private MimeMessage CreateMailMessage(LogEventInfo lastEvent, string body)
486498
487499 if ( string . IsNullOrEmpty ( renderedFrom ) )
488500 {
489- throw new NLogRuntimeException ( RequiredPropertyIsEmptyFormat , "From" ) ;
501+ throw new NLogRuntimeException ( string . Format ( RequiredPropertyIsEmptyFormat , "From" ) ) ;
490502 }
491503
492504 msg . From . Add ( MailboxAddress . Parse ( renderedFrom ) ) ;
@@ -497,13 +509,11 @@ private MimeMessage CreateMailMessage(LogEventInfo lastEvent, string body)
497509
498510 if ( ! addedTo && ! addedCc && ! addedBcc )
499511 {
500- throw new NLogRuntimeException ( RequiredPropertyIsEmptyFormat , "To/Cc/Bcc" ) ;
512+ throw new NLogRuntimeException ( string . Format ( RequiredPropertyIsEmptyFormat , "To/Cc/Bcc" ) ) ;
501513 }
502514
503515 msg . Subject = Subject == null ? string . Empty : Subject . Render ( lastEvent ) . Trim ( ) ;
504516
505- //todo msg.BodyEncoding = Encoding;
506-
507517 if ( Priority != null )
508518 {
509519 var renderedPriority = Priority . Render ( lastEvent ) ;
@@ -513,15 +523,18 @@ private MimeMessage CreateMailMessage(LogEventInfo lastEvent, string body)
513523 TextPart CreateBodyPart ( )
514524 {
515525 var newBody = body ;
516- if ( Html && ReplaceNewlineWithBrTagInHtml )
526+ var html = RenderLogEvent ( Html , lastEvent ) ;
527+ var replaceNewlineWithBrTagInHtml = RenderLogEvent ( ReplaceNewlineWithBrTagInHtml , lastEvent ) ;
528+ if ( html && replaceNewlineWithBrTagInHtml )
517529 {
518530 newBody = newBody ? . Replace ( Environment . NewLine , "<br/>" ) ;
519531 }
520532
521- return new TextPart ( Html ? TextFormat . Html : TextFormat . Plain )
533+ var encoding = RenderLogEvent ( Encoding , lastEvent , DefaultEncoding ) ;
534+ return new TextPart ( html ? TextFormat . Html : TextFormat . Plain )
522535 {
523536 Text = newBody ,
524- ContentType = { Charset = Encoding ? . WebName }
537+ ContentType = { Charset = encoding ? . WebName }
525538 } ;
526539 }
527540
0 commit comments