E-maile w PHP

Obecnie funkcja wysyłania e-maili jest używana praktycznie w większości większych serwisów opartych na systemie dynamicznego generowania stron. W tym artykule opiszemy w jaki sposób posługiwać się funkcją mail() standardowo dostępną w PHP jak i bardziej zaawansowanym systemem - mianowicie gniazdkami.

Funkcja mail()


Wysyłanie e-maili z poziomu PHP jest niesamowicie proste. Wystarczy bowiem użyć wbudowanej funkcji mail(), która upraszcza całą sprawę. Oto sposób jej użycia:

bool mail ( string to, string subject, string message [, string additional_headers
 [, string additional_parameters]])


Oznaczenie parametrów:

  • to - adres e-mail odbiorcy e-maila
  • subject - temat wiadomości
  • message - treść wiadomości
  • additional_headers - dodatkowe nagłówki (parametr opcjonalny)
  • additional_parameters - dodatkowe parametry przekazywane do SendMaila (parametr opcjonalny)


Przykładowe użycie funkcji mail() wygląda tak:

mail('mail@serwer.com', 'Temat', 'Treść');


Jest to najprostsze z możliwych wywołań tej funkcji. Spowoduje wysłanie e-maila o treści 'Treść' z tematem 'Temat' pod adres 'mail@serwer.com'.

Co do nagłówków: aby dokładnie zrozumieć zasadę dodawnia nagłówków należy zapoznać się ze specyfikacją
wysyłania e-maili np. tutaj: http://www.faqs.org/rfcs/rfc1896.

Przykładowo: możesz dodać nagłówek 'From', który oznacza nadawce listu.

mail('mail@serwer.com', 'Temat', 'Treść'
          'From: Adam Boduch <adam@boduch.net>\r\n
           Reply-To: Adam Boduch <adam@boduch.net>\r\n'
);

           
W powyższej instrukcji do e-maila zostaną dołączone nagłówki 'From' oraz 'Reply-To' (adres zwrotny). Nie zaszkodzi
także ustawić nagłówka 'Return-Path' czyli adresu na który zostanie odesłany list w razie, gdy np. skrzynka
odbiorcy nie istnieje. Uwaga! Poszczególne nagłówki e-maili muszą być oddzielone od siebie znakami \r\n
aczkolwiek na systemach typu Unix może działać także, gdy nagłówki będą oddzielone znakiem \n.

Używanie gniazdek


Na wielu serwerach funkcja mail() jest blokowana przez administratorów. Z różnych względów - np. ze względu na obciązania serwera, w przypadku wysyłania dużej ilości listów lub możliwość rozsyłania spamu. Dobrym
sposobem jest wykorzystanie gniazdek w celu przesłania listu. Chociaż jest to metoda bardziej czasochłonna, ale
pozwala na połączenie się z dowolnym serwerem i wysłanie z tego serwera listu. W artykule przedstawimy prostą klasę, która umożliwi połączenie się z serwerem i wysłania e-maila.

Aby wysłać e-maila z konkretnego serwera należy się z nim połączyć (najczęściej na porcie 25) oraz przekazać mu zrozumiałe dla niego komendy - np.

HELO mail.swerer.pl\r\n
MAIL FROM: <adres@serwer.pl>\r\n
RCPT TO: <odbiorca@serwer.pl>\r\n
DATA\r\n
Subject: Temat\r\n
From: Adam Boduchrn\r\n
Wiadomość\r\n
.\r\n
QUIT\r\n


Dla przykładu powyższe instrukcje umożliwią wysłanie listu do odbiorca@sewer.pl.

Ale przejdźmy do rzeczy: połączenie z serwerem może odbyć się za pomocą funkcji fsockopen().

/* otwarcie gniazdka (laczenie sie z serwerem poczty) */
$this->socket = fsockopen($this->host, 25, $errno, $error, 30);
if (!$this->socket)
{
    Error("$error ($errno)");
}


Pierwszym parametrem tej funkcji musi być nazwa hosta; drugim port. Trzeci i czwarty parametr to opis błędu oraz numer błędu. Ostatni parametr to TimeOut (ilość sekund przez jakie skrypt bedzie próbował połączyć
się z serwerem).

Wysyłanie komendy odybwa się za pośrednictwem funkcji fwrite():

fwrite($this->socket, $var_command)


Pierwszym parametrem musi być uchwyt do gniazdka (uzyskany jako rezultat działania funkcji fsockopen()). Drugi parametr to treść wysyłanej komendy.

Równie prosto można odczytać tekst, który został zwrócony przez serwer (funkcja fgets()).

fgets($this->socket, 100);


Pierwszym parametrem musi być oczywiście uchwyt, a drugim ilość znaków jakie zostaną odczytane. Funkcja fgets() zwraca łańcuch (string), który zawiera treść zwróconą przez serwer. To chyba wszystko co trzeba wiedzieć na temat łączenia się z serwerem i wysyłaniem do niego komend. Nie należy oczywiście zapominać o tym, aby na końcu zamknąć połączenie (funkcja fclose()).

Klasa Mail


Na podstawie tego, co napisaliśmy można napisać klasę, która uprości cały proces przesyłania wiadomości. Kod źródłowy całego skryptu przedstawia się następująco:

<?php
 
   function Error($msg)
   {
   /* funkcja wyswietla komunikat bledu pocztym konczy dzialanie programu. Wlasciwie stanowi niejako alias do funkcji die() */
        echo $msg;
        exit;
   }

   error_reporting  (E_ERROR | E_WARNING | E_PARSE); // wyswietlaj bledy
   set_time_limit(30); // time-out na 30 sek.


   class Mail
   {

       var $host; // host, z ktorym bedziemy sie laczyc
       var $socket; // uchwyt

       var $mail_subject; // temat listu
       var $mail_sender; // nadawca
       var $mail_recipient; // odbiorca
       var $mail_content; // treść

       var $log; // log

       function Mail($server_host)
       {
           if (empty($server_host))
           {
                Error('Nie wpisałeś hosta, z którym mam się połączyć');
           }

           $this->host = $server_host;
       }

       function connect()
       {
          /* otwarcie gniazdka (laczenie sie z serwerem poczty) */
           $this->socket = fsockopen($this->host, 25, $errno, $error, 30);
           if (!$this->socket)
           {
               Error("$error ($errno)");
           }

           /* wyslanie tekstu przywitalnego */
           $this->send_cmd("HELO " . $this->host . "\r\n");
       }
       
       function disconnect()
       {
       /* rozlaczenie z serwerem; przed tym nalezy jednak wyslac polecenie QUIT */
           $this->send_cmd("QUIT\r\n");
           fclose($this->socket);
       }
       
       function send_cmd($var_command)
       {
       /* funkcja wysyla do gniazdka polecenie z parametru $var_command oraz odczytuje odpowiedz
          z serwera i przypisuja ja do zmiennej $log */

           if ( fwrite($this->socket, $var_command) )
           {
               $this->log .= fgets($this->socket, 100) . '<br>';
           }
       }

       
       function set_mail_sender($var_sender)
       {
           $this->mail_sender = $var_sender;
       }
       
       function set_mail_recipient($var_recipient)
       {
           $this->mail_recipient = $var_recipient;
       }
       
       function set_mail_subject($var_subject)
       {
           $this->mail_subject = $var_subject;
       }
       
       function set_mail_content($var_content)
       {
           $this->mail_content = $var_content;
       }
       
       function send_mail()
       {
           if (empty($this->mail_recipient) ||
               empty($this->mail_sender)) Error('Nie wpisałeś nadawcy lub odbiorcy e-maila!');
               
           /* nadawca wiadomosci */
           $this->send_cmd("MAIL FROM: <" . $this->mail_sender . ">\r\n");
           
           /* odbiorca wiadomosci */
           $this->send_cmd("RCPT TO: <" . $this->mail_recipient . ">\r\n");
           
           /*  informuje, ze zaraz rozpoczniemy wysylanie danych */
           $this->send_cmd("DATA\r\n");
           
           /* temat wiadomosci */
           $this->send_cmd("Subject: " . $this->mail_subject . "\r\n");
           
           /* kodowanie */
           $this->send_cmd("Content-type: text/html; charset=iso-8859-2\r\n");
           
           /* naglowki */
           $this->send_cmd("From: " . $this->mail_sender . "\r\n");
           $this->send_cmd("Reply-To: " . $this->mail_sender . "\r\n");
           $this->send_cmd("Return-Path: " . $this-&gt;mail_sender . "\r\n\r\n");
           
           /* tresc wiadomosci */
           $this->send_cmd($this->mail_content . "\r\n");
           $this->send_cmd(".\r\n"); // koniec wiadomosci

       }

   }

   $mail = new Mail('mail.pf.pl');
   $mail->set_mail_sender('bald@pf.pl');
   $mail->set_mail_recipient('root@localhost.localdomain');
   $mail->set_mail_subject('Testowy temat');
   $mail->set_mail_content('Jakas tresc');
   $mail->connect();
   $mail->send_mail();
   $mail->disconnect();

   echo $mail->log;
?>


Na samym końcu następuje skorzystanie z tej klasy oraz z serwera mail.pf.pl do wysłania listu. Na końcu powinien zostać wyświetlony log z działania klasy (log sporządzony na podstawie komunikatów zwracanych przez serwer).
Informacje
Ostatnia modyfikacja 07-03-2006 14:11 Ostatni autor Adam Boduch
Ilość wyświetleń 18142 Wersja 2
Komentarz
Olamagato dnia 16-06-2009 12:12
Ta "dopracowana" klasa PHPmailer, to z punktu widzenia obiektowego nędza. Pola w większości publiczne, weryfikacja wprowadzonych danych dopiero w metodzie send (czyli najpóźniej jak się da, albo żadna), praktycznie żadnych możliwości odchudzenia klasy z niepotrzebnego w wielu zastosowaniach kodu... 65 KB.
Fakt, że technicznie wyczerpuje specyfikację, ale to jedyne co można o niej powiedzieć. Może poza tym, że tak jak sam PHP jest ona sklejką niezbyt powiązanych ze sobą metod różnych autorów.
WeedSmoker dnia 30-08-2006 13:14
Czy musze miec u siebie na kompie serwer SMTP zeby korzystac z funkcji mail w podstawowej wersji? np Microsoft Exchange?
Coldpeer dnia 17-07-2006 17:36
Lepiej skorzystać z napisanej już przez kogoś dopracowanej klasy PHPmailer :P Załącznki dodaje się poprzez metodę Attachment.
Adam Boduch dnia 13-08-2003 15:32
Musisz zaznajomić się ze znaczniem nagłówków e-mailach . Póżniej należy jedynie dodać odpowiedni nagłówek.

Informacje: [url]http://www.faqs.org/rfcs/rfc1896[/url]
                    [url]http://www.zend.com/zend/spotlight/sendmimeemailpart1.php[/url]
BlackSide dnia 18-10-2002 08:27
Jak wysłać maila z załącznikiem?

Copyright © 2000-2006 by Coyote Group 0.9.3-pre3
Czas generowania strony: 0.2046 sek. (zapytań SQL: 9)