Skip to content

Commit 04a0059

Browse files
committed
IMAP: Получение, работа с ящиками
1 parent f8c4046 commit 04a0059

File tree

10 files changed

+605
-50
lines changed

10 files changed

+605
-50
lines changed

MailComponent.sln

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,34 @@ Global
2626
{9A739C32-D551-43B0-920A-D9C53367BC38}.Release|Any CPU.ActiveCfg = Release|Any CPU
2727
{9A739C32-D551-43B0-920A-D9C53367BC38}.Release|Any CPU.Build.0 = Release|Any CPU
2828
EndGlobalSection
29+
GlobalSection(MonoDevelopProperties) = preSolution
30+
Policies = $0
31+
$0.TextStylePolicy = $1
32+
$1.inheritsSet = VisualStudio
33+
$1.scope = text/plain
34+
$1.FileWidth = 120
35+
$1.TabsToSpaces = False
36+
$1.inheritsScope = text/plain
37+
$0.CSharpFormattingPolicy = $2
38+
$2.IndentSwitchSection = True
39+
$2.NewLinesForBracesInProperties = True
40+
$2.NewLinesForBracesInAccessors = True
41+
$2.NewLinesForBracesInAnonymousMethods = True
42+
$2.NewLinesForBracesInControlBlocks = True
43+
$2.NewLinesForBracesInAnonymousTypes = True
44+
$2.NewLinesForBracesInObjectCollectionArrayInitializers = True
45+
$2.NewLinesForBracesInLambdaExpressionBody = True
46+
$2.NewLineForElse = True
47+
$2.NewLineForCatch = True
48+
$2.NewLineForFinally = True
49+
$2.NewLineForMembersInObjectInit = True
50+
$2.NewLineForMembersInAnonymousTypes = True
51+
$2.NewLineForClausesInQuery = True
52+
$2.SpacingAfterMethodDeclarationName = False
53+
$2.SpaceAfterMethodCallName = False
54+
$2.SpaceBeforeOpenSquareBracket = False
55+
$2.inheritsSet = Mono
56+
$2.inheritsScope = text/x-csharp
57+
$2.scope = text/x-csharp
58+
EndGlobalSection
2959
EndGlobal

MailComponent/Mail/ImapReceiver.cs

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
using System;
8+
using ScriptEngine.Machine;
9+
using MailKit.Net.Imap;
10+
using MailKit;
11+
using MailKit.Search;
12+
using System.Linq;
13+
using System.Collections.Generic;
14+
using ScriptEngine.HostedScript.Library;
15+
16+
namespace OneScript.InternetMail
17+
{
18+
public class ImapReceiver : IMailReceiver, IDisposable
19+
{
20+
private readonly ImapClient client = new ImapClient();
21+
private InternetMailProfile _profile;
22+
private string _currentMailbox = "";
23+
private string _mailboxDelimiterCharacter = "/";
24+
private IMailFolder _currentFolder = null;
25+
26+
public void SetCurrentMailbox(string mailbox)
27+
{
28+
_currentMailbox = mailbox;
29+
UpdateCurrentFolder();
30+
}
31+
32+
public void SetDelimiterCharacter(string delimiter)
33+
{
34+
_mailboxDelimiterCharacter = delimiter;
35+
UpdateCurrentFolder();
36+
}
37+
38+
private void CloseCurrentFolder()
39+
{
40+
if (_currentFolder != null)
41+
{
42+
_currentFolder.Close(false);
43+
_currentFolder = null;
44+
}
45+
}
46+
47+
private void UpdateCurrentFolder()
48+
{
49+
CloseCurrentFolder();
50+
51+
if (string.IsNullOrEmpty(_currentMailbox))
52+
_currentFolder = client.Inbox;
53+
else
54+
_currentFolder = client.GetFolder(_currentMailbox);
55+
56+
_currentFolder.Open(FolderAccess.ReadWrite);
57+
}
58+
59+
public void ClearDeletedMessages()
60+
{
61+
_currentFolder.Expunge();
62+
}
63+
64+
public void CreateMailbox(string name)
65+
{
66+
_currentFolder.Create(name, true);
67+
}
68+
69+
public void DeleteMailbox(string name)
70+
{
71+
var folderToDelete = client.GetFolder(name);
72+
folderToDelete.Delete();
73+
}
74+
75+
// Альмаматерь добавляет префикс к порядковым номерам. Сделаем же так и мы.
76+
private static string ID_PREFIX = "imap-";
77+
78+
private string UniqueIdToInternalId(UniqueId id)
79+
{
80+
return string.Format("{0}{1}", ID_PREFIX, id.Id);
81+
}
82+
83+
private UniqueId InternalIdToUniqueId(string id)
84+
{
85+
if (id.StartsWith(ID_PREFIX, StringComparison.Ordinal))
86+
return new UniqueId(0, UInt32.Parse(id.Substring(ID_PREFIX.Length)));
87+
88+
return UniqueId.Invalid;
89+
}
90+
91+
private IList<UniqueId> GetMessagesList(ArrayImpl ids)
92+
{
93+
var result = new List<UniqueId>();
94+
if (ids == null)
95+
{
96+
result.AddRange(_currentFolder
97+
.Fetch(0, -1, MessageSummaryItems.UniqueId)
98+
.Select((IMessageSummary arg) => arg.UniqueId));
99+
}
100+
else
101+
{
102+
// Получим список идентификаторов писем с учётом возможных вариантов входящих данных
103+
var Uids = new List<UniqueId>();
104+
foreach (var data in ids)
105+
{
106+
if (data.DataType == DataType.String)
107+
{
108+
// Идентификатор сообщения
109+
Uids.Add(InternalIdToUniqueId(data.AsString()));
110+
}
111+
else if (data.DataType == DataType.Number)
112+
{
113+
// Передан порядковый номер в текущем ящике
114+
var index = (int)data.AsNumber();
115+
var letterData = _currentFolder.Fetch(index, index, MessageSummaryItems.UniqueId);
116+
foreach (var oneData in letterData)
117+
Uids.Add(oneData.UniqueId);
118+
}
119+
else if (data is InternetMailMessage)
120+
{
121+
// ИнтернетПочтовоеСообщение
122+
foreach (var id in (data as InternetMailMessage).Uid)
123+
{
124+
Uids.Add(InternalIdToUniqueId(id.AsString()));
125+
}
126+
}
127+
else if (data is ArrayImpl)
128+
{
129+
// Массив идентификаторов
130+
foreach (var id in (data as ArrayImpl))
131+
{
132+
Uids.Add(InternalIdToUniqueId(id.AsString()));
133+
}
134+
}
135+
}
136+
result.AddRange(Uids);
137+
}
138+
139+
return result;
140+
}
141+
142+
public void DeleteMessages(ArrayImpl dataToDelete)
143+
{
144+
var messages = GetMessagesList(dataToDelete);
145+
_currentFolder.AddFlags(messages, MessageFlags.Deleted, silent: true);
146+
}
147+
148+
public ArrayImpl Get(bool deleteMessages, ArrayImpl ids, bool markAsRead)
149+
{
150+
var result = new ArrayImpl();
151+
var processedMessages = GetMessagesList(ids);
152+
153+
foreach (var i in processedMessages)
154+
{
155+
var mimeMessage = _currentFolder.GetMessage(i);
156+
var iMessage = new InternetMailMessage(mimeMessage, UniqueIdToInternalId(i));
157+
result.Add(iMessage);
158+
}
159+
160+
if (processedMessages.Count > 0)
161+
{
162+
if (deleteMessages)
163+
{
164+
_currentFolder.AddFlags(processedMessages, MessageFlags.Deleted, silent: true);
165+
}
166+
else if (markAsRead)
167+
{
168+
_currentFolder.AddFlags(processedMessages, MessageFlags.Seen, silent: true);
169+
}
170+
}
171+
172+
return result;
173+
}
174+
175+
private IList<UniqueId> SearchMessages(StructureImpl filter)
176+
{
177+
var imapFilter = new InternetMailImapSearchFilter(filter);
178+
var query = imapFilter.CreateSearchQuery();
179+
return _currentFolder.Search(query);
180+
}
181+
182+
public ArrayImpl GetHeaders(StructureImpl filter)
183+
{
184+
185+
var result = new ArrayImpl();
186+
187+
var dataToFetch = MessageSummaryItems.Envelope
188+
| MessageSummaryItems.Flags
189+
| MessageSummaryItems.UniqueId
190+
| MessageSummaryItems.InternalDate
191+
| MessageSummaryItems.MessageSize
192+
;
193+
194+
IList<IMessageSummary> allHeaders;
195+
196+
if (filter == null)
197+
allHeaders = _currentFolder.Fetch(0, -1, dataToFetch);
198+
else
199+
{
200+
var ids = SearchMessages(filter);
201+
if (ids.Count == 0)
202+
return result;
203+
204+
allHeaders = _currentFolder.Fetch(ids, dataToFetch);
205+
}
206+
207+
foreach (var headers in allHeaders)
208+
{
209+
var mailMessage = new InternetMailMessage(headers);
210+
211+
mailMessage.Uid.Add(ValueFactory.Create(UniqueIdToInternalId(headers.UniqueId)));
212+
result.Add(mailMessage);
213+
}
214+
215+
return result;
216+
}
217+
218+
public ArrayImpl GetIdentifiers(ArrayImpl identifiers, StructureImpl filter)
219+
{
220+
var result = new ArrayImpl();
221+
var allUids = GetHeaders(filter);
222+
223+
foreach (var ivHeaderWithUid in allUids)
224+
{
225+
var headerWithUid = ivHeaderWithUid as InternetMailMessage;
226+
var Id = headerWithUid.Uid.Get(0);
227+
228+
if (identifiers == null || identifiers.Find(Id).DataType != DataType.Undefined)
229+
result.Add(Id);
230+
}
231+
232+
return result;
233+
}
234+
235+
public ArrayImpl GetMailboxes(bool subscribedOnly)
236+
{
237+
var result = new ArrayImpl();
238+
239+
var allFolders = client.GetFolders(null, subscribedOnly);
240+
foreach (var folder in allFolders)
241+
{
242+
result.Add(ValueFactory.Create(folder.FullName));
243+
}
244+
245+
return result;
246+
}
247+
248+
public ArrayImpl GetMailboxes()
249+
{
250+
return GetMailboxes(subscribedOnly: false);
251+
}
252+
253+
public ArrayImpl GetMailboxesBySubscription()
254+
{
255+
return GetMailboxes(subscribedOnly: true);
256+
}
257+
258+
public int GetMessageCount()
259+
{
260+
return _currentFolder.Count;
261+
}
262+
263+
public void Logoff()
264+
{
265+
CloseCurrentFolder();
266+
if (client.IsConnected)
267+
client.Disconnect(true);
268+
}
269+
270+
public void Logon(InternetMailProfile profile)
271+
{
272+
_profile = profile;
273+
274+
client.Timeout = _profile.Timeout * 1000;
275+
client.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
276+
client.Connect(profile.ImapServerAddress, profile.GetImapPort());
277+
278+
if (!string.IsNullOrEmpty(profile.ImapUser))
279+
client.Authenticate(profile.ImapUser, profile.ImapPassword);
280+
281+
UpdateCurrentFolder();
282+
}
283+
284+
public void RenameMailbox(string name, string newName)
285+
{
286+
var oldFolder = client.GetFolder(name);
287+
oldFolder.Rename(oldFolder.ParentFolder, newName);
288+
}
289+
290+
public void SubscribeToMailbox(string name)
291+
{
292+
var folder = client.GetFolder(name);
293+
folder.Subscribe();
294+
}
295+
296+
public void UndeleteMessages(ArrayImpl deletedData)
297+
{
298+
var messages = GetMessagesList(deletedData);
299+
_currentFolder.RemoveFlags(messages, MessageFlags.Deleted, silent: true);
300+
}
301+
302+
public void UnsubscribeFromMailbox(string name)
303+
{
304+
var folder = client.GetFolder(name);
305+
if (folder.IsSubscribed)
306+
folder.Unsubscribe();
307+
}
308+
309+
public void Dispose()
310+
{
311+
Logoff();
312+
}
313+
314+
}
315+
}

0 commit comments

Comments
 (0)