11using Microsoft . Graph ;
22using Azure . Identity ;
3+ using System . Net . Sockets ;
4+ using System . Net ;
5+ using System . Text . RegularExpressions ;
36using Microsoft . Graph . Models ;
7+ using System . Text ;
48
9+ Console . WriteLine ( "Initializing..." ) ;
10+ var mail_listener = new TcpListener ( IPAddress . Any , 25 ) ;
511var scopes = new [ ] { "https://graph.microsoft.com/.default" } ;
6-
712var options = new ClientSecretCredentialOptions
813{
914 AuthorityHost = AzureAuthorityHosts . AzurePublicCloud ,
1015} ;
11-
1216var clientSecretCredential = new ClientSecretCredential (
1317 Environment . GetEnvironmentVariable ( "TENANT_ID" ) ,
1418 Environment . GetEnvironmentVariable ( "CLIENT_ID" ) ,
1519 Environment . GetEnvironmentVariable ( "CLIENT_SECRET" ) ,
1620 options
1721) ;
1822
19-
23+ Console . WriteLine ( "Setting up MS Graph Service Client..." ) ;
2024var graphClient = new GraphServiceClient ( clientSecretCredential , scopes ) ;
2125
22- await graphClient . Users [ "support@belowaverage.org" ] . SendMail . PostAsync ( new ( )
26+ Console . WriteLine ( "Starting SMTP listener loop..." ) ;
27+ mail_listener . Start ( ) ;
28+ while ( true )
29+ {
30+ try {
31+ var client = mail_listener . AcceptTcpClient ( ) ;
32+ Console . WriteLine ( "Accepting connection, attempting to process..." ) ;
33+ _ = Task . Run ( ( ) => {
34+ client . NoDelay = true ;
35+ var stream = client . GetStream ( ) ;
36+ var sw = new StreamWriter ( stream ) ;
37+ var sr = new StreamReader ( stream ) ;
38+ sw . AutoFlush = true ;
39+ sw . WriteLine ( $ "220 Who is it...?") ;
40+ HandleConnection ( client , stream , sw , sr ) ;
41+ } ) ;
42+ }
43+ catch ( Exception e )
44+ {
45+ Console . WriteLine ( "An error occured in the SMTP listener loop:" ) ;
46+ Console . WriteLine ( e . Message ) ;
47+ Console . WriteLine ( e . StackTrace ) ;
48+ }
49+ }
50+
51+ void HandleConnection ( TcpClient client , Stream stream , StreamWriter sw , StreamReader sr )
52+ {
53+ string From = string . Empty ;
54+ List < string > To = new ( ) ;
55+ string Body = string . Empty ;
56+ string Subject = string . Empty ;
57+ BodyType BType = BodyType . Text ;
58+ while ( true )
59+ {
60+ var msg = sr . ReadLine ( ) ;
61+ if ( msg . StartsWith ( "HELO" ) )
62+ {
63+ sw . WriteLine ( "250 Whatchu want?" ) ;
64+ continue ;
65+ }
66+ if ( msg . StartsWith ( "MAIL FROM:" ) )
67+ {
68+ From = Regex . Match ( msg , "<(.*)>" ) . Groups [ 1 ] . Value ;
69+ sw . WriteLine ( "250 You again?!" ) ;
70+ continue ;
71+ }
72+ if ( msg . StartsWith ( "RCPT TO:" ) )
73+ {
74+ To . Add ( Regex . Match ( msg , "<(.*)>" ) . Groups [ 1 ] . Value ) ;
75+ sw . WriteLine ( "250 Ok fine..." ) ;
76+ continue ;
77+ }
78+ if ( msg . StartsWith ( "DATA" ) )
79+ {
80+ sw . WriteLine ( "354 And whats so important that you have to bother me...?" ) ;
81+ ( BType , Subject , Body ) = ReadData ( sr ) ;
82+ sw . WriteLine ( "250 Oh yea, that was *very* important... SMH." ) ;
83+ continue ;
84+ }
85+ if ( msg . StartsWith ( "QUIT" ) )
86+ {
87+ sw . WriteLine ( "221 Bye, don't talk to me..." ) ;
88+ break ;
89+ }
90+ }
91+ client . Close ( ) ;
92+ Console . WriteLine ( "Sending to MS Graph..." ) ;
93+ SendMessage ( From , To , Subject , Body , BType ) ;
94+ Console . WriteLine ( "Done." ) ;
95+ }
96+
97+ ( BodyType , string , string ) ReadData ( StreamReader sr )
2398{
24- Message = new ( )
99+ string Subject = string . Empty ;
100+ string Body ;
101+ BodyType BType = BodyType . Text ;
102+ bool Base64 = false ;
103+ while ( true )
104+ {
105+ var msg = sr . ReadLine ( ) ;
106+ if ( msg . StartsWith ( "Subject:" ) )
107+ {
108+ Subject = Regex . Match ( msg , "Subject: (.*)" ) . Groups [ 1 ] . Value ;
109+ continue ;
110+ }
111+ if ( msg . StartsWith ( "Content-Type:" ) )
112+ {
113+ if ( msg . Contains ( "html" ) ) BType = BodyType . Html ;
114+ continue ;
115+ }
116+ if ( msg == "Content-Transfer-Encoding: base64" )
117+ {
118+ Base64 = true ;
119+ continue ;
120+ }
121+ if ( msg == string . Empty )
122+ {
123+ Body = ReadBody ( sr , Base64 ) ;
124+ break ;
125+ }
126+ }
127+ return ( BType , Subject , Body ) ;
128+ }
129+
130+ string ReadBody ( StreamReader sr , bool Base64 )
131+ {
132+ string Body = string . Empty ;
133+ while ( true )
134+ {
135+ var msg = sr . ReadLine ( ) ;
136+ if ( msg == "." ) break ;
137+ if ( msg == ".." )
138+ {
139+ msg = "." ;
140+ }
141+ Body += msg ;
142+ }
143+ if ( Base64 )
144+ {
145+ Body = Encoding . UTF8 . GetString ( Convert . FromBase64String ( Body ) ) ;
146+ }
147+ return Body ;
148+ }
149+
150+ void SendMessage ( string From , List < string > To , string Subject , string Body , BodyType BType )
151+ {
152+ List < Recipient > recipients = new ( ) ;
153+ foreach ( string email in To )
154+ {
155+ recipients . Add ( new ( ) { EmailAddress = new ( ) { Address = email } } ) ;
156+ }
157+ _ = graphClient . Users [ From ] . SendMail . PostAsync ( new ( )
25158 {
26- From = new ( ) { EmailAddress = new ( ) { Address = "support@belowaverage.org" } } ,
27- ToRecipients = [ new ( ) { EmailAddress = new ( ) { Address = "dylan@belowaverage.org" } } ] ,
28- Subject = "Hi" ,
29- Body = new ( ) { ContentType = BodyType . Html , Content = "Hi" }
30- } ,
31- SaveToSentItems = false
32- } ) ;
159+ Message = new ( )
160+ {
161+ From = new ( ) { EmailAddress = new ( ) { Address = From } } ,
162+ ToRecipients = recipients ,
163+ Subject = Subject ,
164+ Body = new ( ) { ContentType = BType , Content = Body }
165+ } ,
166+ SaveToSentItems = false
167+ } ) ;
168+ }
0 commit comments