· 7 years ago · Dec 13, 2018, 08:50 PM
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Net.Sockets;
6using System.Text;
7using System.Threading.Tasks;
8
9namespace Lab_SMTP
10{
11 public class SMTPClient
12 {
13 private bool _authRequest = false;
14 private Socket _socket;
15
16 public bool AuthRequest => _authRequest;
17
18 public async Task<bool> Connect(string serverDomain)
19 {
20 Socket s = GetSocket(serverDomain, 25);
21 if (s == null) return false;
22 _socket = s;
23 string hsResponse = await SendRequestWithResponse(_socket, "EHLO yandex.ru \r\n");
24 _authRequest = hsResponse.Contains("AUTH LOGIN");
25 return hsResponse.Contains("250");
26 }
27
28 public async Task<bool> SendAuth(string username, string password)
29 {
30 if (_socket == null || !_socket.Connected) return false;
31 string response = await SendRequestWithResponse(_socket, "AUTH LOGIN\r\n");
32 if (!response.Contains("334")) return false;
33 string encodedUsername = Convert.ToBase64String(Encoding.UTF8.GetBytes(username));
34 string encodedPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes(password));
35 response = await SendRequestWithResponse(_socket, $"{encodedUsername}\r\n");
36 if (!response.Contains("334")) return false;
37 response = await SendRequestWithResponse(_socket, $"{encodedPassword}\r\n");
38 return response.Contains("235");
39 }
40
41 public async Task<bool> SendFrom(string from) {
42 if (_socket == null || !_socket.Connected) return false;
43 string response = await SendRequestWithResponse(_socket, $"MAIL FROM:<{from}>\r\n");
44 return response.Contains("250");
45 }
46
47 public async Task<bool> SendTo(string to) {
48 if (_socket == null || !_socket.Connected) return false;
49 string response = await SendRequestWithResponse(_socket, $"RCPT TO:<{to}>\r\n");
50 return response.Contains("250");
51 }
52
53 public async Task<bool> SendData(string data) {
54 if (_socket == null || !_socket.Connected) return false;
55 string response = await SendRequestWithResponse(_socket, "DATA \r\n");
56 if (!response.Contains("354")) return false;
57 StringReader reader = new StringReader(data);
58 while (true)
59 {
60 string str = reader.ReadLine();
61 if (str == null) break;
62 await SendRequest(_socket, $"{str}\r\n");
63 }
64 response = await SendRequestWithResponse(_socket, ".\r\n");
65 return response.Contains("250");
66 }
67
68 public async Task<bool> SendQuit(string to) {
69 if (_socket == null || !_socket.Connected) return false;
70 string response = await SendRequestWithResponse(_socket, $"QUIT\r\n");
71 return response.Contains("250");
72 }
73
74 public static Socket GetSocket(string host, int port) {
75 Socket s = null;
76 var tempSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
77 try {
78 tempSocket.Connect(host, port);
79 }
80 catch (SocketException ex) {
81 return null;
82 }
83 if (tempSocket.Connected)
84 s = tempSocket;
85 return s;
86 }
87
88 public static Task<int> ReceiveAsync(Socket socket, byte[] buffer, int offset, int size, SocketFlags socketFlags) {
89 var tcs = new TaskCompletionSource<int>(socket);
90 socket.BeginReceive(buffer, offset, size, socketFlags, iar =>
91 {
92 var t = (TaskCompletionSource<int>)iar.AsyncState;
93 var s = (Socket)t.Task.AsyncState;
94 try { t.TrySetResult(s.EndReceive(iar)); }
95 catch (Exception exc) { t.TrySetException(exc); }
96 }, tcs);
97 return tcs.Task;
98 }
99
100 public static async Task SendRequest(Socket socket, string request) {
101 Byte[] bytesSent = Encoding.Default.GetBytes(request);
102 socket.Send(bytesSent, bytesSent.Length, 0);
103 await Task.Delay(100);
104 }
105
106 public static async Task<string> SendRequestWithResponse(Socket socket, string request) {
107 return await SendRequestWithResponse(socket, socket, request);
108 }
109
110 public static async Task<string> SendRequestWithResponse(Socket socketToSend, Socket socketToRecieve, string request) {
111 Byte[] bytesReceived = new Byte[256];
112 int bytes;
113 string response = "";
114
115 await SendRequest(socketToSend, request);
116
117 do {
118 bytes = await ReceiveAsync(socketToRecieve, bytesReceived, 0, bytesReceived.Length, 0);
119 response = response + Encoding.Default.GetString(bytesReceived, 0, bytes);
120 if (bytes < 255) break;
121 }
122 while (bytes > 0);
123 return response;
124 }
125 }
126}