Pop3cli
/
Program.cs
311 строк · 10.4 Кб
1#region License
2//------------------------------------------------------------------------------
3// Copyright (c) Dmitrii Evdokimov
4// Source https://github.com/diev/
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9// http://www.apache.org/licenses/LICENSE-2.0
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//------------------------------------------------------------------------------
16#endregion
17
18#define TRACE
19
20using Lib;
21
22using Mime;
23
24using Pop3;
25
26using System;
27using System.Collections.Generic;
28using System.Configuration;
29using System.IO;
30using System.Text;
31
32namespace Pop3cli
33{
34class Program
35{
36static void Main(string[] args)
37{
38Console.WriteLine(App.Banner);
39
40//AppTrace.Information(App.Title);
41AppTrace.Verbose(Environment.CommandLine);
42
43//if (args.Length == 0)// || Environment.CommandLine.Contains("?"))
44//Usage(null, 2);
45
46
47//Console.WriteLine("====================");
48//Console.WriteLine();
49
50//string src = Path.Combine(AppConfig.Get("Eml"), "3935?.eml");
51
52var settings = ConfigurationManager.AppSettings;
53
54switch (args.Length)
55{
56case 0:
57{
58string host = settings["Host"];
59
60if (host.Contains("*"))
61{
62AppTrace.Error("Требуется настроить config!");
63
64Usage();
65}
66
67string src = settings["Src"].ExpandPath();
68string bak = settings["Bak"].ExpandPath();
69string dst = settings["Dst"].ExpandPath();
70
71if (string.IsNullOrEmpty(host))
72{
73AppTrace.Information("Распаковка вложений");
74
75ExtractAttachmentsFromFiles(src, dst);
76}
77else
78{
79AppTrace.Information("Загрузка сообщений");
80
81int port = int.Parse(settings["Port"] ?? "110");
82bool ssl = (settings["Ssl"] ?? "0").Equals("1");
83
84string user = settings["User"];
85string pass = settings["Pass"];
86
87LoadMessages(host, port, ssl, user, pass, src, bak, dst);
88}
89break;
90}
91
92case 1:
93{
94string arg = args[0];
95
96if (arg.Equals("-?") || arg.Equals("/?"))
97{
98Usage();
99}
100else
101{
102AppTrace.Information($"Распаковка вложений из {arg}");
103
104string dst = settings["Dst"].ExpandPath();
105ExtractAttachmentsFromFiles(arg, dst);
106}
107break;
108}
109
110case 2:
111{
112string arg1 = args[0];
113string arg2 = args[1];
114
115AppTrace.Information($"Распаковка вложений из {arg1} в {arg2}");
116
117ExtractAttachmentsFromFiles(arg1, arg2);
118break;
119}
120
121default:
122{
123Usage();
124break;
125}
126}
127#if DEBUG
128Console.WriteLine();
129Console.WriteLine("======== Press Enter to end program");
130Console.ReadLine();
131#endif
132//AppExit.Information("Сделано.");
133AppExit.Exit();
134}
135
136static void Usage()
137{
138const string usage = "Параметры запуска:\n" +
139"0: Читать файл конфигурации и, если указан Host, загрузить файлы с этого POP3 сервера,\n" +
140" если нет - просто распаковать все вложения из файлов по маске Src в папку Dst.\n\n" +
141"1: Если -? или /h - показать эту помощь, иначе - по указанной маске вместо Src в конфиге.\n\n" +
142"2: Использовать указанные параметры вместо Src и Dst в конфиге.";
143
144Console.WriteLine(usage);
145//AppExit.Information("О программе.");
146
147Environment.Exit(1);
148}
149
150private static void ExtractAttachmentsFromFiles(string src, string dst)
151{
152if (Directory.Exists(src))
153{
154string[] files = Directory.GetFiles(src);
155
156foreach (string file in files)
157{
158Extract(file, dst);
159}
160}
161
162else if (src.Contains("*") || src.Contains("?"))
163{
164string path = Path.GetDirectoryName(src);
165
166if (!Directory.Exists(path))
167{
168AppExit.Error($"{path} not exists!", 2);
169}
170
171string[] files = Directory.GetFiles(path, Path.GetFileName(src));
172
173foreach (string file in files)
174{
175Extract(file, dst);
176}
177}
178else if (File.Exists(src))
179{
180Extract(src, dst);
181}
182else
183{
184AppExit.Error($"{src} not found!");
185}
186}
187
188private static void LoadMessages(string host, int port, bool ssl, string user, string pass, string src, string bak, string dst)
189{
190try
191{
192//prepare pop client
193var client = new Pop3MailClient(host, port, ssl, user, pass)
194{
195AutoReconnect = true
196};
197
198//remove the following line if no tracing is needed
199//client.Trace += new Pop3.TraceHandler(Console.WriteLine);
200client.Trace += new TraceHandler(AppTrace.Verbose);
201client.ReadTimeout = 180000; //give server 180 seconds to answer
202
203//establish connection
204client.Connect();
205
206//get mailbox statistics
207client.GetMailboxStats(out int NumberOfMails, out int MailboxSize);
208
209//get a list of unique mail ids
210client.GetUniqueEmailIdList(out List<Pop3.EmailUid> EmailUids);
211
212//get email
213for (int i = 0; i < EmailUids.Count; i++)
214{
215string path = Path.Combine(src, EmailUids[i].Uid + ".eml");
216
217if (!File.Exists(path))
218{
219int id = EmailUids[i].EmailId;
220
221if (client.GetRawEmail(id, out string text))
222{
223File.WriteAllText(path, text);
224Extract(path, dst);
225}
226}
227}
228
229//cleanup server deleted email
230if (!Directory.Exists(bak))
231{
232Directory.CreateDirectory(bak);
233}
234
235string[] files = Directory.GetFiles(src, "*.eml");
236
237foreach (string file in files)
238{
239string filename = Path.GetFileNameWithoutExtension(file);
240bool found = false;
241
242foreach (var e in EmailUids)
243{
244if (e.Uid.Equals(filename))
245{
246found = true;
247break;
248}
249}
250
251if (!found)
252{
253AppTrace.Verbose("{0} bak", filename);
254File.Move(file, Path.Combine(bak, filename + ".eml"));
255}
256}
257
258//close connection
259client.Disconnect();
260}
261catch (Exception ex)
262{
263var sb = new StringBuilder();
264sb
265.AppendLine("Run Time Error Occured:")
266.AppendLine(ex.Message)
267.AppendLine(ex.StackTrace);
268
269AppTrace.Error(sb);
270}
271}
272
273private static void Extract(string path, string folder)
274{
275using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
276using (var streamReader = new StreamReader(fileStream))
277{
278MimeParser parser = new MimeParser(streamReader);
279
280if (parser.GetEmail(out MimeMessage message))
281{
282#if DEBUG
283Console.WriteLine(message.MailStructure());
284#endif
285var sb = new StringBuilder();
286sb
287.AppendLine($"[{Path.GetFileName(path)}] {message.DeliveryDate:dd.MM HH:mm} <{message.From.Address}> {message.From.DisplayName}")
288.AppendLine($" {message.Subject}");
289
290if (!Directory.Exists(folder))
291{
292Directory.CreateDirectory(folder);
293}
294
295foreach (var attachment in message.Attachments)
296{
297string name = attachment.Name;
298sb.AppendLine($" - {name}");
299
300using (var file = File.OpenWrite(Path.Combine(folder, name)))
301{
302attachment.ContentStream.CopyTo(file);
303}
304}
305
306AppTrace.Information(sb);
307}
308}
309}
310}
311}
312