1
1
//
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
3
3
//
4
4
// All rights reserved.
5
5
//
34
34
using System ;
35
35
using System . Collections . Generic ;
36
36
using System . ComponentModel ;
37
+ using System . Diagnostics . CodeAnalysis ;
37
38
using System . Text ;
38
39
using MailKit . Net . Smtp ;
39
40
using MailKit . Security ;
@@ -80,8 +81,12 @@ namespace NLog.MailKit
80
81
/// <code lang="C#" source="examples/targets/Configuration API/Mail/Buffered/Example.cs" />
81
82
/// </example>
82
83
[ Target ( "Mail" ) ]
84
+ [ SuppressMessage ( "ReSharper" , "RedundantStringFormatCall" ) ]
83
85
public class MailTarget : TargetWithLayoutHeaderAndFooter
84
86
{
87
+ private static readonly Encoding DefaultEncoding = System . Text . Encoding . UTF8 ;
88
+ private const SecureSocketOptions DefaultSecureSocketOption = SecureSocketOptions . StartTlsWhenAvailable ;
89
+
85
90
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." ;
86
91
87
92
/// <summary>
@@ -94,10 +99,10 @@ public MailTarget()
94
99
{
95
100
Body = "${message}${newline}" ;
96
101
Subject = "Message from NLog on ${machinename}" ;
97
- Encoding = Encoding . UTF8 ;
102
+ Encoding = DefaultEncoding ;
98
103
SmtpPort = 25 ;
99
104
SmtpAuthentication = SmtpAuthenticationMode . None ;
100
- SecureSocketOption = SecureSocketOptions . StartTlsWhenAvailable ;
105
+ SecureSocketOption = DefaultSecureSocketOption ;
101
106
Timeout = 10000 ;
102
107
}
103
108
@@ -143,7 +148,8 @@ public MailTarget(string name) : this()
143
148
/// </summary>
144
149
/// <value>A value of <c>true</c> if new lines should be added; otherwise, <c>false</c>.</value>
145
150
/// <docgen category='Layout Options' order='99' />
146
- public bool AddNewLines { get ; set ; }
151
+ [ DefaultValue ( false ) ]
152
+ public Layout < bool > AddNewLines { get ; set ; }
147
153
148
154
/// <summary>
149
155
/// Gets or sets the mail subject.
@@ -170,14 +176,14 @@ public Layout Body
170
176
/// </summary>
171
177
/// <docgen category='Layout Options' order='20' />
172
178
[ DefaultValue ( "UTF8" ) ]
173
- public Encoding Encoding { get ; set ; }
179
+ public Layout < Encoding > Encoding { get ; set ; }
174
180
175
181
/// <summary>
176
182
/// Gets or sets a value indicating whether to send message as HTML instead of plain text.
177
183
/// </summary>
178
184
/// <docgen category='Layout Options' order='11' />
179
185
[ DefaultValue ( false ) ]
180
- public bool Html { get ; set ; }
186
+ public Layout < bool > Html { get ; set ; }
181
187
182
188
/// <summary>
183
189
/// Gets or sets SMTP Server to be used for sending.
@@ -190,16 +196,16 @@ public Layout Body
190
196
/// </summary>
191
197
/// <docgen category='SMTP Options' order='11' />
192
198
[ DefaultValue ( "None" ) ]
193
- public SmtpAuthenticationMode SmtpAuthentication { get ; set ; }
199
+ public Layout < SmtpAuthenticationMode > SmtpAuthentication { get ; set ; }
194
200
195
201
/// <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").
197
203
/// </summary>
198
204
/// <docgen category='SMTP Options' order='12' />
199
205
public Layout SmtpUserName { get ; set ; }
200
206
201
207
/// <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").
203
209
/// </summary>
204
210
/// <docgen category='SMTP Options' order='13' />
205
211
public Layout SmtpPassword { get ; set ; }
@@ -212,31 +218,31 @@ public Layout Body
212
218
/// <docgen category='SMTP Options' order='14' />
213
219
/// .
214
220
[ DefaultValue ( false ) ]
215
- public bool EnableSsl { get ; set ; }
221
+ public Layout < bool > EnableSsl { get ; set ; }
216
222
217
223
/// <summary>
218
224
/// Provides a way of specifying the SSL and/or TLS encryption
219
225
///
220
226
/// If <see cref="EnableSsl" /> is <c>true</c>, then <see cref="SecureSocketOptions.SslOnConnect" /> will be used.
221
227
/// </summary>
222
- [ DefaultValue ( SecureSocketOptions . StartTlsWhenAvailable ) ]
228
+ [ DefaultValue ( DefaultSecureSocketOption ) ]
223
229
[ CLSCompliant ( false ) ]
224
- public SecureSocketOptions SecureSocketOption { get ; set ; }
230
+ public Layout < SecureSocketOptions > SecureSocketOption { get ; set ; }
225
231
226
232
/// <summary>
227
233
/// Gets or sets the port number that SMTP Server is listening on.
228
234
/// </summary>
229
235
/// <docgen category='SMTP Options' order='15' />
230
236
[ DefaultValue ( 25 ) ]
231
- public int SmtpPort { get ; set ; }
237
+ public Layout < int > SmtpPort { get ; set ; }
232
238
233
239
/// <summary>
234
240
/// Gets or sets a value indicating whether SmtpClient should ignore invalid certificate.
235
241
/// </summary>
236
242
/// <docgen category='SMTP Options' order='16' />
237
243
/// .
238
244
[ DefaultValue ( false ) ]
239
- public bool SkipCertificateValidation { get ; set ; }
245
+ public Layout < bool > SkipCertificateValidation { get ; set ; }
240
246
241
247
/// <summary>
242
248
/// Gets or sets the priority used for sending mails.
@@ -248,22 +254,22 @@ public Layout Body
248
254
/// </summary>
249
255
/// <remarks>Only happens when <see cref="Html" /> is set to true.</remarks>
250
256
[ DefaultValue ( false ) ]
251
- public bool ReplaceNewlineWithBrTagInHtml { get ; set ; }
257
+ public Layout < bool > ReplaceNewlineWithBrTagInHtml { get ; set ; }
252
258
253
259
/// <summary>
254
260
/// Gets or sets a value indicating the SMTP client timeout.
255
261
/// </summary>
256
- /// <remarks>Warning: zero is not infinit waiting</remarks>
262
+ /// <remarks>Warning: zero is not infinite waiting</remarks>
257
263
[ DefaultValue ( 10000 ) ]
258
- public int Timeout { get ; set ; }
264
+ public Layout < int > Timeout { get ; set ; }
259
265
260
266
/// <summary>
261
267
/// Renders the logging event message and adds it to the internal ArrayList of log messages.
262
268
/// </summary>
263
269
/// <param name="logEvent">The logging event.</param>
264
270
protected override void Write ( AsyncLogEventInfo logEvent )
265
271
{
266
- Write ( ( IList < AsyncLogEventInfo > ) new [ ] { logEvent } ) ;
272
+ Write ( new [ ] { logEvent } ) ;
267
273
}
268
274
269
275
/// <summary>
@@ -289,9 +295,10 @@ protected override void InitializeTarget()
289
295
InternalLogger . Debug ( "Init mailtarget with mailkit" ) ;
290
296
CheckRequiredParameters ( ) ;
291
297
292
- if ( SmtpAuthentication == SmtpAuthenticationMode . Ntlm )
298
+ var smtpAuthentication = RenderLogEvent ( SmtpAuthentication , LogEventInfo . CreateNullEvent ( ) ) ;
299
+ if ( smtpAuthentication == SmtpAuthenticationMode . Ntlm )
293
300
{
294
- throw new NLogConfigurationException ( "Ntlm not yet supported" ) ;
301
+ throw new NLogConfigurationException ( "NTLM not yet supported" ) ;
295
302
}
296
303
297
304
base . InitializeTarget ( ) ;
@@ -321,26 +328,29 @@ private void ProcessSingleMailMessage(IList<AsyncLogEventInfo> events)
321
328
using ( var client = new SmtpClient ( ) )
322
329
{
323
330
CheckRequiredParameters ( ) ;
324
- client . Timeout = Timeout ;
331
+ client . Timeout = RenderLogEvent ( Timeout , lastEvent ) ;
325
332
326
333
var renderedHost = SmtpServer . Render ( lastEvent ) ;
327
334
if ( string . IsNullOrEmpty ( renderedHost ) )
328
335
{
329
- throw new NLogRuntimeException ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ;
336
+ throw new NLogRuntimeException ( string . Format ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ) ;
330
337
}
331
338
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 ) ;
334
343
InternalLogger . Trace ( " Subject: '{0}'" , message . Subject ) ;
335
344
InternalLogger . Trace ( " From: '{0}'" , message . From ) ;
336
345
337
- if ( SkipCertificateValidation )
346
+ var skipCertificateValidation = RenderLogEvent ( SkipCertificateValidation , lastEvent ) ;
347
+ if ( skipCertificateValidation )
338
348
{
339
349
client . ServerCertificateValidationCallback += ( s , cert , chain , sslPolicyErrors ) => true ;
340
350
}
341
351
342
352
343
- client . Connect ( renderedHost , SmtpPort , secureSocketOptions ) ;
353
+ client . Connect ( renderedHost , smtpPort , secureSocketOptions ) ;
344
354
InternalLogger . Trace ( " Connecting succesfull" ) ;
345
355
346
356
// Note: since we don't have an OAuth2 token, disable
@@ -349,7 +359,8 @@ private void ProcessSingleMailMessage(IList<AsyncLogEventInfo> events)
349
359
350
360
// Note: only needed if the SMTP server requires authentication
351
361
352
- if ( SmtpAuthentication == SmtpAuthenticationMode . Basic )
362
+ var smtpAuthentication = RenderLogEvent ( SmtpAuthentication , LogEventInfo . CreateNullEvent ( ) ) ;
363
+ if ( smtpAuthentication == SmtpAuthenticationMode . Basic )
353
364
{
354
365
var userName = SmtpUserName ? . Render ( lastEvent ) ;
355
366
var password = SmtpPassword ? . Render ( lastEvent ) ;
@@ -397,10 +408,11 @@ private void ProcessSingleMailMessage(IList<AsyncLogEventInfo> events)
397
408
private StringBuilder CreateBodyBuffer ( IEnumerable < AsyncLogEventInfo > events , LogEventInfo firstEvent , LogEventInfo lastEvent )
398
409
{
399
410
var bodyBuffer = new StringBuilder ( ) ;
411
+ var addNewLines = RenderLogEvent ( AddNewLines , firstEvent , false ) ;
400
412
if ( Header != null )
401
413
{
402
414
bodyBuffer . Append ( Header . Render ( firstEvent ) ) ;
403
- if ( AddNewLines )
415
+ if ( addNewLines )
404
416
{
405
417
bodyBuffer . Append ( "\n " ) ;
406
418
}
@@ -409,7 +421,7 @@ private StringBuilder CreateBodyBuffer(IEnumerable<AsyncLogEventInfo> events, Lo
409
421
foreach ( var eventInfo in events )
410
422
{
411
423
bodyBuffer . Append ( Layout . Render ( eventInfo . LogEvent ) ) ;
412
- if ( AddNewLines )
424
+ if ( addNewLines )
413
425
{
414
426
bodyBuffer . Append ( "\n " ) ;
415
427
}
@@ -418,7 +430,7 @@ private StringBuilder CreateBodyBuffer(IEnumerable<AsyncLogEventInfo> events, Lo
418
430
if ( Footer != null )
419
431
{
420
432
bodyBuffer . Append ( Footer . Render ( lastEvent ) ) ;
421
- if ( AddNewLines )
433
+ if ( addNewLines )
422
434
{
423
435
bodyBuffer . Append ( "\n " ) ;
424
436
}
@@ -431,17 +443,17 @@ private void CheckRequiredParameters()
431
443
{
432
444
if ( SmtpServer == null )
433
445
{
434
- throw new NLogConfigurationException ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ;
446
+ throw new NLogConfigurationException ( string . Format ( RequiredPropertyIsEmptyFormat , nameof ( SmtpServer ) ) ) ;
435
447
}
436
448
437
449
if ( From == null )
438
450
{
439
- throw new NLogConfigurationException ( RequiredPropertyIsEmptyFormat , nameof ( From ) ) ;
451
+ throw new NLogConfigurationException ( string . Format ( RequiredPropertyIsEmptyFormat , nameof ( From ) ) ) ;
440
452
}
441
453
}
442
454
443
455
/// <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
445
457
/// </summary>
446
458
/// <param name="logEvent">event for rendering layouts </param>
447
459
/// <returns>string to group on</returns>
@@ -456,7 +468,7 @@ private string GetSmtpSettingsKey(LogEventInfo logEvent)
456
468
AppendLayout ( sb , logEvent , SmtpServer ) ;
457
469
AppendLayout ( sb , logEvent , SmtpPassword ) ;
458
470
AppendLayout ( sb , logEvent , SmtpUserName ) ;
459
-
471
+
460
472
return sb . ToString ( ) ;
461
473
}
462
474
@@ -476,7 +488,7 @@ private static void AppendLayout(StringBuilder sb, LogEventInfo logEvent, Layout
476
488
}
477
489
478
490
/// <summary>
479
- /// Create the mailmessage with the addresses, properties and body.
491
+ /// Create the mail message with the addresses, properties and body.
480
492
/// </summary>
481
493
private MimeMessage CreateMailMessage ( LogEventInfo lastEvent , string body )
482
494
{
@@ -486,7 +498,7 @@ private MimeMessage CreateMailMessage(LogEventInfo lastEvent, string body)
486
498
487
499
if ( string . IsNullOrEmpty ( renderedFrom ) )
488
500
{
489
- throw new NLogRuntimeException ( RequiredPropertyIsEmptyFormat , "From" ) ;
501
+ throw new NLogRuntimeException ( string . Format ( RequiredPropertyIsEmptyFormat , "From" ) ) ;
490
502
}
491
503
492
504
msg . From . Add ( MailboxAddress . Parse ( renderedFrom ) ) ;
@@ -497,13 +509,11 @@ private MimeMessage CreateMailMessage(LogEventInfo lastEvent, string body)
497
509
498
510
if ( ! addedTo && ! addedCc && ! addedBcc )
499
511
{
500
- throw new NLogRuntimeException ( RequiredPropertyIsEmptyFormat , "To/Cc/Bcc" ) ;
512
+ throw new NLogRuntimeException ( string . Format ( RequiredPropertyIsEmptyFormat , "To/Cc/Bcc" ) ) ;
501
513
}
502
514
503
515
msg . Subject = Subject == null ? string . Empty : Subject . Render ( lastEvent ) . Trim ( ) ;
504
516
505
- //todo msg.BodyEncoding = Encoding;
506
-
507
517
if ( Priority != null )
508
518
{
509
519
var renderedPriority = Priority . Render ( lastEvent ) ;
@@ -513,15 +523,18 @@ private MimeMessage CreateMailMessage(LogEventInfo lastEvent, string body)
513
523
TextPart CreateBodyPart ( )
514
524
{
515
525
var newBody = body ;
516
- if ( Html && ReplaceNewlineWithBrTagInHtml )
526
+ var html = RenderLogEvent ( Html , lastEvent ) ;
527
+ var replaceNewlineWithBrTagInHtml = RenderLogEvent ( ReplaceNewlineWithBrTagInHtml , lastEvent ) ;
528
+ if ( html && replaceNewlineWithBrTagInHtml )
517
529
{
518
530
newBody = newBody ? . Replace ( Environment . NewLine , "<br/>" ) ;
519
531
}
520
532
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 )
522
535
{
523
536
Text = newBody ,
524
- ContentType = { Charset = Encoding ? . WebName }
537
+ ContentType = { Charset = encoding ? . WebName }
525
538
} ;
526
539
}
527
540
0 commit comments