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 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections; 7 using System.Globalization; 8 using System.IO; 9 using System.Net.Mime; 10 using System.Runtime.ExceptionServices; 11 using System.Text; 12 13 namespace System.Net.Mail 14 { 15 internal static class CheckCommand 16 { 17 private static readonly AsyncCallback s_onReadLine = new AsyncCallback(OnReadLine); 18 private static readonly AsyncCallback s_onWrite = new AsyncCallback(OnWrite); 19 BeginSend(SmtpConnection conn, AsyncCallback callback, object state)20 internal static IAsyncResult BeginSend(SmtpConnection conn, AsyncCallback callback, object state) 21 { 22 MultiAsyncResult multiResult = new MultiAsyncResult(conn, callback, state); 23 multiResult.Enter(); 24 IAsyncResult writeResult = conn.BeginFlush(s_onWrite, multiResult); 25 if (writeResult.CompletedSynchronously) 26 { 27 conn.EndFlush(writeResult); 28 multiResult.Leave(); 29 } 30 SmtpReplyReader reader = conn.Reader.GetNextReplyReader(); 31 multiResult.Enter(); 32 33 //this actually does a read on the stream. 34 IAsyncResult result = reader.BeginReadLine(s_onReadLine, multiResult); 35 if (result.CompletedSynchronously) 36 { 37 LineInfo info = reader.EndReadLine(result); 38 if (!(multiResult.Result is Exception)) 39 multiResult.Result = info; 40 multiResult.Leave(); 41 } 42 multiResult.CompleteSequence(); 43 return multiResult; 44 } 45 46 EndSend(IAsyncResult result, out string response)47 internal static object EndSend(IAsyncResult result, out string response) 48 { 49 object commandResult = MultiAsyncResult.End(result); 50 if (commandResult is Exception e) 51 { 52 ExceptionDispatchInfo.Throw(e); 53 } 54 55 LineInfo info = (LineInfo)commandResult; 56 response = info.Line; 57 return info.StatusCode; 58 } 59 OnReadLine(IAsyncResult result)60 private static void OnReadLine(IAsyncResult result) 61 { 62 if (!result.CompletedSynchronously) 63 { 64 MultiAsyncResult multiResult = (MultiAsyncResult)result.AsyncState; 65 try 66 { 67 SmtpConnection conn = (SmtpConnection)multiResult.Context; 68 LineInfo info = conn.Reader.CurrentReader.EndReadLine(result); 69 if (!(multiResult.Result is Exception)) 70 multiResult.Result = info; 71 multiResult.Leave(); 72 } 73 catch (Exception e) 74 { 75 multiResult.Leave(e); 76 } 77 } 78 } 79 OnWrite(IAsyncResult result)80 private static void OnWrite(IAsyncResult result) 81 { 82 if (!result.CompletedSynchronously) 83 { 84 MultiAsyncResult multiResult = (MultiAsyncResult)result.AsyncState; 85 try 86 { 87 SmtpConnection conn = (SmtpConnection)multiResult.Context; 88 conn.EndFlush(result); 89 multiResult.Leave(); 90 } 91 catch (Exception e) 92 { 93 multiResult.Leave(e); 94 } 95 } 96 } 97 Send(SmtpConnection conn, out string response)98 internal static SmtpStatusCode Send(SmtpConnection conn, out string response) 99 { 100 conn.Flush(); 101 SmtpReplyReader reader = conn.Reader.GetNextReplyReader(); 102 LineInfo info = reader.ReadLine(); 103 response = info.Line; 104 reader.Close(); 105 return info.StatusCode; 106 } 107 } 108 109 internal static class ReadLinesCommand 110 { 111 private static readonly AsyncCallback s_onReadLines = new AsyncCallback(OnReadLines); 112 private static readonly AsyncCallback s_onWrite = new AsyncCallback(OnWrite); 113 BeginSend(SmtpConnection conn, AsyncCallback callback, object state)114 internal static IAsyncResult BeginSend(SmtpConnection conn, AsyncCallback callback, object state) 115 { 116 MultiAsyncResult multiResult = new MultiAsyncResult(conn, callback, state); 117 multiResult.Enter(); 118 IAsyncResult writeResult = conn.BeginFlush(s_onWrite, multiResult); 119 if (writeResult.CompletedSynchronously) 120 { 121 conn.EndFlush(writeResult); 122 multiResult.Leave(); 123 } 124 SmtpReplyReader reader = conn.Reader.GetNextReplyReader(); 125 multiResult.Enter(); 126 IAsyncResult readLinesResult = reader.BeginReadLines(s_onReadLines, multiResult); 127 if (readLinesResult.CompletedSynchronously) 128 { 129 LineInfo[] lines = conn.Reader.CurrentReader.EndReadLines(readLinesResult); 130 if (!(multiResult.Result is Exception)) 131 multiResult.Result = lines; 132 multiResult.Leave(); 133 } 134 multiResult.CompleteSequence(); 135 return multiResult; 136 } 137 EndSend(IAsyncResult result)138 internal static LineInfo[] EndSend(IAsyncResult result) 139 { 140 object commandResult = MultiAsyncResult.End(result); 141 if (commandResult is Exception e) 142 { 143 ExceptionDispatchInfo.Throw(e); 144 } 145 return (LineInfo[])commandResult; 146 } 147 OnReadLines(IAsyncResult result)148 private static void OnReadLines(IAsyncResult result) 149 { 150 if (!result.CompletedSynchronously) 151 { 152 MultiAsyncResult multiResult = (MultiAsyncResult)result.AsyncState; 153 try 154 { 155 SmtpConnection conn = (SmtpConnection)multiResult.Context; 156 LineInfo[] lines = conn.Reader.CurrentReader.EndReadLines(result); 157 if (!(multiResult.Result is Exception)) 158 multiResult.Result = lines; 159 multiResult.Leave(); 160 } 161 catch (Exception e) 162 { 163 multiResult.Leave(e); 164 } 165 } 166 } 167 OnWrite(IAsyncResult result)168 private static void OnWrite(IAsyncResult result) 169 { 170 if (!result.CompletedSynchronously) 171 { 172 MultiAsyncResult multiResult = (MultiAsyncResult)result.AsyncState; 173 try 174 { 175 SmtpConnection conn = (SmtpConnection)multiResult.Context; 176 conn.EndFlush(result); 177 multiResult.Leave(); 178 } 179 catch (Exception e) 180 { 181 multiResult.Leave(e); 182 } 183 } 184 } Send(SmtpConnection conn)185 internal static LineInfo[] Send(SmtpConnection conn) 186 { 187 conn.Flush(); 188 return conn.Reader.GetNextReplyReader().ReadLines(); 189 } 190 } 191 192 internal static class AuthCommand 193 { BeginSend(SmtpConnection conn, string type, string message, AsyncCallback callback, object state)194 internal static IAsyncResult BeginSend(SmtpConnection conn, string type, string message, AsyncCallback callback, object state) 195 { 196 PrepareCommand(conn, type, message); 197 return ReadLinesCommand.BeginSend(conn, callback, state); 198 } 199 BeginSend(SmtpConnection conn, string message, AsyncCallback callback, object state)200 internal static IAsyncResult BeginSend(SmtpConnection conn, string message, AsyncCallback callback, object state) 201 { 202 PrepareCommand(conn, message); 203 return ReadLinesCommand.BeginSend(conn, callback, state); 204 } 205 CheckResponse(LineInfo[] lines)206 private static LineInfo CheckResponse(LineInfo[] lines) 207 { 208 if (lines == null || lines.Length == 0) 209 { 210 throw new SmtpException(SR.SmtpAuthResponseInvalid); 211 } 212 System.Diagnostics.Debug.Assert(lines.Length == 1, "Did not expect more than one line response for auth command"); 213 return lines[0]; 214 } 215 EndSend(IAsyncResult result)216 internal static LineInfo EndSend(IAsyncResult result) 217 { 218 return CheckResponse(ReadLinesCommand.EndSend(result)); 219 } PrepareCommand(SmtpConnection conn, string type, string message)220 private static void PrepareCommand(SmtpConnection conn, string type, string message) 221 { 222 conn.BufferBuilder.Append(SmtpCommands.Auth); 223 conn.BufferBuilder.Append(type); 224 conn.BufferBuilder.Append((byte)' '); 225 conn.BufferBuilder.Append(message); 226 conn.BufferBuilder.Append(SmtpCommands.CRLF); 227 } 228 PrepareCommand(SmtpConnection conn, string message)229 private static void PrepareCommand(SmtpConnection conn, string message) 230 { 231 conn.BufferBuilder.Append(message); 232 conn.BufferBuilder.Append(SmtpCommands.CRLF); 233 } 234 Send(SmtpConnection conn, string type, string message)235 internal static LineInfo Send(SmtpConnection conn, string type, string message) 236 { 237 PrepareCommand(conn, type, message); 238 return CheckResponse(ReadLinesCommand.Send(conn)); 239 } 240 Send(SmtpConnection conn, string message)241 internal static LineInfo Send(SmtpConnection conn, string message) 242 { 243 PrepareCommand(conn, message); 244 return CheckResponse(ReadLinesCommand.Send(conn)); 245 } 246 } 247 248 internal static class DataCommand 249 { BeginSend(SmtpConnection conn, AsyncCallback callback, object state)250 internal static IAsyncResult BeginSend(SmtpConnection conn, AsyncCallback callback, object state) 251 { 252 PrepareCommand(conn); 253 return CheckCommand.BeginSend(conn, callback, state); 254 } 255 CheckResponse(SmtpStatusCode statusCode, string serverResponse)256 private static void CheckResponse(SmtpStatusCode statusCode, string serverResponse) 257 { 258 switch (statusCode) 259 { 260 case SmtpStatusCode.StartMailInput: 261 { 262 return; 263 } 264 case SmtpStatusCode.LocalErrorInProcessing: 265 case SmtpStatusCode.TransactionFailed: 266 default: 267 { 268 if ((int)statusCode < 400) 269 { 270 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, serverResponse); 271 } 272 273 throw new SmtpException(statusCode, serverResponse, true); 274 } 275 } 276 } 277 EndSend(IAsyncResult result)278 internal static void EndSend(IAsyncResult result) 279 { 280 string response; 281 SmtpStatusCode statusCode = (SmtpStatusCode)CheckCommand.EndSend(result, out response); 282 CheckResponse(statusCode, response); 283 } 284 PrepareCommand(SmtpConnection conn)285 private static void PrepareCommand(SmtpConnection conn) 286 { 287 if (conn.IsStreamOpen) 288 { 289 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 290 } 291 292 conn.BufferBuilder.Append(SmtpCommands.Data); 293 } 294 Send(SmtpConnection conn)295 internal static void Send(SmtpConnection conn) 296 { 297 PrepareCommand(conn); 298 string response; 299 SmtpStatusCode statusCode = CheckCommand.Send(conn, out response); 300 CheckResponse(statusCode, response); 301 } 302 } 303 304 internal static class DataStopCommand 305 { CheckResponse(SmtpStatusCode statusCode, string serverResponse)306 private static void CheckResponse(SmtpStatusCode statusCode, string serverResponse) 307 { 308 switch (statusCode) 309 { 310 case SmtpStatusCode.Ok: 311 { 312 return; 313 } 314 case SmtpStatusCode.ExceededStorageAllocation: 315 case SmtpStatusCode.TransactionFailed: 316 case SmtpStatusCode.LocalErrorInProcessing: 317 case SmtpStatusCode.InsufficientStorage: 318 default: 319 { 320 if ((int)statusCode < 400) 321 { 322 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, serverResponse); 323 } 324 325 throw new SmtpException(statusCode, serverResponse, true); 326 } 327 } 328 } 329 PrepareCommand(SmtpConnection conn)330 private static void PrepareCommand(SmtpConnection conn) 331 { 332 if (conn.IsStreamOpen) 333 { 334 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 335 } 336 337 conn.BufferBuilder.Append(SmtpCommands.DataStop); 338 } Send(SmtpConnection conn)339 internal static void Send(SmtpConnection conn) 340 { 341 PrepareCommand(conn); 342 string response; 343 SmtpStatusCode statusCode = CheckCommand.Send(conn, out response); 344 CheckResponse(statusCode, response); 345 } 346 } 347 348 internal static class EHelloCommand 349 { BeginSend(SmtpConnection conn, string domain, AsyncCallback callback, object state)350 internal static IAsyncResult BeginSend(SmtpConnection conn, string domain, AsyncCallback callback, object state) 351 { 352 PrepareCommand(conn, domain); 353 return ReadLinesCommand.BeginSend(conn, callback, state); 354 } 355 CheckResponse(LineInfo[] lines)356 private static string[] CheckResponse(LineInfo[] lines) 357 { 358 if (lines == null || lines.Length == 0) 359 { 360 throw new SmtpException(SR.SmtpEhloResponseInvalid); 361 } 362 if (lines[0].StatusCode != SmtpStatusCode.Ok) 363 { 364 if ((int)lines[0].StatusCode < 400) 365 { 366 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, lines[0].Line); 367 } 368 369 throw new SmtpException(lines[0].StatusCode, lines[0].Line, true); 370 } 371 string[] extensions = new string[lines.Length - 1]; 372 for (int i = 1; i < lines.Length; i++) 373 { 374 extensions[i - 1] = lines[i].Line; 375 } 376 return extensions; 377 } 378 EndSend(IAsyncResult result)379 internal static string[] EndSend(IAsyncResult result) 380 { 381 return CheckResponse(ReadLinesCommand.EndSend(result)); 382 } PrepareCommand(SmtpConnection conn, string domain)383 private static void PrepareCommand(SmtpConnection conn, string domain) 384 { 385 if (conn.IsStreamOpen) 386 { 387 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 388 } 389 390 conn.BufferBuilder.Append(SmtpCommands.EHello); 391 conn.BufferBuilder.Append(domain); 392 conn.BufferBuilder.Append(SmtpCommands.CRLF); 393 } 394 Send(SmtpConnection conn, string domain)395 internal static string[] Send(SmtpConnection conn, string domain) 396 { 397 PrepareCommand(conn, domain); 398 return CheckResponse(ReadLinesCommand.Send(conn)); 399 } 400 } 401 402 internal static class HelloCommand 403 { BeginSend(SmtpConnection conn, string domain, AsyncCallback callback, object state)404 internal static IAsyncResult BeginSend(SmtpConnection conn, string domain, AsyncCallback callback, object state) 405 { 406 PrepareCommand(conn, domain); 407 return CheckCommand.BeginSend(conn, callback, state); 408 } 409 CheckResponse(SmtpStatusCode statusCode, string serverResponse)410 private static void CheckResponse(SmtpStatusCode statusCode, string serverResponse) 411 { 412 switch (statusCode) 413 { 414 case SmtpStatusCode.Ok: 415 { 416 return; 417 } 418 default: 419 { 420 if ((int)statusCode < 400) 421 { 422 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, serverResponse); 423 } 424 425 throw new SmtpException(statusCode, serverResponse, true); 426 } 427 } 428 } 429 EndSend(IAsyncResult result)430 internal static void EndSend(IAsyncResult result) 431 { 432 string response; 433 SmtpStatusCode statusCode = (SmtpStatusCode)CheckCommand.EndSend(result, out response); 434 CheckResponse(statusCode, response); 435 } 436 PrepareCommand(SmtpConnection conn, string domain)437 private static void PrepareCommand(SmtpConnection conn, string domain) 438 { 439 if (conn.IsStreamOpen) 440 { 441 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 442 } 443 444 conn.BufferBuilder.Append(SmtpCommands.Hello); 445 conn.BufferBuilder.Append(domain); 446 conn.BufferBuilder.Append(SmtpCommands.CRLF); 447 } 448 Send(SmtpConnection conn, string domain)449 internal static void Send(SmtpConnection conn, string domain) 450 { 451 PrepareCommand(conn, domain); 452 string response; 453 SmtpStatusCode statusCode = CheckCommand.Send(conn, out response); 454 CheckResponse(statusCode, response); 455 } 456 } 457 458 internal static class StartTlsCommand 459 { BeginSend(SmtpConnection conn, AsyncCallback callback, object state)460 internal static IAsyncResult BeginSend(SmtpConnection conn, AsyncCallback callback, object state) 461 { 462 PrepareCommand(conn); 463 return CheckCommand.BeginSend(conn, callback, state); 464 } 465 CheckResponse(SmtpStatusCode statusCode, string response)466 private static void CheckResponse(SmtpStatusCode statusCode, string response) 467 { 468 switch (statusCode) 469 { 470 case SmtpStatusCode.ServiceReady: 471 { 472 return; 473 } 474 475 case SmtpStatusCode.ClientNotPermitted: 476 default: 477 { 478 if ((int)statusCode < 400) 479 { 480 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, response); 481 } 482 483 throw new SmtpException(statusCode, response, true); 484 } 485 } 486 } 487 EndSend(IAsyncResult result)488 internal static void EndSend(IAsyncResult result) 489 { 490 string response; 491 SmtpStatusCode statusCode = (SmtpStatusCode)CheckCommand.EndSend(result, out response); 492 CheckResponse(statusCode, response); 493 } 494 PrepareCommand(SmtpConnection conn)495 private static void PrepareCommand(SmtpConnection conn) 496 { 497 if (conn.IsStreamOpen) 498 { 499 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 500 } 501 502 conn.BufferBuilder.Append(SmtpCommands.StartTls); 503 conn.BufferBuilder.Append(SmtpCommands.CRLF); 504 } 505 Send(SmtpConnection conn)506 internal static void Send(SmtpConnection conn) 507 { 508 PrepareCommand(conn); 509 string response; 510 SmtpStatusCode statusCode = CheckCommand.Send(conn, out response); 511 CheckResponse(statusCode, response); 512 } 513 } 514 515 internal static class MailCommand 516 { BeginSend(SmtpConnection conn, byte[] command, MailAddress from, bool allowUnicode, AsyncCallback callback, object state)517 internal static IAsyncResult BeginSend(SmtpConnection conn, byte[] command, MailAddress from, 518 bool allowUnicode, AsyncCallback callback, object state) 519 { 520 PrepareCommand(conn, command, from, allowUnicode); 521 return CheckCommand.BeginSend(conn, callback, state); 522 } 523 CheckResponse(SmtpStatusCode statusCode, string response)524 private static void CheckResponse(SmtpStatusCode statusCode, string response) 525 { 526 switch (statusCode) 527 { 528 case SmtpStatusCode.Ok: 529 { 530 return; 531 } 532 case SmtpStatusCode.ExceededStorageAllocation: 533 case SmtpStatusCode.LocalErrorInProcessing: 534 case SmtpStatusCode.InsufficientStorage: 535 default: 536 { 537 if ((int)statusCode < 400) 538 { 539 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, response); 540 } 541 542 throw new SmtpException(statusCode, response, true); 543 } 544 } 545 } 546 EndSend(IAsyncResult result)547 internal static void EndSend(IAsyncResult result) 548 { 549 string response; 550 SmtpStatusCode statusCode = (SmtpStatusCode)CheckCommand.EndSend(result, out response); 551 CheckResponse(statusCode, response); 552 } 553 PrepareCommand(SmtpConnection conn, byte[] command, MailAddress from, bool allowUnicode)554 private static void PrepareCommand(SmtpConnection conn, byte[] command, MailAddress from, bool allowUnicode) 555 { 556 if (conn.IsStreamOpen) 557 { 558 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 559 } 560 conn.BufferBuilder.Append(command); 561 string fromString = from.GetSmtpAddress(allowUnicode); 562 conn.BufferBuilder.Append(fromString, allowUnicode); 563 if (allowUnicode) 564 { 565 conn.BufferBuilder.Append(" BODY=8BITMIME SMTPUTF8"); 566 } 567 conn.BufferBuilder.Append(SmtpCommands.CRLF); 568 } 569 Send(SmtpConnection conn, byte[] command, MailAddress from, bool allowUnicode)570 internal static void Send(SmtpConnection conn, byte[] command, MailAddress from, bool allowUnicode) 571 { 572 PrepareCommand(conn, command, from, allowUnicode); 573 string response; 574 SmtpStatusCode statusCode = CheckCommand.Send(conn, out response); 575 CheckResponse(statusCode, response); 576 } 577 } 578 579 internal static class RecipientCommand 580 { BeginSend(SmtpConnection conn, string to, AsyncCallback callback, object state)581 internal static IAsyncResult BeginSend(SmtpConnection conn, string to, AsyncCallback callback, object state) 582 { 583 PrepareCommand(conn, to); 584 return CheckCommand.BeginSend(conn, callback, state); 585 } 586 CheckResponse(SmtpStatusCode statusCode, string response)587 private static bool CheckResponse(SmtpStatusCode statusCode, string response) 588 { 589 switch (statusCode) 590 { 591 case SmtpStatusCode.Ok: 592 case SmtpStatusCode.UserNotLocalWillForward: 593 { 594 return true; 595 } 596 case SmtpStatusCode.MailboxUnavailable: 597 case SmtpStatusCode.UserNotLocalTryAlternatePath: 598 case SmtpStatusCode.ExceededStorageAllocation: 599 case SmtpStatusCode.MailboxNameNotAllowed: 600 case SmtpStatusCode.MailboxBusy: 601 case SmtpStatusCode.InsufficientStorage: 602 { 603 return false; 604 } 605 default: 606 { 607 if ((int)statusCode < 400) 608 { 609 throw new SmtpException(SR.net_webstatus_ServerProtocolViolation, response); 610 } 611 612 throw new SmtpException(statusCode, response, true); 613 } 614 } 615 } 616 EndSend(IAsyncResult result, out string response)617 internal static bool EndSend(IAsyncResult result, out string response) 618 { 619 SmtpStatusCode statusCode = (SmtpStatusCode)CheckCommand.EndSend(result, out response); 620 return CheckResponse(statusCode, response); 621 } 622 PrepareCommand(SmtpConnection conn, string to)623 private static void PrepareCommand(SmtpConnection conn, string to) 624 { 625 if (conn.IsStreamOpen) 626 { 627 throw new InvalidOperationException(SR.SmtpDataStreamOpen); 628 } 629 630 conn.BufferBuilder.Append(SmtpCommands.Recipient); 631 conn.BufferBuilder.Append(to, true); // Unicode validation was done prior 632 conn.BufferBuilder.Append(SmtpCommands.CRLF); 633 } 634 635 Send(SmtpConnection conn, string to, out string response)636 internal static bool Send(SmtpConnection conn, string to, out string response) 637 { 638 PrepareCommand(conn, to); 639 SmtpStatusCode statusCode = CheckCommand.Send(conn, out response); 640 return CheckResponse(statusCode, response); 641 } 642 } 643 644 645 internal static class SmtpCommands 646 { 647 internal static readonly byte[] Auth = Encoding.ASCII.GetBytes("AUTH "); 648 internal static readonly byte[] CRLF = Encoding.ASCII.GetBytes("\r\n"); 649 internal static readonly byte[] Data = Encoding.ASCII.GetBytes("DATA\r\n"); 650 internal static readonly byte[] DataStop = Encoding.ASCII.GetBytes("\r\n.\r\n"); 651 internal static readonly byte[] EHello = Encoding.ASCII.GetBytes("EHLO "); 652 internal static readonly byte[] Expand = Encoding.ASCII.GetBytes("EXPN "); 653 internal static readonly byte[] Hello = Encoding.ASCII.GetBytes("HELO "); 654 internal static readonly byte[] Help = Encoding.ASCII.GetBytes("HELP"); 655 internal static readonly byte[] Mail = Encoding.ASCII.GetBytes("MAIL FROM:"); 656 internal static readonly byte[] Noop = Encoding.ASCII.GetBytes("NOOP\r\n"); 657 internal static readonly byte[] Quit = Encoding.ASCII.GetBytes("QUIT\r\n"); 658 internal static readonly byte[] Recipient = Encoding.ASCII.GetBytes("RCPT TO:"); 659 internal static readonly byte[] Reset = Encoding.ASCII.GetBytes("RSET\r\n"); 660 internal static readonly byte[] Send = Encoding.ASCII.GetBytes("SEND FROM:"); 661 internal static readonly byte[] SendAndMail = Encoding.ASCII.GetBytes("SAML FROM:"); 662 internal static readonly byte[] SendOrMail = Encoding.ASCII.GetBytes("SOML FROM:"); 663 internal static readonly byte[] Turn = Encoding.ASCII.GetBytes("TURN\r\n"); 664 internal static readonly byte[] Verify = Encoding.ASCII.GetBytes("VRFY "); 665 internal static readonly byte[] StartTls = Encoding.ASCII.GetBytes("STARTTLS"); 666 } 667 668 669 670 internal struct LineInfo 671 { 672 private string _line; 673 private SmtpStatusCode _statusCode; 674 LineInfoSystem.Net.Mail.LineInfo675 internal LineInfo(SmtpStatusCode statusCode, string line) 676 { 677 _statusCode = statusCode; 678 _line = line; 679 } 680 internal string Line 681 { 682 get 683 { 684 return _line; 685 } 686 } 687 internal SmtpStatusCode StatusCode 688 { 689 get 690 { 691 return _statusCode; 692 } 693 } 694 } 695 } 696