wysyłanie maila z notyfikacją

Przepraszam za pytanie na granicy OT, ale zastanawia mnie pewna kwestia:

Jak w najprostszy sposób wysłać maila z jakaś informacją z poziomu programu napisanego w C, działającego pod Raspberry Pi? W internecie znajduję mnóstwo przykładów dotyczyących Pythona albo PHP, pod C już trochę trudniej.

Do głowy przychodzi mi kilka rozwiązań, m.in.:

1) Napisanie własnej procedury, implementującej protokół SMTP i wykorzystującej socket TCP. 2) Skorzystanie z jakiegoś klienta e-mail obsługiwanego z poziomu konsoli i wywoływanie go przez system().

A może dałoby się to zrobić bardziej elegancko? Jakaś gotowa biblioteka, udostępniająca odpowiednią funkcję? Albo program, który udostępniałby w systemie odpowiedni plik, do którego mógłbym pisać wysyłając wiadomość?

Reply to
Atlantis
Loading thread data ...

Użytkownik Atlantis napisał:

Nie znam C, czy w tym języku nie da się wywołać programu z niezbędnymi parametrami?

Reply to
AlexY

W dniu 2014-08-23 12:00, AlexY pisze:

Właśnie podał sposób - przez system(). Ale Atlantisowi nie chodzi o wywoływanie zewnętrznych programów.

Nie mam doświadczenia praktycznego, ale w zebranych materiałach do RPi mam: libESMTP i libquickmail.

Reply to
Michał Lankosz

A po co C? nc (netcat) nie może być?

Reply to
Marek

Pan Michał Lankosz napisał:

Te zewnętrzne programy, to nie w czym innym napisane, jak w C. Jak ktoś się uprze, to sobie może uwewnętrznić.

Ale tu w ogóle nic do roboty nie ma -- wystarczy przygotować treść maila z nagłówkami i wysłać to na port 25 swojego serwera. Ktoś już zauważył, że dobrze do tego się nadaje netcat (nc) -- też napisany w C, więc każdy może sobie zobaczyć, jak to robi.

Jak sie nie chce zgłębiać RFC, można zajrzeć na przykład tu (pierwsze trafienie google)

formatting link

Reply to
invalid unparseable

Użytkownik Michał Lankosz napisał:

[..]

No to musi wyważać otwarte drzwi czyli jak Jarek napisał wstawić program pocztowy w swój program, IMHO bez sensu.

[..]
Reply to
AlexY

W dniu 2014-08-23 15:10, Jarosław Sokołowski pisze:

Hmm... Wystarczy po prostu wysłać kolejne linie jednym ciągiem, bez sprawdzania odpowiedzi serwera? No i czy istnieją jeszcze jakieś publiczne serwery SMTP, które umożliwiałyby wysłanie wiadomości bez autoryzacji?

Reply to
Atlantis

Ale chwila, chcesz wysyłać maile jawnie (znany serwer, oficjalny dostęp) czy chcesz spamować szukając open relay'e? Bo w pierwszym przypadku 99% wszystko zadziała a w drugim trzeba weryfikować komunikację. Analizując output netcata i kody odp. smtp możesz stwierdzić czy wystąpił jakiś problem. Protokoły komunikacyjne aplikacji stworzone za czasów wczesnego internetu są human readable & friendly, wystarczy umiejętność czytania :), przez co są łatwe implementacyjnie.

Reply to
Marek

Większość umożliwia PLAIN lub LOGIN, wygeneruj sobie string auth (albo podejrzyj tcpdumpem komunikację lnormalnego klienta by ten string wyciągnąć) i dodaj do skryptu podczas komunikacji z serwerem.

Reply to
Marek

Trochę napisałem na wyrost, nie do końca może to działać z każdym serwerem. Jeśli na serwerze jest zaimplementowana silna ochrona antyspamowa np. greeting pause to od klienta wymaga się precyzyjnej (rfc strict) komunikacji, nie pamiętam czy netcatem da się zaimplementować oczekiwanie na odp., wysyłanie sesji "ciurkiem" może nie zadziałać.

Reply to
Marek

Hmm... Doczytałem trochę i udało mi się napisać prostą funkcję.

Najpierw w taki sposób przesyłam kolejne polecenia: rc = send(sd, "AUTH LOGIN\n", strlen("AUTH LOGIN\n"), MSG_WAITALL); rc = recv(sd, ans, sizeof(ans), 0); if (rc > 0) { ans[rc] = '\0'; puts(ans); }

Udało mi się w ten sposób przejść całą procedurę uwierzytelniania oraz ustawiania adresów nadawcy i odbiorcy. Potem przechodzę do "DATA".

sprintf(buffer, "DATA\nFROM: snipped-for-privacy@host.pl\nTO: <%s>\nSUBJECT: TO JEST TEMAT TEGO MAILA\nA TO JEST JEGO TRESC\r\n.\r\n", to); rc = send(sd, buffer, strlen(buffer), MSG_WAITALL); rc = recv(sd, ans, sizeof(ans), 0); if (rc > 0) { ans[rc] = '\0'; puts(ans); }

Niestety taka konstrukcja działa tylko połowicznie. To znaczy dochodzi mail z określonym tematem, ale bez treści. Błąd zapewne jest banalny, ale ja nie mogę go dostrzec. O co może chodzić?

Reply to
Atlantis

tu dodaj jeszcze jedno \n - ma być pusta linia pomiędzy nagłówkami, a treścią

Reply to
A

Dnia Sun, 24 Aug 2014 15:59:29 +0200, Atlantis napisał(a):

\n\n przed treścią.

Reply to
Borys Pogoreło

  1. Serwer czy net może być niedostępny (timeout czy connection refused)
  2. Serwer może mieć trudne chwile i odpowie Ci 450
  3. Filtr antyspamowy nie polubi Ci 'SUBJECT' zamiast 'Subject', braku nagłówków czy np. złego kodowania.

Wyślij to normalnie przez system() i niech demon poczowy na Linuksie się tym martwi. Chyba nie będziesz pisał demona na nowo? Co z chwilowymi problemami (1.,2.)? Skolejkujesz sam gdzieś tego maila czy stracisz?

Na Linuxie naprawdę nie ma sensu wynajdować koła od nowa, bo szkoda czasu i zawsze się okaże, że jakiś serwer odpowie Ci trochę inaczej, ale zgodnie z RFC i program się wyłoży. Albo przytrzyma Ci połączenie (czy sieć padnie w tym momencie) i program się powiesi do wytimeoutowania sesji tcp. No chyba, że wysyłasz asynchronicznie w osobnym wątku czy podprocesie, ale wtedy jak poforkujesz się dla każdego maila znowu musisz kontrolować pamięć/zasoby i ilość procesów itd...

Rozumiem, żebyś rzeżbił na Arduino, ale tu masz wszystko gotowe, przetestowane i działające.

Pozdrawiam

Marek

Reply to
Marek Wodzinski

W dniu 2014-08-26 00:01, Marek Wodzinski pisze:

Hmm... W tej chwili funkcja załatwia tylko podstawową komunikację z serwerem przy przesyłaniu i zwraca 1 w przypadku sukcesu albo kod błędu, gdy coś poszło niezgodnie z planem. W tej chwili kody błędu opierają się tylko na niepowodzeniu wywołań kolejnych send() i recv(). Planowałem jednak dodać jeszcze parsowanie odpowiedzi serwera. Jednak chyba masz rację...

Jaki daemon pocztowy mógłbyś polecić? I jak wygląda obsługa odpowiedniego konta? Wywołuje się je z linii poleceń, czy tożsamość jest odgórnie skonfigurowana i zależy od użytkownika, który uruchomi program wywołujący daemona?

Kod pisałem pod konkretny serwer, nawet dane uwierzytelniające są hardkodowane z źródle. Chodziło mi też eksperyment mający na celu przybliżenie zasady działania poczty e-mail.

Przyzwyczajenia... Programowania uczyłem się na AVR-ach. ;)

Reply to
Atlantis

Zależy do czego potrzebujesz i jak bardzo szanujesz zasoby:-) I czy w przyszłości maszynka sama ma wysyłać maile od razu na świat czy zawsze tylko przez jakiś serwer.

Podobno msmtp jest prosty, mały i dobry, ale jakoś zawsze używałem 'pełnych' demonów - zaleta jest taka, że łatwiej jest poznać i znaleźć pomoc do jednego popularnego programu niż fajnego, małego, ale egzotycznego. Jak nie liczysz każdego bajtu czy mikrosekundy na obsługę maila, to zazwyczaj wystarcza to co dostajesz w dystrybucji.

Jeżeli chcesz słać wszystko przez zewnętrzny serwer, to w konfiguracji demona. Zależy jaki masz lub zainstalujesz. Podobno w Raspbianie jest exim defaultowo, więc może już coś masz nawet zainstalowane albo i uruchomione :-)

Wysyłanie wywołujesz z linii poleceń, treść maila zazwyczaj wrzucasz na stdin.

To trochę inaczej się odbywa. Zazwyczaj masz demona do poczty (mta), który działa cały czas lub uruchamiany jest czasem z crona (rzadziej). On sprawdza czy coś ma w kolejce do wysłania i to ewentualnie wysyła.

Natomiast jak chcesz wysłać maila, to wywołujesz inny program (czasem ten sam, ale z innymi opcjami), który weźmie tego maila, wstępnie sprawdzi co próbujesz wysłać i wrzuci do kolejki demonowi.

Tożsamość (w sensie ustawienia autoryzacji i serwera) konfigurujesz demonowi o ile nie wysyłasz sam od razu na świat. Wtedy on może wysłać maila dalej używając tej konfiguracji. Mta to taki router - sam podejmuje decyzje co zrobić z dostanym mailem. Czasem możesz mu wymusić, żeby słał wszystko lub część poczty (np. w zależności od nadawcy czy odbiorcy) przez określonego relaya. Dlatego też raczej nie ma szans, że określisz dodatkowe parametry relaya w czasie wrzucania maila do kolejki.

Taki hint już do wysyłania: możesz wywołać 'mail' używając jego switchy, żeby dodać dodatkowe nagłowki. Ale ponieważ praktycznie każdy mta ma tryb udawania sendmaila (jednego z najstarszych demonów), to niezależnie czy będziesz miał exima, postfixa, sendmaila czy coś tam jeszcze, to zawsze powinno się dać wywołać 'sendmail -t' i wrzucić na stdin całego maila z nagłówkami. Wtedy 'sendmail' sam sobie znajdzie From:, To:, Cc, Bcc (to ostatnie też grzecznie usunie) i zrobi z tym co trzeba. Osobiście używam opcji z sendmail -t :-)

Czasem serwer się zmienia, czasem chcesz udostępnić program komuś. W Linuksie najlepiej jak system tym się zajmie, a nie sama aplikacja. Czasem robi to aplikacja, ale często są to już potworki w językach skryptowych z opasłymi i sprawdzonymi bibliotekami. A i tak często taka biblioteka ma jako fallback wysłanie 'normalnie'.

Przydaje się też czasem wiedzieć jak wysłać maila telnetem czy netcatem :-)

Pozdrawiam

Marek

Reply to
Marek Wodzinski

W dniu 2014-08-26 16:22, Marek Wodzinski pisze:

Exim4 musiałem zainstalować, ale nie mogę sobie poradzić z konfiguracją. Co jest z nim nie tak, że z uporem maniaka w miejscu FROM: wstawia adres utworzony z LOKALNEJ nazwy użytkownika i hosta, przez co mail jest odrzucany przez serwer. Tak samo przy EHLO podaje nazwę maszyny (raspberrypi) zamiast tpnet.pl. Można go jakoś nauczyć prawidłowego wysyłania maili?

SSMTP zachowuje się dokładnie tak samo...

Reply to
Atlantis

Zapomniałem o jednej opcji :-) sendmail - snipped-for-privacy@domena.com -t Inaczej w 'kopercie' użyje właśnie danych z systemu. Dobrze jeszcze dopisać do trusted_users użytkownika, który będzie wysyłał tego maila - sendmail dodaje dodatkowy nagłówek, że user coś kombinuje, nie wiem jak exim.

W EHLO serwer przedstawia się swoją nazwą. W zasadzie serwery są przyzwyczajone, że klient bzdurnie się przedstawia. Jeżeli dalej autoryzujesz się, to nie ma to znaczenia. Jeżeli wysyłasz bezpośrednio, to niektóre sprawdzają czy hostname jest prawidłowy (istnieje). Częściej sprawdza się czy jednak nie ustawiasz takiego EHLO jak nazwa/ip serwera z którym się łączysz - to akurat często jest w spamie. Czyli tym bym się nie przejmował tak długo jak maile będą dochodzić. Sam często testuję przez 'EHLO dupa' :-)

Pozdrawiam

Marek

Reply to
Marek Wodzinski

W dniu 2014-08-26 22:53, Marek Wodzinski pisze:

Wydaje mi się, że to ma znaczenie, przynajmniej w przypadku Interii. Gdy próbowałem wysyłać maile przez telnet, serwer nie przyjmował innego EHLO jak tylko tpnet.pl. W przeciwnym razie w pewnym momencie wywalał komunikat błędu...

Właśnie nie dochodzi. Nie mogę tego normalnie skonfigurować... Udało mi się już ustawić alias - tak więc mam prawdziwy e-mail przypisany do nazwy użytkownika w systemie. Ciągle jednak nie jestem w stanie wysłać wiadomości...

mail -s "Test" snipped-for-privacy@gwp.pl -v

Wśród zwróconych treści znajduje się:

SMTP>> EHLO raspberrypi

oraz

SMTP<< 554 5.7.1 <******.*******.****.tpnet.pl[***.***.***.***]>: Client host rejected: Access denied

Reply to
Atlantis

Atlantis snipped-for-privacy@wp.pl napisał(a):

To jest cała komunikacja? 554 to odpowiedź na EHLO? Jeśli nie, to wklej całość. Gwiazdkować nie musisz, bo i tak widać Twój adres w nagłówkach. Z jakim serwerem się łączysz i na jakim porcie? Ja ostatnio zrobiłem wysyłanie na socketach w C i nie było problemu na WP. EHLO podawałem wymyślone. Skoro wysyłasz do gwp.pl, to serwerem SMTP jest smtp1.apnet.pl. No chyba, że to pomyłka i wysyłasz do wp.pl. Mi się to gwp to EHLO nie przyczepia: grzegorz@jabber:~$ telnet smtp1.apnet.pl 587 Trying 213.76.170.4... Connected to smtp1.apnet.pl. Escape character is '^]'.

220 apnet.pl ESMTP EHLO elektronika 250-apnet.pl 250-STARTTLS 250-PIPELINING 250-8BITMIME 250-SIZE 0 250 AUTH LOGIN PLAIN QUIT 221 apnet.pl Connection closed by foreign host.
Reply to
Grzegorz Niemirowski

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.