Menu
Jest wolny
Zameldować się
Dom  /  Multimedia / Konfigurowanie zbierania poczty Yandex. Zbieramy wszystkie listy z różnych skrzynek pocztowych w jedną

Konfigurowanie zbierania poczty Yandex. Zbieramy wszystkie listy z różnych skrzynek pocztowych w jedną

Prawdopodobnie tylko nieliczni nie mieli problemu z tym, że ich adres e-mail już ich nie lubił lub po prostu go nie potrzebowali. Ale co, jeśli ze skrzynką jest skojarzona duża liczba kontaktów, których nie chciałbyś stracić.

Pierwszym rozwiązaniem, jakie może przyjść na myśl, jest stworzenie nowego pięknego adresu i ciągłe sprawdzanie drugiego. To skomplikowane. W takim przypadku zaczynamy tworzyć jeszcze więcej skrzynek pocztowych i mylimy się z wieloma adresami.

Jest tu wiele niedogodności: istnieje ryzyko zapomnienia hasła, adres nadal irytuje [email chroniony], kiedy jesteś dyrektorem poważnej firmy i nie tylko!

Jest na to rozwiązanie i jest bardzo proste. I wygodne.

Po utworzeniu skrzynki pocztowej z idealnym adresem włącz zbieranie listów ze starej poczty. Wszystkie listy z połączonych skrzynek pocztowych można znaleźć w głównej poczcie w folderach o tej samej nazwie. Wszystko jest zadbane, przejrzyste i uporządkowane.

Kolekcjoner oszczędza czas przy przechodzeniu z pudełka do skrzynki i pozwala całkowicie przejść na nowy adres bez obawy, że ktoś pozostanie bez odpowiedzi.

Jak skonfigurować?

Jeszcze raz. Wszystko jest bardzo proste. My mówimy:

  1. Przejdź do ustawień swojej skrzynki pocztowej;
  2. Wybierz sekcję „Poczta z innych skrzynek pocztowych”;
  3. Wpisz adres e-mail i hasło do skrzynki pocztowej, z której chcesz odbierać listy.

Po podłączeniu nowego adresu zobaczysz go na ogólnej liście na tej samej stronie.

W tej sekcji możesz łatwo zarządzać kolektorem: wstrzymywać, usuwać lub dodawać dodatkowe skrzynki. Zebrane listy będą przechowywane w osobnym folderze z wewnętrznymi podfolderami, które utworzyłeś w starej skrzynce pocztowej.

Nawiasem mówiąc, jeśli jesteś zdeterminowany, aby użyć pięknego nowego adresu, ale jesteś zbyt leniwy, aby powiadomić wszystkich, którzy nadal piszą do starej poczty, skonfiguruj reguły filtrowania z automatyczną odpowiedzią z nowego adresu.

Aby to zrobić, skonfiguruj filtr i wprowadź stary adres w kolumnie „Jeśli litery do kogo”. Wybierz czynność „Odpowiedz za pomocą wiadomości”. Jeśli w wiadomości wskażesz adres nowej skrzynki pocztowej, to każdy, kto napisze na starą pocztę, otrzyma odpowiedź i nie straci Twoich kontaktów.

Przełączanie się z jednej karty z Gmaila na inną za pomocą Yandex.Mail jest raczej żmudne. A jeśli masz kilkanaście kont u różnych dostawców poczty, sprawdzanie nowej korespondencji rano staje się torturą. Łącząc litery w jednym miejscu, pozbędziesz się tej niedogodności.

interfejs sieciowy

Większość dostawców poczty e-mail udostępnia wbudowaną funkcję zbierania poczty z wielu skrzynek pocztowych. Na przykład spróbujmy zebrać listy ze wszystkich skrzynek pocztowych na jednym koncie Gmail.

Przede wszystkim upewnij się, że usługa pocztowa, z której chcesz odbierać listy, ma dostęp POP. Następnie przejdź do ustawień Gmaila i kliknij „Ustawienia” w prawym górnym rogu. Przejdź do karty „Konta” i poszukaj sekcji „Odbieraj pocztę z innych kont”.

Dodaj konto, wprowadź swój adres e-mail i kliknij Dalej, a następnie wprowadź hasło. Aby wymiana poczty między dostawcami była bezpieczniejsza, upewnij się, że opcja „Zawsze używaj bezpiecznego połączenia (SSL) podczas odbierania poczty” jest włączona. Następnie kliknij „Dodaj konto”.

Teraz e-maile przychodzące na dodany adres będą automatycznie gromadzone w Twojej skrzynce odbiorczej Gmaila. Możesz dodać dowolną liczbę adresów pocztowych.

Klienci komputerowi

Poczta e-mail wymaga oprogramowania. Tak, możesz wiele zrobić w internetowym kliencie poczty (czasami znacznie więcej niż Google obecnie pozwala zrobić w Gmailu). Jednak interfejs sieciowy nie przypomina aplikacji natywnej. Nawet najnowocześniejszy interfejs sieciowy jest wąskim gardłem w obsłudze poczty.

Rafe Needleman, Сnet.com

Pulpitowe klienty poczty e-mail są świetne, ponieważ mogą agregować wiadomości e-mail z wielu kont. Jednocześnie możesz pracować z dziesiątkami adresów i nawet nie myśleć o tym, który dostawca przechowuje tę lub inną wiadomość.

Większość stacjonarnych klientów poczty e-mail ma wbudowaną ogólną skrzynkę odbiorczą. Nawet jeśli Twój ulubiony klient obsługuje tylko oddzielne foldery skrzynki odbiorczej, nadal możesz łatwo zebrać je razem za pomocą inteligentnych filtrów.

Mimo że program Outlook jest zaprojektowany do zarządzania wieloma skrzynkami pocztowymi w tym samym czasie, nadal wyświetla osobną skrzynkę odbiorczą dla każdego konta. Ale można to łatwo naprawić za pomocą filtrów.

Otwórz Outlooka, przejdź do zakładki „Foldery” i kliknij „Utwórz folder wyszukiwania” na pasku narzędzi. Następnie wybierz opcję Utwórz niestandardowy folder wyszukiwania. Kliknij „Wybierz”, ale nie wybieraj żadnych kryteriów wyszukiwania, aby wszystkie nowe wiadomości były wysyłane do folderu. Nadaj folderowi dowolną nazwę, na przykład „Cała poczta”.

Kliknij „Przeglądaj”, zaznacz wszystkie foldery i skrzynki pocztowe, z których chcesz zbierać pocztę i zaznacz opcję „Szukaj w podfolderach”.

Teraz w utworzonym inteligentnym folderze pojawią się listy ze wszystkich kont pocztowych dodanych do programu Outlook. Możesz włączyć opcję „Pokaż w ulubionych”, aby nowa poczta była zawsze widoczna.

Klient poczty Mac udostępnia jedną skrzynkę odbiorczą dla wszystkich połączonych kont. Po prostu dodaj swoje konta, a wszystkie nowe e-maile będą gromadzone w jednym miejscu.

Thunderbird ułatwia zbieranie wszystkich wiadomości e-mail w jednej skrzynce odbiorczej. Przejdź do menu „Widok” (jeśli pasek menu nie jest wyświetlany, naciśnij Alt). Następnie wybierz „Foldery” → „Skonsolidowane”. Będziesz mieć teraz jedną skrzynkę odbiorczą na nowe wiadomości e-mail, jeden folder Robocze, jeden folder Elementy wysłane i jeden folder Archiwum. Nie będziesz musiał długo szukać tego, gdzie leży. W takim przypadku wiadomości będą przechowywane, tak jak poprzednio, na serwerach dostawców poczty.

Klienci mobilni

Ujednolicona skrzynka odbiorcza jest dostępna w wielu mobilnych klientach poczty e-mail, w tym w Gmailu. Aplikacja Gmail zbiera skrzynkę odbiorczą ze wszystkich kont e-mail, w tym Yahoo, Outlook i innych usług.

Jeśli nie podoba Ci się aplikacja Google, możesz wypróbować klientów poczty e-mail innych firm, takich jak Outlook lub MyMail.

Może masz własne pomysły na grupowanie poczty w jednym miejscu? Udostępnij w komentarzach.

W tym artykule skupimy się na tym, czym są „poczta z innych skrzynek pocztowych” i „odbieranie listów z innych kont”. Recenzje usług pocztowych i porównania.

W miarę aktualizowania funkcjonalności usług pocztowych będziemy publikować wiadomości na końcu tego artykułu.

Poczta Mail.ru, wyszukiwarki Yandex i Google od kilku lat oferują bardzo przydatną i niezbędną funkcjonalność, która umożliwia połączenie wszystkich pozostałych kont e-mail w jednej wiadomości. Innymi słowy, warto raz dodać i skonfigurować wszystkie swoje „maile”, a będzie można nimi zarządzać w jednym oknie bez ciągłego wpisywania loginu i hasła.

Usługi pocztowe oferują nam ogromną przestrzeń do przechowywania wszystkich przychodzących wiadomości e-mail, przyjazny interfejs użytkownika, dobrą funkcjonalność zarządzania i wiele więcej. Aby przetestować możliwości wymienionych usług pocztowych, wyróżnimy trzy parametry do oceny ich pracy: 1) konieczne jest zarządzanie różnymi kontami e-mail, w tym z różnych usług i witryn, za pośrednictwem jednego klienta pocztowego; 2) posiadać osobisty podpis i imię na każdej przesyłce; 3) usuwać wiadomości z serwerów tych kont pocztowych, które zostały dodane do poczty, yandex lub google mail.

Nasze zadanie wygląda następująco:

Więc zacznijmy. Jako pierwsi testujemy usługę Mail.ru, która mówi nam: „Możesz zbierać pocztę ze wszystkich swoich skrzynek pocztowych do jednej skrzynki pocztowej na Mail.ru.

Skonfiguruj zbieranie wiadomości e-mail z dowolnego serwera przy użyciu protokołu IMAP lub POP3 ”. Aby dodać zewnętrzną pocztę inną niż @mail, @inbox, @list, @bk, musisz mieć co najmniej jedną pocztę, która już istnieje na wymienionych serwerach z poczty. Innymi słowy, najpierw zarejestruj pocztę, a następnie dodaj inne konta pocztowe. Proces rejestracji dla poczty jest prosty, nie ma sensu go opisywać, ale opiszemy dodawanie kolejnych e-maili do tego konta pocztowego.

Następnie zostaniesz poproszony o podanie loginu i hasła z dowolnej używanej skrzynki pocztowej, a w ciągu 3-5 minut „Kolektor poczty z poczty” utworzy folder z nazwą dodanej poczty obok folderów „przychodzące”, „wysłane”, „spam” i inny.

W rzeczywistości kolektor listów zacznie działać w ciągu 10-15 minut i doda wszystkie listy do nowo utworzonego folderu z określonej skrzynki pocztowej. Wszystkie przychodzące listy na nowy e-mail będą trafiać do tego folderu, będzie można również wysyłać listy z załączonej skrzynki pocztowej. Podczas tworzenia nowego listu pojawi się pole Od, w którym możesz wybrać, z której skrzynki ma zostać wysłany list.

Zaletą usługi pocztowej Mail.ru jest prostota dodawania i łatwość konfiguracji innych skrzynek pocztowych, brak konieczności określania różnych protokołów (POP3, SMTP). Jest to bardzo ważne, ponieważ nie każdy użytkownik wie, co to jest.

Wadą Mail.ru jest to, że nie można przypisać nazwy i podpisu do każdej nowo dodanej poczty (każdej nowej wiadomości e-mail, z wyjątkiem głównej), to znaczy, że nazwa i podpis głównej poczty zostaną przesłane na każdy adres i to wszystko. Kolejną dużą wadą jest to, że podczas przesyłania listów do poczty nie ma możliwości automatycznego usuwania oryginalnych listów z dołączonego serwera skrzynki pocztowej. Dlaczego tak ważne jest usuwanie wiadomości z serwera dodanej skrzynki pocztowej? Pozwoli to uniknąć zapełnienia załączonej wiadomości, ponieważ zewnętrzne konta e-mail są zwykle zbyt małe, aby przechowywać wiadomości e-mail. Na przykład, jeśli miejsce na pocztę na koncie zewnętrznym jest pełne, Mail.ru nie wyświetli żadnych nowych liter, dopóki nie przejdziesz do zewnętrznego interfejsu poczty i nie usuniesz stamtąd bezpośrednio, aby zwolnić miejsce. Ponadto łączymy pocztę z Mail w nadziei uzyskania dużej ilości miejsca na naszą pocztę, która może być ograniczona przez zasoby hostingowe. Tak więc, pomimo faktu, że Mail.ru oferuje prawie nieograniczoną liczbę skrzynek pocztowych, podczas dodawania poczty z innej strefy domeny (na przykład [email chroniony]), dodane zasoby poczty e-mail nie zwiększą się w Mail.ru, ale będą nadal ograniczone przez zasoby hostingu (w naszym przypadku zasoby primer.ru).

Możliwość dodania innej poczty do usługi Mail nie odpowiadała naszemu zadaniu w dwóch z trzech punktów, co daje łącznie jeden punkt.

To prawda, Mail.ru ma inny sposób dodawania poczty zewnętrznej, a dokładniej łączenia się z pocztą zewnętrzną lub logowania się do niej. To wygląda tak:

Ta metoda nie nadaje się do naszego zadania, ponieważ nie jest to kolektor poczty, ale tryb użytkownika, który łączy się z pocztą i ładuje wszystkie foldery i listy do interfejsu poczty za każdym razem. Ale tutaj można dodać osobisty podpis i imię dla każdej wiadomości, możliwe jest wysyłanie listów ze skonfigurowanej poczty. Usuwanie wiadomości z załadowanych skrzynek nie działa, ponieważ to nie jest kolektor poczty.

Ważny! Niektórzy użytkownicy błędnie uważają, że jeśli litery są wyświetlane w wiadomości e-mail, można usunąć pocztę, z której nastąpiło pobranie. Zwróć uwagę, że Mail.ru działa jako przeglądarka poczty i jeśli wyczyścisz pocztę, zostanie ona usunięta zarówno z głównej skrzynki pocztowej, jak i poczty.

Drugim obiektem testów jest Yandex ze swoim kolektorem listów. Zadania są podobne: zbieranie poczty, przypisywanie podpisu i nazwy do każdej wiadomości oraz usuwanie całej poczty z dodanej skrzynki pocztowej.

Kolektor poczty Yandex jest skonfigurowany w podobny sposób, ale jeśli poczta jest podłączona z jakiejś witryny, na przykład site.ru, należy określić dodatkowe ustawienia, patrz zrzut ekranu.

Usługa Mail wykonała to za nas, podczas gdy Yandex oferuje ręczne ustawienie wszystkich ustawień z poczty innej firmy. Nie ma tu nic skomplikowanego: w polu logowania wpisz pełną nazwę poczty ( [email chroniony]), w polu serwera wprowadź tylko domenę (site.ru), lepiej pozostawić domyślnie wszystkie inne ustawienia lub zmienić, jeśli wiesz, co robisz. Po pomyślnym dodaniu poczty pojawi się następujący komunikat:

W przeciwieństwie do Mail collector, Yandex oferuje wybór, czy zapisać oryginały listów w dodanej skrzynce pocztowej, czy nie. We wszystkim innym kolektor poczty Yandex działa podobnie jak Mail.ru, możliwe jest wybranie skrzynki pocztowej, z której ma zostać wysłany list. Ale Yandex ma ten sam problem z podpisem listów: nie ma możliwości ustawienia indywidualnej nazwy i podpisu dla każdej dodanej skrzynki pocztowej.

Sądząc po nawigacji, istnieje możliwość dodania indywidualnego podpisu dla każdej skrzynki, ale w rzeczywistości to nie działa. Wybieramy wiadomość, zapisujemy imię i nazwisko oraz podpis, klikamy zapisz. To wszystko, podpis jest zapisywany i działa, ale jest również zapisywany dla wszystkich innych skrzynek pocztowych, to znaczy, przypisując nazwę i podpis do jednej skrzynki pocztowej, automatycznie zmieniasz te parametry we wszystkich wiadomościach połączonych w Yandex. Nawet jeśli wybierzesz inne pole, podpis będzie teraz wszędzie taki sam.

W sumie Yandex z powodzeniem poradził sobie ze zbieraniem i sortowaniem poczty, może usuwać oryginały listów z dodanej skrzynki pocztowej, ale nie może pracować z podpisami! Kolektor poczty Yandex nie wykonał naszego zadania i otrzymuje dwa punkty na trzy.

Chciałbym zauważyć, że po „grzebaniu” we wszystkich trzech usługach w celu składania listów wydaje się, że Mail w pośpiechu „uderzył” w swoją funkcjonalność. Chociaż, szczerze mówiąc, zadowoli to większość użytkowników, Mail stworzył kolekcjonera poczty na pokaz, aby sprawdzić konkurencyjny wyścig. Wszystko działa dobrze i bezawaryjnie, ale kolekcjoner z Mail nie poradził sobie z naszym zadaniem. W interfejsie poczty znajduje się kilka jednostek reklamowych, ale nie przeszkadzają one w pracy z listami.

Jeśli chodzi o Yandex, który dawno temu stworzył kolektor listów, wydaje się, że ta konkretna branża nie jest obsługiwana, ponieważ naprawienie tak prostej funkcjonalności (możliwość dodawania wielu podpisów do skrzynek pocztowych) nie powinno być trudne dla tak potężnej wyszukiwarki. Niemniej jednak Yandex ma inną unikalną funkcjonalność, która umożliwia wiązanie domen z ich serwerami dns, a następnie tworzenie i konfigurowanie poczty. Ale takie operacje i ustawienia wymagają wiedzy i czasu. I chociaż nie ma tam nic skomplikowanego, w każdym razie nie jest to dla większości użytkowników rosyjskiego Internetu. Wielka zaleta - brak reklam w interfejsie poczty Yandex! Minus - ograniczenie kolektora listów do 10 skrzynek pocztowych.

Finalistą i zwycięzcą jest kolekcjoner listów z Google, który mimo wszystko poradził sobie z naszym zadaniem z hukiem limit 5 pudełek

Prawdopodobnie wielu z was w swojej praktyce miało do czynienia z zadaniem zbierania poczty z kilku skrzynek. Dlaczego to może być konieczne? Zapewne dlatego, że jest to uniwersalny mechanizm wymiany danych między systemami. Wiele bibliotek dla dowolnych języków, które implementują SMTP, POP3, IMAP, gotowe rozwiązania do implementacji stosu wiadomości (jak trudno nazwać skrzynką pocztową ...) itp.

Nic dziwnego, że wiele zadań integracyjnych jest realizowanych za pośrednictwem poczty. Tutaj wchodzi w grę pewna usługa, która może szybko odebrać tę wiadomość, skategoryzować ją i wykonać niezbędne czynności.

Kto potrzebuje poniższego kodu, nie może dalej czytać:

Foreach (skrzynka pocztowa var w skrzynkach pocztowych) using (var client \u003d new Pop3Client ()) (client.Connect (Hostname, Port, false); client.Authenticate (User, Password); var count \u003d client.GetMessageCount (); for (var i \u003d 0; i< count; i++) { Mail = client.GetMessage(i + 1); var cat = SortMail(Mail); DoSomething(Mail, cat); } }

Co robimy

Przyjmijmy od razu kilka założeń:
1) Musisz zbierać pocztę dla kilku systemów. Może w przyszłości na kilka więcej. I więcej ... Generalnie rozwiązanie powinno być uniwersalne;
2) Listów prawdopodobnie będzie dużo - wynika z punktu 1 (inaczej bym nie napisał tego postu);
3) Poczta będzie musiała zostać przeanalizowana;
4) Wszystkie skrzynki serwisowe - użytkownicy tam nie chodzą.

Czego użyjemy

System musi działać 24 godziny na dobę, 7 dni w tygodniu, dlatego zaimplementujemy go jako usługę Windows. W tym celu proponuję od razu użyć TopShelf.

Oczywiście wszystko powinno być zrównoleglone. W tym miejscu do gry wkracza moja ulubiona biblioteka TPL DataFlow.

Będziemy odbierać pocztę za pomocą POP3. Wszystkie „modne rzeczy” IMAP w tym zadaniu są zbędne - musisz jak najszybciej i łatwo odebrać źródło listu i usunąć je z serwera. Tutaj wystarczy POP3 dla oczu. Używamy OpenPop.NET.

Jako opcja, zaostrzymy monitorowanie w Zabbix. (Będziemy pracować 24 godziny na dobę, 7 dni w tygodniu i będziemy dawać sławną prędkość - trzeba to monitorować).

Udać się

Stwórzmy zwykłą aplikację konsolową. Otwórz konsolę NuGet i zainstaluj wszystkie niezbędne pakiety:

Install-Package Nlog Install-Package OpenPop.NET Install-Package TopShelf Install-Package Microsoft.TPL.DataFlow
Przejdź do folderu projektu, utwórz App.Debug.config i App.Release.config. Wyładowujemy projekt ze studia, otwieramy jego kod (dalej TopCrawler.csproj). Dodaj do sekcji z konfiguracją:

Konfiguracje

App.config App.config


Poniżej znajduje się niestandardowy cel dla programu MSBuild:

Przekształć cel

$ (TargetFileName) .config


Osobiście przyzwyczaiłem się do tego w ten sposób - staromodny - dodawania transformacji konfiguracji do oddzielnych środowisk.
Dla wygody sugeruję konfiguracje typu silnie. Osobna klasa odczyta konfigurację. (O teoretycznych aspektach takiego rozwiązania można mówić w komentarzach). Konfiguracje, dzienniki, monitorowanie to doskonały powód do zaimplementowania wzorca Singleton.

Utwórz folder o tej samej nazwie w projekcie (musi być zamówienie). Wewnątrz tworzymy 3 klasy - Config, Logger, Zabbix. Nasz rejestrator:

Logger

klasa statyczna Logger (public static NLog.Logger Log (get; private set;) public static NLog.Logger Archive (get; private set;) static Logger () (Log \u003d LogManager.GetLogger ("Global"); Archive \u003d LogManager. GetLogger ("Archiwizator");))


Monitorowanie za pomocą Zabbix zasługuje na osobny wpis, więc zostawię tutaj klasę implementującą agenta:

Zabbix

przestrzeń nazw TopCrawler.Singleton (///

/// Singleton: zabbix sender class /// statyczna klasa Zabbix (public static ZabbixSender Sender (get; private set;) static Zabbix () (Sender \u003d new ZabbixSender (Config.ZabbixServer, Config.ZabbixPort);)) struct ZabbixItem (public string Value; public string Key; public string ;) class ZabbixSender (internal struct SendItem (// ReSharper disable InconsistentNaming - Zabbix rozróżnia wielkość liter w publicznym łańcuchu znaków; publiczny klucz ciągu; publiczna wartość ciągu; public string clock; // ReSharper restore InconsistentNaming) #pragma warning disable 0649 internal struct ZabbixResponse ( public string Response; public string Info;) #pragma warning restore 0649 #region --- Constants --- public const string DefaultHeader \u003d "ZBXD \\ x01"; public const string SendRequest \u003d "sender data"; public const int DefaultTimeout \u003d 10000 ; #endregion #region --- Pola --- prywatne tylko do odczytu DateTime _dtUnixMinTime \u003d DateTime.SpecifyKind (new DateTime (1970, 1, 1), DateTimeKind.Utc); private readonly int _timeout; prywatny ciąg znaków tylko do odczytu _zabbixserver; private readonly int _zabbixport; #endregion #region --- Konstruktory --- public ZabbixSender (string zabbixserver, int zabbixport): this (zabbixserver, zabbixport, DefaultTimeout) () public ZabbixSender (string zabbixserver, int zabbixport, int timeout) (_zabbixserver \u003d zabbixport zabbixport; _timeout \u003d timeout;) #endregion #region --- Metody --- public string SendData (ZabbixItem itm) (return SendData (new List (1) (itm)); ) publiczny ciąg SendData (List lstData) (try (var serializer \u003d new JavaScriptSerializer (); var values \u200b\u200b\u003d new List (lstData.Count); values.AddRange (lstData.Select (itm \u003d\u003e new SendItem (host \u003d itm.Host, key \u003d itm.Key, value \u003d itm.Value, clock \u003d Math.Floor ((DateTime.Now.ToUniversalTime () - _dtUnixMinTime)). TotalSeconds) .ToString (CultureInfo.InvariantCulture)))); var json \u003d serializer.Serialize (new (request \u003d SendRequest, data \u003d values.ToArray ())); var header \u003d Encoding.ASCII.GetBytes (DefaultHeader); var length \u003d BitConverter.GetBytes ((long) json.Length); var data \u003d Encoding.ASCII.GetBytes (json); var pakiet \u003d nowy bajt; Buffer.BlockCopy (nagłówek, 0, pakiet, 0, nagłówek.Length); Buffer.BlockCopy (długość, 0, pakiet, nagłówek.Length, długość.Length); Buffer.BlockCopy (dane, 0, pakiet, nagłówek.Length + length.Length, data.Length); using (var socket \u003d new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) (socket.Connect (_zabbixserver, _zabbixport); socket.Send (pakiet); // Nagłówek var bufor \u003d nowy bajt; ReceivData (gniazdo , buffer, 0, buffer.Length, _timeout); if (DefaultHeader! \u003d Encoding.ASCII.GetString (buffer, 0, buffer.Length)) throw new Exception ("Invalid header"); // Message length buffer \u003d new byte ; ReceivData (socket, buffer, 0, buffer.Length, _timeout); var dataLength \u003d BitConverter.ToInt32 (buffer, 0); if (dataLength \u003d\u003d 0) throw new Exception ("Invalid data length"); // Message buffer \u003d nowy bajt; ReceivData (gniazdo, bufor, 0, buffer.Length, _timeout); var response \u003d serializer.Deserialize (Encoding.ASCII.GetString (buffer, 0, buffer.Length)); return string.Format ("Response: (0), Info: (1)", response.Response, response.Info); )) catch (Exception e) (return string.Format ("Exception: (0)", e);)) private static void ReceivData (Socket pObjSocket, bufor bajtowy, int offset, int size, int timeout) (var startTickCount \u003d Environment.TickCount; var received \u003d 0; do (if (Environment.TickCount\u003e startTickCount + timeout) throw new TimeoutException (); try (Otrzymano + \u003d pObjSocket.Receive (bufor, przesunięcie + odebrano, rozmiar - odebrano, SocketFlags.None) ;) catch (SocketException ex) (if (ex.SocketErrorCode \u003d\u003d SocketError.WouldBlock || ex.SocketErrorCode \u003d\u003d SocketError.IOPending || ex.SocketErrorCode \u003d\u003d SocketError.NoBufferSpaceAvailable) Rzut wątku; 30); else ) podczas gdy (otrzymał< size); } #endregion } }


Konfiguracje ... Pora zrobić przynajmniej coś ciekawego. Najpierw w konfiguracjach będziemy przechowywać pola, które sprawdzamy. Po drugie, ustawienia DataFlow. Proponuję to:

Configs



A więc host i port, z którym się łączy, użytkownik i hasło - tutaj wszystko jest jasne. Dalej jest rodzaj pudełka. Powiedzmy, że usługa jest używana przez marketing (a także inne działy). Mają skrzynki pocztowe, w których zrzucane są automatyczne odpowiedzi na mailing, a także raporty spamu FBL. Sama skrzynka pocztowa już kategoryzuje list, więc w takich sytuacjach od razu ustawiamy typ skrzynki. Dzięki ustawieniom DataFlow będzie to jasne później, gdy zaczniemy tworzyć obiekty. Tutaj będziemy mieć własne sekcje w config. Istnieje wiele podręczników, jak to zrobić, więc pokażę tylko wynik:

Definiowanie typów

#region --- Typy --- klasa statyczna MailboxType (public const string Bo \u003d "bo"; public const string Crm \u003d "crm"; public const string Fbl \u003d "fbl"; public const string Bounce \u003d "bounce";) class MailboxInfo (public string Type (get; set;) public string Hostname (get; set;) public string User (get; set;) public string Password (get; set;) public int Port (get; set;)) class DataBlockOptions (public int Maxdop (get; set;) public int BoundedCapacity (get; set;) public DataBlockOptions () (Maxdop \u003d 1; BoundedCapacity \u003d 1;)) #endregion


Utwórz sekcje

///

/// Sekcja konfiguracji niestandardowej /// public class CustomSettingsConfigSection: ConfigurationSection (public CredentialsCollection CredentialItems (get (return base ["CredentialsList"] as CredentialsCollection;)) public DataBlockOptionsCollection DataFlowOptionsItems (get (return base ["DataFlowOptionsList"]) as DataBlockOptionsList)


///

/// Kolekcja niestandardowa - lista danych logowania /// public class CredentialsCollection: ConfigurationElementCollection, IEnumerable (protected override ConfigurationElement CreateNewElement () (return new CredentialsElement ();) protected override object GetElementKey (ConfigurationElement element) (return ((CredentialsElement) element) .Username;) public CredentialsElement this (get (return BaseGet (index) as CredentialsElement;) ) public nowy IEnumerator < Count; i++) { yield return BaseGet(i) as CredentialsElement; } } } /// /// Niestandardowe dane logowania /// public class CredentialsElement: ConfigurationElement (public string Hostname (get (return base ["hostname"] as string;)) public string Username (get (return base ["username"] as string;)) public string Password (get (return base ["hasło"] jako ciąg;)) public string Type (get (return base ["type"] as string;)) public string Port (get (return base ["port"] as string;))) /// /// Kolekcja niestandardowa - lista opcji DataBlock /// public class DataBlockOptionsCollection: ConfigurationElementCollection, IEnumerable (protected override ConfigurationElement CreateNewElement () (return new DataBlockOptionsElement ();) protected override object GetElementKey (ConfigurationElement element) (return ((DataBlockOptionsElement) element) .Name;) public CredentialsElement this (get (return BaseGet (index) as Credentials) ) public nowy IEnumerator GetEnumerator () (for (var i \u003d 0; i< Count; i++) { yield return BaseGet(i) as DataBlockOptionsElement; } } } /// /// Niestandardowe opcje DataBlock /// public class DataBlockOptionsElement: ConfigurationElement (public string Name (get (return base ["name"] as string;)) public string Maxdop (get (return base ["maxdop"] as string;)) public string BoundedCapacity (get (return base ["boundedcapacity"] jako ciąg znaków;)))


Nie będę pisał pełnej implementacji configu, rozumie się, że w trakcie procesu rozwoju zostaną tam dodane potrzebne nam parametry.

Przeczytajmy nasze niestandardowe ustawienia, takie jak:

Czytać

lista publiczna CredentialsList (get; private set;) publiczny słownik DataFlowOptionsList (get; private set;) ... static Config () (try (var customConfig \u003d (CustomSettingsConfigSection) ConfigurationManager.GetSection ("CustomSettings"); // Pobierz skrzynki pocztowe foreach (element var w customConfig.CredentialItems) CredentialsList.Add ( new MailboxInfo (Hostname \u003d item.Hostname, Port \u003d Convert.ToInt32 (item.Port), User \u003d item.Username, Type \u003d item.Type, Password \u003d item.Password)); // Get DataFlow settings foreach (var item in customConfig.DataFlowOptionsItems) DataFlowOptionsList.Add (item.Name, new DataBlockOptions (Maxdop \u003d Convert.ToInt32 (item.Maxdop), BoundedCapacity \u003d Convert.ToInt32 (item.BoundedCapacity)));) catch (Exception ex) (Logger Fatal ("Błąd odczytu konfiguracji: (0)", np. Wiadomość); rzut;))


Jakoś okazuje się to bardzo przewlekłe, a nawet nie dotarliśmy do najciekawszego.

Na razie pomińmy powiązanie TopShelf, liczniki wydajności, komunikację z bazą danych i przejdźmy do rzeczy! Tworzymy klasę Crawler - rdzeń. Najpierw czytamy pocztę:

Prywatne niestabilne bool _stopPipeline; ... public void Start () (do (var getMailsTasks \u003d _config.CredentialsList.Select (credentials \u003d\u003e Task.Run (() \u003d\u003e GetMails (credentials))). ToList (); foreach (var task in getMailsTasks) task .Wait (); Thread.Sleep (2000);) while (! _StopPipeline); // Zatrzymaj potok - poczekaj na zakończenie wszystkich punktów końcowych // Spowoduje to zatrzymanie potoku DataFlow if (_stopPipeline) Logger.Log.Warn ("Pipeline ma został zatrzymany przez użytkownika ");)
Tutaj lenistwo zebrało swoje żniwo i postanowiłem nie zawracać sobie głowy - jeśli jest około 20-30 pudełek, możesz uruchomić zadanie dla każdego i nie martwić się liczbą wątków. (Pozwól mi wziąć prysznic z pomidorami.)

Przejdźmy do samego czytania:

Private void GetMails (MailboxInfo info) (try (using (var client \u003d new Pop3Client ()) (
Od razu obliczmy czasy dostępu do skrzynki pocztowej - przydatne przy diagnozowaniu obciążenia sieci i serwera.

// Pobierz metryki Zabbix var stopwatch \u003d new Stopwatch (); stopwatch.Start (); // Pobierz licznik poczty client.Connect (info.Hostname, info.Port, false); client.Authenticate (info.User, info.Password); stopwatch.Stop ();
Wysyłanie danych do Zabbix. To proste - podajemy nazwę hosta (tak jak w Zabbix), klucz (znowu, ściśle, jak w Zabbix) i wartość ciągu.

// Wyślij to do Zabbix Zabbix.Sender.SendData (new ZabbixItem (Host \u003d Config.HostKey, Key \u003d info.Type + Config.TimingKey, Value \u003d stopwatch.ElapsedMilliseconds.ToString ())); Logger.Log.Debug ("Send [(0)] timing to Zabbix: connected to" (1) "as" (2) ", timing (3) ms", info.Type, info.Hostname, info.User, stopwatch.ElapsedMilliseconds); var count \u003d client.GetMessageCount (); if (count \u003d\u003d 0) return; Logger.Log.Debug ("Dostaliśmy nowe (0) wiadomości w" (1) "", count, info.User); // Wyślij wiadomości do bloku sortowania for (var i \u003d 0; i< count; i++) { try { var mailInfo = new MessageInfo { IsSpam = false, Mail = client.GetMessage(i + 1), Type = MessageType.UNKNOWN, Subtype = null, Recipient = null, Mailbox = info }; Logger.Log.Debug("Download message from "{0}". Size: {1}b", info.User, mailInfo.Mail.RawMessage.Length);
Potok DataFlow zostanie utworzony podczas tworzenia klasy Crawler. Wierzymy, że naszym pierwszym krokiem jest uporządkowanie listu.

While (! _SortMailDataBlock.Post (mailInfo)) Thread.Sleep (500);
Widzisz, jakie proste - sam przenośnik jest jeden. Wszystkie zadania, które odczytują pocztę, wysyłają tam wiadomości pojedynczo. Jeśli blok jest zajęty, Post zwróci wartość false i poczekamy, aż będzie wolny. Prąd nadal działa w tym czasie. To właśnie nazywam współbieżnością bezproblemową.

Wiadomość trafiła na przenośnik, teraz możesz ją zapisać w archiwum RAW ze spokojem (tak, wszystko co czytamy - zapisujemy do archiwum plików. Obsługa techniczna podziękuje nam później).

Skonfigurujmy na przykład rotację archiwum:

NLog.config



Następnie możesz ustawić na nim logStash, ale to już inna historia ...

// Zapisz każdą wiadomość w archiwum Logger.Log.Debug ("Archiwizuj wiadomość"); Logger.Archive.Info (Functions.MessageToString (mailInfo.Mail)); ) catch (Exception ex) (Logger.Log.Error ("Parse email error: (0)", ex.Message); Functions.ErrorsCounters.Increment (); // Archiwizuj pocztę mimo wszystko Logger.Log.Debug ("Archiwizuj wiadomość "); Logger.Archive.Info (Encoding.Default.GetString (client.GetMessageAsBytes (i + 1)));) if (_config.DeleteMail) client.DeleteMessage (i + 1); if (_stopPipeline) przerwa; ) Logger.Log.Debug ("Zakończono z" (0) "", info.User); )) catch (Exception ex) (Logger.Log.Error ("General error - type: (0), message: (1)", ex, ex.Message); Functions.ErrorsCounters.Increment ();))
Tutaj użyliśmy statycznych liczników błędów (pod względem typów pudełek), gdzie ErrorsCounters to:

Publiczny słownik statyczny ErrorsCounters \u003d nowy słownik ();
A same liczniki można zrobić w ten sposób:

Counter.cs

class Counter (private long _counter; public Counter () (_counter \u003d 0;) public void Increment () (Interlocked.Increment (ref _counter);) public long Read () (return _counter;) public long Refresh () (return Interlocked .Exchange (ref _counter, 0);) public void Add (long value) (Interlocked.Add (ref _counter, value);) public void Set (long value) (Interlocked.Exchange (ref _counter, value);))


Przejdźmy do tworzenia potoku. Powiedzmy, że mamy pola, w które wlewają się automatyczne odpowiedzi. Takie listy muszą zostać przeanalizowane (jaki rodzaj automatycznej odpowiedzi, od kogo, dla jakiej listy mailingowej itp.) I umieścić wynik w pamięci (DB). Powiedzmy, że są pola, w których spadają raporty FBL. Takie listy od razu dodajemy do bazy danych. Wszystkie inne litery uważamy za „przydatne” - należy je sprawdzić pod kątem spamu i przesłać do zewnętrznego systemu, na przykład CRM.

Jak już zrozumiałeś, ten przykład dotyczy głównie wykorzystania modułu zbierającego do zadań marketingowych - zbierania statystyk dotyczących dostarczania poczty, informacji o spamie.

Dlatego zdecydowaliśmy się na przepływ pracy. Deklarujemy niezbędne bloki w klasie Crawler:

Class MessageInfo (public bool IsSpam (get; set;) public Message Mail (get; set;) public string Subtype (get; set;) public string Recipient (get; set;) public MessageType Type (get; set;) public MailboxInfo Mailbox (get; set;)) class Crawler (// Pipeline private TransformBlock _sortMailDataBlock; prywatny TransformBlock _spamFilterDataBlock; prywatny TransformBlock _checkBounceDataBlock; prywatny TransformBlock _identifyDataBlock; prywatny ActionBlock _addToCrmDataBlock; prywatny ActionBlock _addToFblDataBlock; prywatny ActionBlock _addToBounceDataBlock; ...
Tworzymy metodę inicjalizacji i tworzymy bloki potoku (używamy naszych wspaniałych sekcji z konfiguracji do inicjalizacji bloków):

Public void Init () (// *** Create pipeline *** // Utwórz TransformBlock, aby uzyskać typ wiadomości var blockOptions \u003d _config.GetDataBlockOptions ("_ sortMailDataBlock"); _sortMailDataBlock \u003d new TransformBlock (mail \u003d\u003e SortMail (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity)); // Utwórz TransformBlock do filtrowania spamu blockOptions \u003d _config.GetDataBlockOptions ("_ spamFilterDataBlock"); _spamFilterDataBlock \u003d nowy TransformBlock (mail \u003d\u003e FilterSpam (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity)); // Utwórz TransformBlock do sortowania odrzuceń blockOptions \u003d _config.GetDataBlockOptions ("_ checkBounceDataBlock"); _checkBounceDataBlock \u003d nowy TransformBlock (mail \u003d\u003e BounceTypeCheck (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity)); // Utwórz TransformBlock, aby zidentyfikować właściciela odbicia blockOptions \u003d _config.GetDataBlockOptions ("_ identyfDataBlock"); _identifyDataBlock \u003d nowy TransformBlock (mail \u003d\u003e GetRecipient (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity)); // Utwórz ActionBlock, aby wysłać pocztę do CRM blockOptions \u003d _config.GetDataBlockOptions ("_ addToCrmDataBlock"); _addToCrmDataBlock \u003d nowy ActionBlock (mail \u003d\u003e AddToCrm (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity)); // Utwórz ActionBlock, aby wysłać FBL do MailWH blockOptions \u003d _config.GetDataBlockOptions ("_ addToFblDataBlock"); _addToFblDataBlock \u003d nowy ActionBlock (mail \u003d\u003e AddToFbl (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity)); // Utwórz ActionBlock, aby wysłać Bounce do MailWH blockOptions \u003d _config.GetDataBlockOptions ("_ addToBounceDataBlock"); _addToBounceDataBlock \u003d nowy ActionBlock (mail \u003d\u003e AddToBounce (mail), new ExecutionDataflowBlockOptions (MaxDegreeOfParallelism \u003d blockOptions.Maxdop, BoundedCapacity \u003d blockOptions.BoundedCapacity));
Przenośnik montujemy zgodnie z naszym schematem:

// *** Tworzenie potoku *** _sortMailDataBlock.LinkTo (_spamFilterDataBlock, info \u003d\u003e info.Type \u003d\u003d MessageType.GENERAL); _sortMailDataBlock.LinkTo (_addToFblDataBlock, info \u003d\u003e info.Type \u003d\u003d MessageType.FBL); _sortMailDataBlock.LinkTo (_checkBounceDataBlock, info \u003d\u003e info.Type \u003d\u003d MessageType.BOUNCE); _sortMailDataBlock.LinkTo (DataflowBlock.NullTarget (), info \u003d\u003e info.Type \u003d\u003d MessageType.UNKNOWN); / * STUB * / _checkBounceDataBlock.LinkTo (_identifyDataBlock); _identifyDataBlock.LinkTo (_addToBounceDataBlock); _spamFilterDataBlock.LinkTo (_addToCrmDataBlock, info \u003d\u003e! info.IsSpam); _spamFilterDataBlock.LinkTo (DataflowBlock.NullTarget (), info \u003d\u003e info.IsSpam); / * STUB * /
Jak widać wszystko jest niezwykle proste - łączymy blok z kolejnym (z możliwością ustawienia warunku połączenia). Wszystkie bloki są wykonywane równolegle. Każdy blok ma pewien stopień równoległości i pojemności (używając pojemności, można dostosować kolejkę przed blokiem, to znaczy, że blok otrzymał wiadomość, ale jeszcze nie jest przetwarzany). W ten sposób można ustawić wysoki stopień równoległości dla „złożonych” i czasochłonnych operacji, takich jak analiza treści wiadomości e-mail.

Nie będę opisywał materiału DataFlow, lepiej czytać wszystko w podstawowym źródle TPL DataFlow.

SortMailDataBlock.Completion.ContinueWith (t \u003d\u003e (if (t.IsFaulted) ((IDataflowBlock) _spamFilterDataBlock) .Fault (t.Exception); else _spamFilterDataBlock.Complete ();)); _sortMailDataBlock.Completion.ContinueWith (t \u003d\u003e (if (t.IsFaulted) ((IDataflowBlock) _addToFblDataBlock) .Fault (t.Exception); else _addToFblDataBlock.Complete ();)); _sortMailDataBlock.Completion.ContinueWith (t \u003d\u003e (if (t.IsFaulted) ((IDataflowBlock) _checkBounceDataBlock) .Fault (t.Exception); else _checkBounceDataBlock.Complete ();)); _spamFilterDataBlock.Completion.ContinueWith (t \u003d\u003e (if (t.IsFaulted) ((IDataflowBlock) _addToCrmDataBlock) .Fault (t.Exception); else _addToCrmDataBlock.Complete ();)); _checkBounceDataBlock.Completion.ContinueWith (t \u003d\u003e (if (t.IsFaulted) ((IDataflowBlock) _identifyDataBlock) .Fault (t.Exception); else _identifyDataBlock.Complete ();)); _identifyDataBlock.Completion.ContinueWith (t \u003d\u003e (if (t.IsFaulted) ((IDataflowBlock) _addToBounceDataBlock) .Fault (t.Exception); else _addToBounceDataBlock.Complete ();)); )
W rzeczywistości potok już działa, możesz wysyłać do niego wiadomości. Pozostaje tylko zatrzymać to, dodając naszą metodę Start:

Początek

public void Start () (do (var getMailsTasks \u003d _config.CredentialsList.Select (credentials \u003d\u003e Task.Run (() \u003d\u003e GetMails (credentials))). ToList (); foreach (var task in getMailsTasks) task.Wait ( ); Thread.Sleep (2000);) while (! _StopPipeline); // Zatrzymaj potok - poczekaj na zakończenie wszystkich punktów końcowych _sortMailDataBlock.Complete (); _addToCrmDataBlock.Completion.Wait (); _addToFblDataBlock.Completion.Wait (T); _addTlockBlockBlockBlock .Completion.Wait (); if (_stopPipeline) Logger.Log.Warn ("Potok został zatrzymany przez użytkownika");)


Przechodząc do delegatów.
Sortowanie ... Cóż, powiedzmy, że tutaj wszystko jest proste (zawsze mamy czas na komplikowanie):

Private MessageInfo SortMail (MessageInfo mail) (switch (mail.Mailbox.Type) (case MailboxType.Crm: mail.Type \u003d MessageType.GENERAL; break; case MailboxType.Bounce: mail.Type \u003d MessageType.BOUNCE; break; case MailboxType. Fbl: mail.Type \u003d MessageType.FBL; break;) return mail;)
Filtr spamu. To jest do pracy domowej - użyj SpamAssassin.
Oto delegat dla Ciebie:

Private MessageInfo FilterSpam (MessageInfo mail) (// TODO: Add SpamAssassin logic return mail;)
Oraz zajęcia do pracy z API SpamAssassin (link do projektu).
Przechodzimy do analizowania listów. Analizujemy odpowiedzi automatyczne. Tutaj pojawia się MEF.
Utwórz projekt (dll) z interfejsami dla naszych wtyczek (nazwijmy interfejsy).
Dodaj interfejs:

Interfejs publiczny ICondition (string Check (Message mimeMessage);) public interface IConditionMetadata (Type Type (get;))
I wszystko. Nasz TopCrawler jest zależny od tego projektu i projekt wtyczki również będzie go używał.
Utwórz nowy projekt (także dll), nazwij go Warunki.
Dodajmy typy automatycznych odpowiedzi:

#region --- Types --- klasa statyczna BounceType (public const string Full \u003d "BounceTypeFull"; public const string Timeout \u003d "BounceTypeTimeout"; public const string Refused \u003d "BounceTypeRefused"; public const string NotFound \u003d "BounceTypeNotFound"; public const string Inactive \u003d "BounceTypeInactive"; public const string OutOfOffice \u003d "BounceTypeOutOfOffice"; public const string HostNotFound \u003d "BounceTypeHostNotFound"; public const string NotAuthorized \u003d "BounceTypeNotAuthorized"; public const string # ManyTypeConnections)
I klasy implementujące nasz interfejs:

Public class ConditionNotFound1: ICondition (public string Check (Message mimeMessage) (if (! MimeMessage.MessagePart.IsMultiPart) return null; const string pattern \u003d "Diagnostic-Code :. + Smtp. + 550"; var regexp \u003d new Regex (wzorzec , RegexOptions.IgnoreCase); return mimeMessage.MessagePart.MessageParts.Any (part \u003d\u003e part.ContentType.MediaType \u003d\u003d "message / delivery-status" && regexp.IsMatch (part.GetBodyAsText ()))? BounceType: null ;)) ... public class ConditionTimeout2: ICondition (return BounceType.Timeout;) ...
Jak widać, chodzi o atrybuty. Za pomocą tych wtyczek zostaną załadowane.
Wracamy do naszego projektu i ładujemy wtyczki:

Class Crawler (... // Wtyczki public IEnumerable \u003e BounceTypeConditions (get; set;) private void LoadPlugins () (try (var container \u003d new CompositionContainer (new DirectoryCatalog (_config.PluginDirectory), true); container.ComposeParts (this);) catch (Exception ex) (Logger.Log .Error ("Nie można załadować wtyczek: (0)", np. Wiadomość);)) ...
Pobieramy LoadPlugins w konstruktorze naszej klasy. Nie będę szczegółowo wyjaśniał mechanizmu ładowania - Google poradzi sobie lepiej.

Przechodzimy do naszego delegata walidacji typu Bounce. Warunki będą obowiązywać kolejno, aż zostanie uruchomiony pierwszy z nich, metoda wyłączna:

Private MessageInfo BounceTypeCheck (MessageInfo mailInfo) (try (foreach (var condition in BounceTypeConditions) (var res \u003d condition.Value.Check (mailInfo.Mail); if (res \u003d\u003d null) continue; mailInfo.Subtype \u003d res; Logger.Log .Debug ("Warunek typu bounce [(0)] wyzwolony dla wiadomości [(1)]", condition.Metadata.Type, mailInfo.Mail.Headers.MessageId); break;)) catch (Exception ex) (Logger.Log .Error ("Nie udało się określić typu odesłania wiadomości" (0) ": (1)", mailInfo.Mail.Headers.MessageId, ex.Message); Logger.ErrorsCounters.Increment ();) return mailInfo;)
Jeśli więc pojawi się nowa logika, wystarczy dodać do projektu nową klasę z wtyczkami implementującymi nasz interfejs i - voila! Nie będę załączał przykładu drugiej wtyczki do ustalenia nadawcy listu - to już jest długi post (auto-odpowiedź została wygenerowana przez sam serwer, więc nadawca też musi zostać sparsowany z nagłówków wiadomości).

Nie ma nic niezwykłego w zapisywaniu wyników w bazie danych. Na przykład tak:

Private void AddToBounce (MessageInfo mail) (try (MailWH.BounceAdd (mail); Functions.ProcessedCounters.Increment (); Functions.Log.Debug ("Send Bounce to MailWH");) catch (Exception ex) (Functions.Log. Błąd („Błąd podczas zapisywania odesłanej wiadomości” (0) ”do MailWH: (1)”, mail.Mail.Headers.MessageId, ex.Message); Functions.ErrorsCounters.Increment ();))

BounceAdd

public static long BounceAdd (MessageInfo message) (using (var conn \u003d new SqlConnection (ConnectionString)) using (var cmd \u003d new SqlDataAdapter ("BounceAdd", conn)) (var body \u003d message.Mail.FindFirstPlainTextVersion () \u003d\u003d null? message.Mail.FindFirstHtmlVersion (). GetBodyAsText (): message.Mail.FindFirstPlainTextVersion (). GetBodyAsText (); var outId \u003d new SqlParameter ("@ ID", SqlDbType.BigInt) (Direction (Direction) \u003d ParameterDirection); .CommandType \u003d CommandType.StoredProcedure; cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ RawMessage", message.Mail.RawMessage)); cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ Message", body)) ; cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ Subject", message.Mail.Headers.Subject ?? "")); cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ MessageID", message.Mail .Headers.MessageId ?? "")); cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ AddressTo", message.Mail.Headers.To.Address ?? "")); cmd.SelectComm and.Parameters.Add (new SqlParameter ("@ AddressFrom", message.Mail.Headers.From.Address ?? „”)); cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ DateRecieved", DateTime.Now)); cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ BounceTypeSysName", (obiekt) message.Subtype ?? DBNull.Value)); cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ SourceFrom", (object) message.Recipient ?? DBNull.Value)); // TODO: Dodaj obsługę ListId cmd.SelectCommand.Parameters.Add (new SqlParameter ("@ ListId", DBNull.Value)); cmd.SelectCommand.Parameters.Add (outId); conn.Open (); cmd.SelectCommand.ExecuteNonQuery (); return outId.Value as long? ?? 0; ))


Przepraszamy, że nie mam czasu, aby pokazać TopShelf - post jest już zbyt nadęty.

wnioski

Z tego samouczka dowiedzieliśmy się, że zbieranie poczty może być trudne. Opracowany rdzeń pozwala na szybkie dodawanie nowych kroków procesu - bloków DataFlow, bez wpływu na istniejącą logikę. Podsystem wtyczek pozwala na szybkie tworzenie logiki parsowania podobnej do skryptu, a sam DataFlow wykonuje wszystkie obliczenia równolegle (i mamy możliwość elastycznej konfiguracji wielowątkowości dla określonej maszyny). TopShelf daje nam możliwość uruchamiania usługi zarówno w trybie serwisowym, jak iw trybie konsoli, co ułatwia debugowanie.

Moim zdaniem Gmail ma jeden z najbardziej przyjaznych dla użytkownika interfejsów internetowych do pracy z pocztą e-mail. Oprócz przyjemnego i wygodnego interfejsu twórcy nie zapomnieli o części funkcjonalnej. Rozmowy, tworzenie różnych folderów, filtrów itp. Wszystko to sprawiło, że Gmail stał się jedną z najpopularniejszych usług pocztowych na świecie. Wiele osób nie wie o tak wspaniałej funkcji jak kolektor poczty. Na przykład masz co najmniej jedną skrzynkę pocztową w nazwie swojej domeny, ale standardowy interfejs poczty internetowej i klienty pocztowe Ci nie odpowiadają ( Mozilla Thunderbird, Microsoft Outlook, The Bat). W takim przypadku możesz użyć narzędzia do zbierania poczty i przetwarzać całą pocztę za pośrednictwem Gmaila, teraz przyjrzymy się, jak to zrobić.

  1. Potrzebujesz konta Gmail, proces rejestracji jest dość prosty i myślę, że nie będzie trudno to rozgryźć.
  2. Po rejestracji w Gmailu musisz przejść do ustawień
  3. W ustawieniu wybierz element „Konta i importowanie”

  4. W tej sekcji interesują nas dwa punkty: „Wyślij e-maile jako:” i „Sprawdź pocztę na innych kontach (używając POP3):”. Znajdują się na nich linki „Dodaj własny adres e-mail” i „Dodaj własne konto pocztowe POP3”.

  5. Aby odebrać pocztę z innej skrzynki pocztowej, kliknij „Dodaj swoje konto pocztowe POP3”. Pojawi się nowe okno, w którym należy wpisać adres skrzynki pocztowej i kliknąć „Dalej”. Następnie pojawia się kilka pól, które należy wypełnić:
    Nazwa Użytkownika
    Hasło
    Serwer i port POP - Adres serwera POP i port do łączenia się z serwerem, z którego będzie pobierana poczta. Możesz znaleźć te informacje we wsparciu swojej usługi pocztowej, zwykle są one publikowane w sekcji „Pytania i odpowiedzi”.
    Zapisuj kopie otrzymanych wiadomości na serwerze - jeśli pole nie jest zaznaczone, po pobraniu listów te litery zostaną usunięte ze skrzynki. ...
    Zawsze korzystaj z bezpiecznego połączenia (SSL) podczas odbierania wiadomości e-mail - należy zainstalować, jeśli Twoja usługa pocztowa korzysta z bezpiecznego połączenia SSL do pracy.
    Przypisz skrót do wiadomości przychodzących - etykieta to wizualny znak obok litery. Jest wygodny w użyciu do zrozumienia, do której skrzynki pocztowej został wysłany list.
    Archiwizuj przychodzące e-maile (pomiń przychodzące) - listy odebrane z tej skrzynki zostaną zarchiwizowane, nie trafią do skrzynki odbiorczej.

  6. Kliknij „Dodaj konto”, po czym Gmail wyśle \u200b\u200blist weryfikacyjny do określonej skrzynki pocztowej. W liście będą dwie opcje weryfikacji, link i kod. Wystarczy kliknąć łącze i wkleić kod w polu potwierdzenia. Łatwiej jest podążać za linkiem, kod najwyraźniej jest wysyłany na wszelki wypadek, nagle link zostanie nieprawidłowo wyświetlony w liście.
  7. Cóż, to wszystko, teraz nasze konto Gmail automatycznie zbiera listy z innej skrzynki pocztowej. Jeśli istnieje potrzeba odpowiedzi z tego lub innego adresu przy użyciu tego samego Gmaila, w ustawieniach kliknij link „Dodaj kolejny adres e-mail” Wypełnij pola:
    "Imię:" - możesz wprowadzić dowolne dane, na przykład swoje imię i nazwisko.
    „Adres e-mail:” - wskazujemy adres pocztowy, w imieniu którego będziemy odpowiadać.
    Znacznik wyboru "Użyj jako aliasu ”.- ten adres będzie używany jako alias dla Twojego głównego adresu i wysyłając na niego list, będzie on wyświetlany w Twojej skrzynce odbiorczej, szczegółowo opisanej w pomocy google pod linkiem „Więcej ...”.
    Wprowadź inny adres w polu „Odpowiedz” (opcjonalnie) - domyślnie odpowiedź przychodzi na ten sam adres, który został użyty do wysłania. Klikając w link, możesz określić inną skrzynkę pocztową, na którą będą dostarczane listy wysyłane na ten adres.
    Kliknij Następny"

  8. Następnie widzimy kilka dodatkowych pól, które należy wypełnić.
    Serwer i port SMTP - informacje te należy uzyskać na poczcie.
    Nazwa Użytkownika - zwykle jest to adres e-mail, to jest login dostępu do skrzynki pocztowej.
    Hasło - hasło dostępu do skrzynki pocztowej.
    Bezpieczne połączenie za pomocą TLS (zalecane) i bezpieczne połączenie za pomocą SSL - drugą opcję (SSL) można wybrać tylko wtedy, gdy Twoja usługa pocztowa korzysta z tego typu bezpiecznego połączenia. Zasadniczo możesz wybrać pierwszą pozycję.

    Po kliknięciu „Dodaj konto” zostanie wysłany list weryfikacyjny, podobnie jak dodanie skrzynki pocztowej do odbioru poczty. Potwierdzamy i gotowe.

Cóż, właściwie to wszystko, w ten sposób możesz skonfigurować zbieranie listów i odpowiedzi z innych skrzynek pocztowych za pośrednictwem Gmaila. Mały niuans, harmonogram zbierania poczty z innych skrzynek pocztowych jest tworzony przez Gmaila niezależnie, osobno dla każdej takiej skrzynki. Oznacza to, że wysłany list na skrzynkę pocztową, z której odbierasz pocztę, nie zostanie natychmiast wyświetlony w skrzynce odbiorczej w interfejsie Gmaila, ale dopiero po weryfikacji. Częstotliwość sprawdzania zależy od liczby i częstotliwości przychodzących listów na tę skrzynkę pocztową, im częściej listy są odbierane, tym częściej czek będzie się odbywał. Nie możesz w żaden sposób zmienić tego parametru, ale w ustawieniach możesz wymusić rozpoczęcie skanowania.