1+ // Licensed to the .NET Foundation under one or more agreements. 
2+ // The .NET Foundation licenses this file to you under the MIT license. 
3+ 
4+ using  System . Net . NetworkInformation ; 
5+ using  System . Net . Security ; 
6+ using  System . Security . Authentication ; 
7+ using  System . Security . Cryptography ; 
8+ using  System . Security . Cryptography . X509Certificates ; 
9+ using  System . Net . Mail . Tests ; 
10+ using  System . Threading ; 
11+ using  System . Threading . Tasks ; 
12+ using  Xunit ; 
13+ using  Xunit . Sdk ; 
14+ using  Xunit . Abstractions ; 
15+ 
16+ namespace  System . Net . Mail . Tests 
17+ { 
18+     public  enum  SendMethod 
19+     { 
20+         Send , 
21+         SendAsync , 
22+         SendMailAsync 
23+     } 
24+ 
25+     public  interface  ISendMethodProvider 
26+     { 
27+         static abstract  SendMethod  SendMethod  {  get ;  } 
28+     } 
29+ 
30+     public  struct  SyncSendMethod  :  ISendMethodProvider 
31+     { 
32+         public  static SendMethod  SendMethod  =>  SendMethod . Send ; 
33+     } 
34+ 
35+     public  struct  AsyncSendMethod  :  ISendMethodProvider 
36+     { 
37+         public  static SendMethod  SendMethod  =>  SendMethod . SendAsync ; 
38+     } 
39+ 
40+     public  struct  SendMailAsyncMethod  :  ISendMethodProvider 
41+     { 
42+         public  static SendMethod  SendMethod  =>  SendMethod . SendMailAsync ; 
43+     } 
44+ 
45+     public  abstract  class  LoopbackServerTestBase < T >  :  IDisposable 
46+         where  T  :  ISendMethodProvider 
47+     { 
48+         protected  LoopbackSmtpServer  Server  {  get ;  private  set ;  } 
49+         protected  ITestOutputHelper  Output  {  get ;  private  set ;  } 
50+ 
51+         private  SmtpClient  _smtp ; 
52+ 
53+         protected  SmtpClient  Smtp 
54+         { 
55+             get 
56+             { 
57+                 return  _smtp  ??=  Server . CreateClient ( ) ; 
58+             } 
59+         } 
60+ 
61+         public  LoopbackServerTestBase ( ITestOutputHelper  output ) 
62+         { 
63+             Output  =  output ; 
64+             Server  =  new  LoopbackSmtpServer ( Output ) ; 
65+         } 
66+ 
67+         private  Task < Exception ? >  SendMailInternal ( MailMessage  msg ,  CancellationToken  cancellationToken ,  bool ?  asyncExpectDirectException ) 
68+         { 
69+             switch  ( T . SendMethod ) 
70+             { 
71+                 case  SendMethod . Send : 
72+                     try 
73+                     { 
74+                         Smtp . Send ( msg ) ; 
75+                         return  Task . FromResult < Exception > ( null ) ; 
76+                     } 
77+                     catch  ( Exception  ex ) 
78+                     { 
79+                         return  Task . FromResult ( ex ) ; 
80+                     } 
81+ 
82+                 case  SendMethod . SendAsync : 
83+                     TaskCompletionSource < Exception ? >  tcs  =  new  TaskCompletionSource < Exception ? > ( ) ; 
84+                     SendCompletedEventHandler  handler  =  null ! ; 
85+                     handler  =  ( s ,  e )  => 
86+                     { 
87+                         Smtp . SendCompleted  -=  handler ; 
88+ 
89+                         if  ( e . Error  !=  null ) 
90+                         { 
91+                             tcs . SetResult ( e . Error ) ; 
92+                         } 
93+                         else  if  ( e . Cancelled ) 
94+                         { 
95+                             tcs . SetResult ( new  OperationCanceledException ( "The operation was canceled." ) ) ; 
96+                         } 
97+                         else 
98+                         { 
99+                             tcs . SetResult ( null ) ; 
100+                         } 
101+                     } ; 
102+                     Smtp . SendCompleted  +=  handler ; 
103+                     try 
104+                     { 
105+                         Smtp . SendAsync ( msg ,  tcs ) ; 
106+ 
107+                         if  ( asyncExpectDirectException  ==  true ) 
108+                         { 
109+                             Assert . Fail ( $ "No exception thrown") ; 
110+                         } 
111+ 
112+                         return  tcs . Task ; 
113+                     } 
114+                     catch  ( Exception  ex )  when  ( ex  is  not XunitException ) 
115+                     { 
116+                         Smtp . SendCompleted  -=  handler ; 
117+ 
118+                         if  ( asyncExpectDirectException  ==  false ) 
119+                         { 
120+                             Assert . Fail ( $ "Expected exception via callback, got direct: { ex } ") ; 
121+                         } 
122+ 
123+                         return  Task . FromResult ( ex ) ; 
124+                     } 
125+ 
126+                 case  SendMethod . SendMailAsync : 
127+                     try 
128+                     { 
129+                         Task  task  =  Smtp . SendMailAsync ( msg ,  cancellationToken ) ; 
130+ 
131+                         if  ( asyncExpectDirectException  ==  true ) 
132+                         { 
133+                             Assert . Fail ( $ "No exception thrown") ; 
134+                         } 
135+ 
136+                         return  task . ContinueWith ( t =>  t . Exception ? . InnerException ) ; 
137+                     } 
138+                     catch  ( Exception  ex )  when  ( ex  is  not XunitException ) 
139+                     { 
140+                         if  ( asyncExpectDirectException  ==  false ) 
141+                         { 
142+                             Assert . Fail ( $ "Expected stored exception, got direct: { ex } ") ; 
143+                         } 
144+ 
145+                         return  Task . FromResult ( ex ) ; 
146+                     } 
147+ 
148+                 default : 
149+                     throw  new  ArgumentOutOfRangeException ( ) ; 
150+             } 
151+         } 
152+ 
153+         protected  async  Task  SendMail ( MailMessage  msg ,  CancellationToken  cancellationToken  =  default ) 
154+         { 
155+             Exception ?  ex  =  await  SendMailInternal ( msg ,  cancellationToken ,  null ) ; 
156+             Assert . Null ( ex ) ; 
157+         } 
158+ 
159+         protected  async  Task < TException >  SendMail < TException > ( MailMessage  msg ,  CancellationToken  cancellationToken  =  default ,  bool  unwrapException  =  true ,  bool  asyncDirectException  =  false )  where  TException  :  Exception 
160+         { 
161+             Exception ?  ex  =  await  SendMailInternal ( msg ,  cancellationToken ,  asyncDirectException ) ; 
162+ 
163+             if  ( unwrapException  &&  T . SendMethod  !=  SendMethod . Send  &&  typeof ( TException )  !=  typeof ( SmtpException ) ) 
164+             { 
165+                 ex  =  Assert . IsType < SmtpException > ( ex ) . InnerException ; 
166+             } 
167+ 
168+             return  Assert . IsType < TException > ( ex ) ; 
169+         } 
170+ 
171+         protected  static string  GetClientDomain ( )  =>  IPGlobalProperties . GetIPGlobalProperties ( ) . HostName . Trim ( ) . ToLower ( ) ; 
172+ 
173+         public  virtual  void  Dispose ( ) 
174+         { 
175+             _smtp ? . Dispose ( ) ; 
176+             Server ? . Dispose ( ) ; 
177+         } 
178+     } 
179+ } 
0 commit comments