Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Odbieranie poczty, załącznik
Forum PHP.pl > Forum > PHP
mhs
Witam,

mam do napisania skrypt, który będzie łączył się z dowolnym serwerem pocztowym, następnie pobierał e-maile, w których będą zapisane pliki CSV. Pliki te będę musiał odczytać i zapisane w nich dane odpowiednio obrobić. O ile z tym ostatnim nie będzie problemu to za bardzo nie wiem jak mam odebrać pocztę z serwera i w jaki sposób wydobyć z maili załączniki.

Będę wdzięczny za wszelkie wskazówki.

Pozdrawiam.
LBO
IMAP, POP3 and NNTP Functions
slash12345
Ten gość chyba szuka pomocy z pop3, IMAP nie jest zbyt praktyczny.
To zagadnienie wykracza poza ramy php, jednak postaram się pomóc. Po pierwsze, wymagana jest znajomość protokołu pop3 (komendy możesz znaleźć poniżej). Wydawać je można po podłączeniu się do serwera pop3 (zakładam, że autor tematu potrafi otwierać połączenie i komunikować się z nim).

Kod
USER x - podaje nazwę użytkownika x
PASS x - podaje hasło x dla użytkownika (wcześniej użyj USER)
LIST - zwraca listę wiadomości w formacie [numer] [wielkość w bajtach]
------przykład listy---
0 6073
1 80337
-------------------------
RETR x - zwraca wiadomość o numerze x
DELE x - usuwa wiadomość o numerze x z serwera


Po wysłaniu RETR w celu otrzymania wiadomości, ekran (ewentualnie strumień wyjściowy) zostanie zasypany danymi, które nierzadko są zakodowane z użyciem base64. W celu ich przetworzenia (gdybyśmy nie znali kodowania na pamięć, ach ta skleroza) należy najpierw sprawdzić nagłówki listu (które nie są kodowane chyba że osoba wysyłająca była wariatem). Jeśli natkniemy się na base64-encoded lub podobny ciąg, mozna użyć funkcji base64_decode(). Należy jednak pamiętać o uprzednim rozbiciu e-maila na segmenty używając np. funkcji explode(). Całe zagadnienie jest dosyć skomplikowane, szczególnie jeśli chodzi o przetwarzanie załączników (też gdzieś w nagłówkach, potem trzeba wyłapywać bloki danych i rozpoznawać jako pliki).
mhs
@slash12345 - Dzięki za odpowiedz - chyba właśnie o to mi chodziło.

Cytat
(zakładam, że autor tematu potrafi otwierać połączenie i komunikować się z nim).

No właśnie nie do końca umiem, ale coś pogrzebałem po sieci i napisałem coś takiego:

  1. <?php
  2. host = '';
  3. $user = '';
  4. $haslo = '';
  5.  
  6.  
  7.  
  8. $fs = fsockopen($host, 110);
  9.  
  10. if ($fs) {
  11.  
  12. echo fgets($fs, 128) . '<br />';
  13.  
  14. fputs($fs, "USER $user\n");
  15.  
  16. echo fgets($fs, 128) . '<br />';
  17.  
  18. fputs($fs, "PASS $haslo\n");
  19.  
  20. echo fgets($fs, 128) . '<br />';
  21.  
  22.  fputs($fs, "LIST\n");
  23.  
  24.  echo fgets($fs, 128) . '<br />';
  25.  
  26. fputs($fs, "RETR 5\n");
  27.  
  28. // jak wyswietlic liste wiadomosci oraz pozniej tresc wybranej wiadomosci?
  29.  
  30. }
  31. else {
  32. echo 'false';
  33. }
  34. ?>


Teraz stanąłem przed problemem, w jaki sposób wyświetlić listę wiadomości lub też samą treść e-maila (po wybraniu go za pomocą RETR. Próbowałem coś za pomocą fread, ale w przypadku wiadomości nie zczytywał mi jej całej - do końca. Będę wdzieczny za każdą wskazówke lub fragment pomocnego kodu.

Bo jak rozumiem, później już pozostanie mi tylko to co się "wyświetli" obrobić - odstać się do załącznika (najprawdopodobniej nie będzie on kodowany) i już pozostanie mi jego obróbka - zgadza się?

Jeszcze raz dzięki za pomoc,
Pozdrawiam.
slash12345
Problem leży zapewne w samym odczytywaniu. Strumień zachowuje się bardzo podobnie do pliku, więc możliwe, że funkcja odczytująca "brała" za mało znaków. Polecam zastosowanie feof(). Skrypt został podzielony na dwie części, żeby umożliwić wprowadzenie danych. Nie testowalem go, ale powinien dzialac.
  1. <?php
  2. /*
  3. Podrecznik funkcji:
  4. string FetchMyMail( string $host, string $user, string $pass, string $postfield = "nrwiad" );
  5. --Funkcja za pierwszym wywolaniem (gdy nie ma danych z formularza), wyswietla formularz
  6. z lista wiadomosci (niestety bez tematow, gdyz wymagaloby to odczytania calej wiadomosci),
  7. a nastepnie (gdy podamy dane), zwraca tresc wiadomosci. 
  8. Parametr $postfield okresla nazwe pola, z ktorego bierzemy ewentualny numer wiad
    omosci
  9. do pobrania.
  10. */
  11. function FetchMyMail($host,$user,$pass,$postfield="nrwiad")
  12. {
  13. $pol = fsockopen($host,110);
  14. //Uzycie \r\n dla pelnej zgodnosci, nie powinno przeszkadzac
  15. fgets($pol);
  16. fputs($pol,"USER {$user}\r\n");
  17. fgets($pol);
  18. fputs($pol,"PASS {$pass}\r\n");
  19. $resp[0] = fgets($pol,1024); //pobieramy 1 KB danych i umieszczamy w tablicy kodow odpowiedzi
  20. if (substr($resp[0],0,3) !== "+OK") die("Błąd autoryzacji."); //sprawdzamy czy wszystko idzie jak nalezy
  21. //WPROWADZENIE DANYCH
  22. if (!isset($_POST[$postfield]))
  23.  {
  24. fputs($pol,"LIST\r\n");
  25. fgets($pol);
  26. $msgtemp = stream_get_contents($pol);
  27. $msglist = explode("\n",$msgtemp);
  28. foreach ($msglist as $mlk => $mlv) { if ($mlv == "" || $mlv == " " || $mlv == ".") unset($msglist[$mlk]); }
  29. $rstr = "<form action='plik.php' method='POST'>Numer wiadomości do pobrania:<br /><select name='nrwiad'>";
  30. //Linie powyzej mozesz zmienic, nazwe pola przekazujemy jako czwarty parametr funk
    cji
  31. foreach ($msglist as $msk => $msv)
  32.  {
  33. $mnum = substr($msv,0,strpos($msv," ")); //wydobywamy liczbe porzadkowa
  34. $rstr .= "<option value='{$mnum}'>{$msv}</option>\n";
  35.  }
  36. $rstr .= "</select><input type='submit' value='Pobierz!'></form>";
  37. print($rstr); //zamiast print() mozesz dac return, skrypt jest zaprojektowany dla latwosci edycji
  38.  }
  39. else
  40.  { //LUB ZWRACANIE MAILA
  41. fputs($pol,"RETR {$_POST[$postfield]}\r\n");
  42. $mstr = ""; //ta zmienna bedzie napelniona wiadomoscia
  43. $mstr = stream_get_contents($pol);
  44. return $mstr;
  45.  }
  46. /* to ponizej mozesz wyjac z komenta, ale i tak nie robi nic pozytecznego...
  47.  fputs($pol,"QUIT\r\n");
  48.  fclose($pol); */
  49. }
  50. ?>

Mam nadzieję, że wskazówki okażą się pomocne.
A teraz: ilu nawiasów i średników zapomniałem?
EDIT: Zmieniłem trochę ten skrypt, poprzednio wykonanie zajmowało około 30 sekund... dopóki nie
otrzymywaliśmy timeouta. Teraz niestety działa tylko w PHP5. W celu uzyskania kompatybilności trzeba by znaleźć funkcję podobną do stream_get_contents lub napisać własną. Testowane przez matracha, podobno działa.
mhs
Dzięki za napisanie tego skryptu. Na jego podstawie przygotowałem własny dzięki czemu mogę już odczytać treść maila. W chwili obecnej mam jeden (przynajmniej na razie) problem. Treść maila, który odczytuję jest mniej więcej taki:

Kod
X-From_: ******** Fri Apr 21 21:53:22 2006
Return-Path:

...
Kod
From: =?iso-8859-2?B?TWljaGGzIEh5v3k=?=
To:
Date: Fri, 21 Apr 2006 21:52:48 +0200
MIME-Version: 1.0
Content-Type: multipart/mixed;


...

Kod
This is a multi-part message in MIME format.

------=_NextPart_000_0003_01C6658D.EFEA9480
Content-Type: text/plain;
    charset="iso-8859-2"
Content-Transfer-Encoding: 7bit


------=_NextPart_000_0003_01C6658D.EFEA9480
Content-Type: application/vnd.ms-excel;
    name="MD_06042001.CSV"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
    filename="MD_06042001.CSV"


....

Kod
Agent;Miejscowosc;Ulica;Kod pocztowy;Wojewodztwo;Godziny otwarcia
D.H. Stokrotka;Bardo;ul. G=B3=F3wna =
11;57-256;Dolno=9Cl=B9skie;06:00-21:00
Sklep Miros=B3aw Ustupski;Bardo;ul. Potwor=F3w =
29;57-256;Dolno=9Cl=B9skie;07:00-20:00
Sklep Spo=BFywczo-Przemys=B3owy Dana;Bardo;ul. Fabryczna =


....

O o dostanie się do pliku nie będzie większym problemem, to w chwili obecnej mam problem z prawidłowym odczytaniem polskich znaków w treści załącznika. To co pokazuje mi się w przeglądarce to jedna wielka sieczka. Próbowałem jakis kombinacji z iconv, ale nie udało się nic zrobić. Czy jest jakiś sposób na prawidłowe "przeczytanie" załącznika? Proszę raz jeszcze za podpowiedź. Z góry dziękuję.

Pozdrawiam.
slash12345
Może jest to aż zbyt proste rozwiązanie, ale popatrz trochę na sekwencje znaków w treści. O ile nie jest zapisana bitowo, możesz odgadnąć, jakie słowo jest zapisane. Następnie przygotuj tablicę (array) sekwencji i użyj funkcji strtr w pokazany niżej sposób:
  1. <?php
  2. //zakladamy, ze zmienna tresc przechowuje tresc pliku/wiadomosci/czegokolwiek
  3. $zam["=B3"] = "ł";
  4. //i tak dalej......
  5. $tresc = strtr($tresc,$zam);
  6. ?>

W takim przypadku ciąg "=B3" ze słowa "G=B3=F3wna" zostanie zamieniony na "ł", podobnie jak w "Miros=B3aw". Możliwe, że ma to jakiś związek z kodami szesnastkowymi znaków.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.