powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / [CLR] Получение почты через IMAP
4 сообщений из 4, страница 1 из 1
[CLR] Получение почты через IMAP
    #39958708
tunknown
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Считая SQL Server сервером приложений, программируемых на Transact-SQL, по мотивам существующей сборки написал ещё одну. Предполагаемое использование- получать письма по IMAP из Входящих в таблицу и стирать, держа ящик пустым. Поэтому всего две функции- получения идентификаторов и заголовков писем из Входящих, получение по списку идентификаторов в виде .eml файлов и процедура стирания писем по списку. Возможно, это не совсем .eml файлы, т.к. обработки содержимого не ведётся, т.е. это просто дамп IMAP команды FETCH. Обработки ошибок в C# нет, т.к. предполагается, что все ошибки должны дойти и обработаться в SQL. Собиралось под Visual C# 2008 Express для .NET Framework 3.5. Под надгрузкой не эксплуатировалась. На разных IMAP серверах и почтовых клиентах не тестировалась.

Сборка
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
// TUnknown 2020 license cc0/public domain
// https://en.wikipedia.org/wiki/Creative_Commons_license#Zero_/_public_domain

//https://tools.ietf.org/html/rfc3501
//https://tools.ietf.org/html/rfc2822
//https://tools.ietf.org/html/rfc2683
//https://tools.ietf.org/html/rfc5321#section-4.5.3
//http://regexstorm.net/reference		-- c# compatible

using System;
using Microsoft.SqlServer.Server;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Threading;
using System.Data.SqlTypes;
using System.Net.Mail;

public class IMAP4CLR
{
	const UInt32 TimeOut = 500;
	const int CRLFOverhead = 1000 ;
	const int ResponseLength = 1000;

	private static bool GetCommandResult( ref TcpClient IMAP , ref StreamWriter sw , string CMDID, ref byte[] data)
	{
		data = null;
		data = new byte[IMAP.ReceiveBufferSize]; // commands that return no more than one buffer must come here

		bool Completed = false, OKFound = false;
		Match mFields;
		DateTime start = System.DateTime.Now;
		string Res = "";
		int readed, ptr = 0, remain = data.Length;

		do
		{
			readed = IMAP.GetStream().Read(data, ptr, remain);
			ptr = ptr + readed;
			remain = remain - readed;

			if (0 < readed) start = System.DateTime.Now;
			Res = Encoding.ASCII.GetString(data).TrimEnd('\0');

			if (!Completed)
			{
				mFields = Regex.Match(Res, CMDID + " ([OBN][KAO][D]{0,1}) ([\\s\\S]+)", RegexOptions.IgnoreCase);
				Completed = mFields.Success;
				if (Completed)
				{
					OKFound = (mFields.Groups[1].ToString() == "OK");
					if (!OKFound) throw new Exception(Res);
				}
			}
			if (IMAP.Available == 0 && !Completed) Thread.Sleep(20);
		} while (!Completed && (System.DateTime.Now - start).TotalMilliseconds < TimeOut);

		return OKFound;
	}

	private static bool ProtocolCommand(ref TcpClient IMAP, ref StreamWriter sw, string Command, ref byte[] data)
	{
		bool OKFound = false;
		if (string.IsNullOrEmpty(Command)) return OKFound;

		string CMDID = Guid.NewGuid().ToString();

		//try
		{
			// can send NOOP before any command to workaround system messages from server if exists

			sw.WriteLine(CMDID + " " + Command);
#if DEBUG
				//string FN = "C:\\TEMP\\" + System.DateTime.Now.ToString("yyyyMMdd_HHmmssfff") + "_" + CMDID;
				//File.WriteAllText(FN + ".cm", CMDID + " " + Command);
#endif
			OKFound = GetCommandResult(ref IMAP, ref sw, CMDID, ref data);
#if DEBUG
				//File.WriteAllBytes(FN + ".rs", data);
#endif
		}
		/*catch (Exception e)
		{
			Res = e.Message;
		}*/
		return OKFound;
	}

	private static string ReadTillEnd(ref TcpClient IMAP )
	{
		string Res = "";
		if (0 < IMAP.Available)
		{
			DateTime start = System.DateTime.Now;
			byte[] Buffer = new byte[IMAP.Available];
			try
			{
				while (0 < IMAP.Available && (System.DateTime.Now - start).TotalMilliseconds < TimeOut)
					if (0 < IMAP.GetStream().Read(Buffer, 0, Buffer.Length))
					{
						start = System.DateTime.Now;
						Res = Res + Encoding.ASCII.GetString(Buffer, 0, Buffer.Length).TrimEnd('\0');
					}
					else
						Thread.Sleep(20);
			}
			finally
			{
				Buffer = null;
			}
		}
		return Res;
	}

	private static bool FetchBody(ref TcpClient IMAP, ref StreamWriter sw, int UID, ref MemoryStream MS)
	{
		bool Fetched = false;
		DateTime start = System.DateTime.Now;
		string Res, CMDID = Guid.NewGuid().ToString();
		int readed = 0, BodyLength = 0, remain, BeginMessage = 0, Avail, Pos;
		Match match;

		MS = null;

		byte[] Buf = new byte[IMAP.ReceiveBufferSize];
		try
		{
			sw.WriteLine(CMDID + " UID FETCH " + UID + " BODY.PEEK[]");
			do
			{
				Res = "";
				if (BodyLength == 0) // first step to detect mail length
				{
					readed = IMAP.GetStream().Read(Buf, 0, Buf.Length); // wait for FETCH only response, not a other nonreaded server response
					if (0 < readed) start = System.DateTime.Now;

					if (100 < readed) remain = 100; else remain = readed;

					//code page has no sense because of command response starts by ASCII
					match = Regex.Match(Encoding.ASCII.GetString(Buf, 0, remain).TrimEnd('\0'), "[*] \\d+ FETCH [(]BODY[[]] {(\\d+)}[\\s]+(\\S+)", RegexOptions.IgnoreCase); // get mail size
					if (match.Success)
						if (Int32.TryParse(match.Groups[1].ToString(), out BodyLength))
							if (0 < BodyLength)
							{
								BodyLength = BodyLength + CRLFOverhead; // reserve for difference between {Size} and real IMAP protocol fetched data

								BeginMessage = match.Groups[2].Index;

								if (readed - BeginMessage < BodyLength)
									remain = readed - BeginMessage;
								else
								{
									remain = BodyLength;
									Res = ReadTillEnd(ref IMAP);// read till end unnecessary data
								}
								MS = new MemoryStream(BodyLength); // instead multiple small expand do one large

								MS.Write(Buf, BeginMessage, remain);
							}
				}
				else
				{
					Avail = (IMAP.Available < Buf.Length ? IMAP.Available : Buf.Length);
					if (0 < Avail)
					{
						readed = IMAP.GetStream().Read(Buf, 0, Avail);

						if (0 < readed)
						{
							start = System.DateTime.Now;
							if (MS.Capacity < MS.Position + readed) MS.SetLength(MS.Position + readed);
							MS.Write(Buf, 0, readed);

							Pos = (int)MS.Position;
							try
							{
								MS.Position = MS.Position - ResponseLength;
								readed = MS.Read(Buf, 0, ResponseLength); // read back to obtain non breaked by readed beffer size end of buffer
							}
							finally
							{
								MS.Position = Pos;
							}
						}
					}
					else
						readed = 0;
				}

				if (0 < readed)
				{
					if (readed < ResponseLength)
					{
						Pos = 0;
						Avail = readed;
					}
					else
					{
						Pos = readed - ResponseLength;
						Avail = ResponseLength;
					}
					Res = Encoding.ASCII.GetString(Buf, Pos, Avail);

					if (Res != "")
					{
						match = Regex.Match(Res, CMDID + " ([OBN][KAO][D]{0,1}) [\\s\\S]+", RegexOptions.IgnoreCase);
						if (match.Success)
							if (match.Groups[1].ToString() != "OK")
								throw new Exception(match.ToString());
							else
							{
								match = Regex.Match(Res, " UID \\d+[)][\\n\\r]{1,2}" + CMDID, RegexOptions.IgnoreCase); // not enought get OK because of fetching for not existed uid returns OK too
								Fetched = match.Success;
								if (Fetched) MS.SetLength(MS.Position - ResponseLength + match.Index); // shorten mail buffer- trim IMAP ptotocol response string
								ReadTillEnd(ref IMAP );
							}
					}
				}

				if (IMAP.Available == 0 && !Fetched) Thread.Sleep(20);
			} while (!Fetched && (System.DateTime.Now - start).TotalMilliseconds < TimeOut); // Timeout after successful reading
		}
		finally
		{
			Buf = null;
		}

		return Fetched;
	}

	private static bool Autenticate(ref TcpClient IMAP , ref StreamWriter sw/*thread-safe*/ , string Server, int Port, string User, string Password, bool IsReadOnly )
	{
		bool Result = false;

		IMAP = new TcpClient(Server, Port); // IMAP.Connect not needed
		sw = new StreamWriter(IMAP.GetStream());
		sw.AutoFlush = true;

		try
		{
			byte[] data = null;
			try
			{
				if (!GetCommandResult(ref IMAP, ref sw, "[*]", ref data)) throw new Exception(Encoding.ASCII.GetString(data, 0, data.Length).TrimEnd('\0'));
			}
			finally
			{
				data = null;
			}

			try
			{
				if (!ProtocolCommand(ref IMAP, ref sw, "LOGIN " + User + " " + Password, ref data)) throw new Exception(Encoding.ASCII.GetString(data, 0, data.Length).TrimEnd('\0'));
			}
			finally
			{
				data = null;
			}

			try
			{
				Result = ProtocolCommand(ref IMAP, ref sw, (IsReadOnly ? "EXAMINE" : "SELECT") + " INBOX", ref data);
				if (!Result) throw new Exception(Encoding.ASCII.GetString(data, 0, data.Length).TrimEnd('\0'));
			}
			finally
			{
				data = null;
			}
		}
		catch
		{
			Disconnect(ref IMAP, ref sw);
		}

		return Result;
	}

	private static void Disconnect(ref TcpClient IMAP , ref StreamWriter sw )
	{
		byte[] data = null;
		try
		{
			ProtocolCommand(ref IMAP, ref sw, "LOGOUT", ref data);
		}
		finally
		{
			data = null;
			if (IMAP.Connected) IMAP.Close();

			sw = null;
			IMAP = null;
		}
	}

	private static string Decode(string str)
	{
		if (8 < str.Length)
		{
			string part, chr;
			foreach (Match enc in Regex.Matches(str, "=[?][a-z0-9_$.:-]+[?]([BQ])[?][a-z0-9+/=]+[?]=[\\s]{0,1}", RegexOptions.IgnoreCase)) // according to https://tools.ietf.org/html/rfc1342
			{
				part = enc.ToString();
				chr = enc.Groups[1].ToString();
				str = str.Replace(part, Attachment.CreateAttachmentFromString("", ((chr == "b" || chr == "q") ? part.Replace("?b?", "?B?").Replace("?q?", "?Q?") : part).TrimEnd(null)).Name); // CreateAttachmentFromString wants strict letter case
			}
		}
		return str;
	}

	private static bool GetMailFields( ref byte[] data, ref string MessageId, ref Nullable<DateTime> Date, ref string From, ref string To, ref string Cc, ref string Subject, ref string Importance)
	{
		string Res = Encoding.ASCII.GetString(data, 0, data.Length).TrimEnd('\0');

		Res = Regex.Replace(Res, "\\r\\n(\\s)", "$1"); // unfolding due to https://tools.ietf.org/html/rfc2822#section-2.2.3

		bool MailPresent = Regex.Match(Res, "[\\r\\n].+:\\s.+[\\r\\n]", RegexOptions.IgnoreCase ).Success; // detect if OK present but UID not exist
		if (MailPresent)
		{
			Match mFields = Regex.Match(Res, "[\\r\\n]Date:\\s([0-9a-z ,:+-]+)(?: [(][A-Z]{2,6}[)]){0,1}[\\r\\n]", RegexOptions.IgnoreCase /*| RegexOptions.Multiline*/);
			if (mFields.Success)
			{
				DateTime dt;
				if (DateTime.TryParse(mFields.Groups[1].ToString(), out dt)) // ignore https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
					try
					{
						Date = (Nullable<DateTime>)dt;
					}
					catch
					{
						Date = null/*DateTime.Now*/; // System.Data.SqlTypes.SqlTypeException DateTime out of bound
					}
				else
					Date = null;
			}
			else
				Date = null;

			mFields = Regex.Match(Res, "[\\r\\n]Message-ID:\\s<([^\\r\\n]+)>[\\r\\n]", RegexOptions.IgnoreCase);
			if (mFields.Success) MessageId = mFields.Groups[1].ToString(); else MessageId = null;

			mFields = Regex.Match(Res, "[\\r\\n]From:\\s([^\\r\\n]+)[\\r\\n]", RegexOptions.IgnoreCase);
			if (mFields.Success) From = Decode(mFields.Groups[1].ToString()); else From = null;

			mFields = Regex.Match(Res, "[\\r\\n]To:\\s([^\\r\\n]+)[\\r\\n]", RegexOptions.IgnoreCase);
			if (mFields.Success) To = Decode(mFields.Groups[1].ToString()); else To = null;

			mFields = Regex.Match(Res, "[\\r\\n]Cc:\\s([^\\r\\n]+)[\\r\\n]", RegexOptions.IgnoreCase);
			if (mFields.Success) Cc = Decode(mFields.Groups[1].ToString()); else Cc = null;

			mFields = Regex.Match(Res, "[\\r\\n]Subject:\\s([^\\r\\n]+)[\\r\\n]", RegexOptions.IgnoreCase);
			if (mFields.Success) Subject = Decode(mFields.Groups[1].ToString()); else Subject = null;

			mFields = Regex.Match(Res, "[\\r\\n]Importance:\\s([^\\r\\n]{3,6})[\\r\\n]", RegexOptions.IgnoreCase);
			if (mFields.Success) Importance = mFields.Groups[1].ToString(); else Importance = null;
		}
		return MailPresent;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	[SqlFunction(FillRowMethodName = "FillList", TableDefinition = "UID int , MessageId nvarchar ( 1000 ) , Date datetime , From nvarchar ( 256 ) , To nvarchar ( 4000 ) , Cc nvarchar ( 4000 ) , Subject nvarchar ( 4000 ) , Importance nvarchar ( 6 )")]
	public static IEnumerable GetEMailsAvailable(string sServer, int iPort, string sUser, string sPassword, DateTime dtMoment)
	{
		TcpClient IMAP = null ;
		StreamWriter sw = null;

		UInt16 Records = 0;
		ArrayList rows = new ArrayList();

		if (Autenticate(ref IMAP, ref sw, sServer, iPort, sUser, sPassword, true))
			try
			{
				string cmd = "UID SEARCH 1:* UNDELETED", MessageId = "", From = "", To = "", Cc = "", Subject = "", Importance = "";
				byte[] data = null;


				if (dtMoment != null) cmd = cmd + " SINCE " + dtMoment.ToString("dd-MMM-yyyy", new System.Globalization.CultureInfo("en-US"));
				if (ProtocolCommand(ref IMAP, ref sw, cmd, ref data))
				{
					Int32 UID;
					Nullable<DateTime> Date = null;
					MatchCollection mUIDs;

					try
					{
						mUIDs = Regex.Matches(Encoding.ASCII.GetString(data, 0, data.Length).TrimEnd('\0'), "([ ]+\\d+)", RegexOptions.IgnoreCase);
					}
					finally
					{
						data = null;
					}

					foreach (Match match in mUIDs)
						foreach (Capture capture in match.Captures)
							if (Int32.TryParse(capture.Value.ToString(), out UID))
								try
								{
									data = null;
									if (ProtocolCommand(ref IMAP, ref sw, "UID FETCH " + UID + " body.peek[header.fields (message-id date from to cc subject importance)]", ref data))
										if (GetMailFields( ref data, ref MessageId, ref Date, ref From, ref To, ref Cc, ref Subject, ref Importance))
										{
											rows.Add(new object[] { UID, MessageId, Date, From, To, Cc, Subject, Importance });
											Records++;
										}
								}
								finally
								{
									data = null;
								}
				}
			}
			/*catch
			{
				if (Records == 0) throw; // hide error to show obtained records
			}*/
			finally
			{
				Disconnect(ref IMAP, ref sw);
			}
		return rows;
	}

	private static void FillList(Object row, out int UID, out string MessageId, out Nullable<DateTime> Date, out string From, out string To, out string Cc, out string Subject, out string Importance)
	{
		UID = (int)((object[])row)[0];
		MessageId = (string)((object[])row)[1];
		Date = (Nullable<DateTime>)((object[])row)[2];
		From = (string)((object[])row)[3];
		To = (string)((object[])row)[4];
		Cc = (string)((object[])row)[5];
		Subject = (string)((object[])row)[6];
		Importance = (string)((object[])row)[7];
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	[SqlFunction(FillRowMethodName = "FillMessages", TableDefinition = "UID int , MessageId nvarchar ( 1000 ) , Date datetime , From nvarchar ( 256 ) , To nvarchar ( 4000 ) , Cc nvarchar ( 4000 ) , Subject nvarchar ( 4000 ) , Importance nvarchar ( 6 ) , Body varbinary ( max )")]
	public static IEnumerable GetEMails(string sServer, int iPort, string sUser, string sPassword, [SqlFacet(MaxSize = 4000)]string sUIDs)
	{
		TcpClient IMAP = null;
		StreamWriter sw = null;

		ArrayList rows = new ArrayList();

		if (1 < sUIDs.Length)
			if (Autenticate(ref IMAP, ref sw, sServer, iPort, sUser, sPassword, true))
			{
				UInt16 Records = 0;

				try
				{
					Int32 UID;
					string MessageId = "", From = "", To = "", Cc = "", Subject = "", Importance = "";
					Nullable<DateTime> Date = null;
					byte[] body;
					MemoryStream MS;

					foreach (string sUID in sUIDs.Split(new char[] { sUIDs[0] }, System.StringSplitOptions.RemoveEmptyEntries))
						if (Int32.TryParse(sUID, out UID))
						{
							body = null;
							if (ProtocolCommand(ref IMAP, ref sw, "UID FETCH " + UID + " body.peek[header.fields (message-id date from to cc subject importance)]", ref body))
								if (GetMailFields( ref body, ref MessageId, ref Date, ref From, ref To, ref Cc, ref Subject, ref Importance))
									try
									{
										MS = null;
										if (FetchBody(ref IMAP, ref sw, UID, ref MS))
										{
											rows.Add(new object[] { UID, MessageId, Date, From, To, Cc, Subject, Importance, MS });
											Records++;
										}
									}
									finally
									{
										MS = null;
										body = null;
									}
						}
				}
				/*catch
				{
					if (Records == 0) throw; //hide error to show obtained records
				}*/
				finally
				{
					Disconnect(ref IMAP, ref sw);
				}
			}
		return rows;
	}

	private static void FillMessages(Object row, out int UID, out string MessageId, out Nullable<DateTime> Date, out string From, out string To, out string Cc, out string Subject, out string Importance, [SqlFacet(MaxSize = -1)]out SqlBytes Body)
	{
		UID = (int)((object[])row)[0];
		MessageId = (string)((object[])row)[1];
		Date = (Nullable<DateTime>)((object[])row)[2];
		From = (string)((object[])row)[3];
		To = (string)((object[])row)[4];
		Cc = (string)((object[])row)[5];
		Subject = (string)((object[])row)[6];
		Importance = (string)((object[])row)[7];
		Body = new SqlBytes((MemoryStream)((object[])row)[8]);
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	[Microsoft.SqlServer.Server.SqlProcedure]
	public static void RemoveEMails(string sServer, int iPort, string sUser, string sPassword, [SqlFacet(MaxSize = 4000)]string sUIDs)
	{
		TcpClient IMAP = null;
		StreamWriter sw = null;

		if (1 < sUIDs.Length)
			if (Autenticate(ref IMAP, ref sw, sServer, iPort, sUser, sPassword, false))
				try
				{
					UInt32 UID;
					bool Closing = false;
					byte[] body;

					foreach (string sUID in sUIDs.Split(new char[] { sUIDs[0] }, System.StringSplitOptions.RemoveEmptyEntries))
						if (UInt32.TryParse(sUID, out UID))
							try
							{
								body = null;
								if (ProtocolCommand(ref IMAP, ref sw, "UID STORE " + UID + " +FLAGS.SILENT (\\Deleted)", ref body)) Closing = true;
							}
							finally
							{
								body = null;
							}

					if (Closing)
						try
						{
							body = null;
							ProtocolCommand(ref IMAP, ref sw, "CLOSE", ref body);
						}
						finally
						{
							body = null;
						}
				}
				finally
				{
					Disconnect(ref IMAP, ref sw);
				}
		return;
	}
}


SQL регистрация
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
EXEC	sp_configure	'clr enabled',	1
RECONFIGURE
go
----------
ALTER	DATABASE	[your_db_name_here]	SET	TRUSTWORTHY	ON
GO
----------
CREATE	ASSEMBLY	IMAP4CLR
FROM	'C:\Program Files\Microsoft SQL Server\MSSQL12.SQLEXPRESS\MSSQL\Binn\imap4clr.dll'
WITH	PERMISSION_SET=	UNSAFE
GO
GO
----------------------------------------------------------------------------------------------------
go
create	FUNCTION	dbo.GetEMailsAvailable
(	@sServer	nvarchar ( 256 )
	,@iPort		int
	,@sUser		nvarchar ( 256 )
	,@sPassword	nvarchar ( 256 )
	,@dtStart	date=	null
)
RETURNS	TABLE
(	UID		int
	,MessageId	nvarchar ( 1000 )
	,Date		datetime
	,[From]		nvarchar ( 256 )
	,[To]		nvarchar ( 4000 )
	,Cc		nvarchar ( 4000 )
	,Subject	nvarchar ( 4000 )
	,Importance	nvarchar ( 6 )
)
EXTERNAL	NAME	IMAP4CLR.IMAP4CLR.GetEMailsAvailable
GO
----------------------------------------------------------------------------------------------------
go
create	FUNCTION	dbo.GetEMails
(	@sServer	nvarchar ( 256 )
	,@iPort		int
	,@sUser		nvarchar ( 256 )
	,@sPassword	nvarchar ( 256 )
	,@sUIDs		nvarchar ( 4000 )
)
RETURNS	TABLE
(	UID		int
	,MessageId	nvarchar ( 1000 )
	,Date		datetime
	,[From]		nvarchar ( 256 )
	,[To]		nvarchar ( 4000 )
	,Cc		nvarchar ( 4000 )
	,Subject	nvarchar ( 4000 )
	,Importance	nvarchar ( 6 )
	,Body		varbinary ( max ) )
EXTERNAL	NAME	IMAP4CLR.IMAP4CLR.GetEMails
GO
----------------------------------------------------------------------------------------------------
go
create	proc	dbo.RemoveEMails
(	@sServer	nvarchar ( 255 )
	,@iPort		int
	,@sUser		nvarchar ( 255 )
	,@sPassword	nvarchar ( 255 )
	,@sUIDs		nvarchar ( 4000 )
)
as
EXTERNAL	NAME	IMAP4CLR.IMAP4CLR.RemoveEMails



На C# не имею опыта, попрактиковался на этом коде, поэтому может быть написано неоптимально.
...
Рейтинг: 0 / 0
[CLR] Получение почты через IMAP
    #39958727
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tunknown,

в чем смысл
Код: sql
1.
2.
3.
4.
finally
{
data = null;
}



если GC и так справится?
...
Рейтинг: 0 / 0
[CLR] Получение почты через IMAP
    #39958734
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff
tunknown,

в чем смысл
Код: sql
1.
2.
3.
4.
finally
{
data = null;
}




если GC и так справится?

Нет в этом никакого смысла - обнуляется локальная ссылка на стеке. А содержимое массива всё равно в куче, и на него эта операция никакого влияния не оказывает, оно там так и продолжает лежать. Если оно не слишком объёмное, и не попало в LOH, то да, в скором времени будет подобрано GC.
...
Рейтинг: 0 / 0
[CLR] Получение почты через IMAP
    #39958815
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tunknown,

ищите эксплуатационных проблем - используйте unsafe сборки, я же рекомендую написать отдельное приложение. В случае работы с почтой нет никакого смысла внедрять этот процесс в пространство сервера.
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / [CLR] Получение почты через IMAP
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]