Skip to content

9. As funções de rede do PHP

Passamos agora às funções de rede do PHP, que nos permitem realizar a programação do TCP / IP (Transfer Control Protocol / Internet Protocol).

9.1. Obter o nome ou o endereço IP de um computador na Internet (inet_01)


<?php

// funciona como nome da máquina <--> endereço IP da máquina
ini_set("display_errors", "off");
// constantes
$HOTES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "localhost", "", "xx");
// endereços IP das máquinas de $HOTES
for ($i = 0; $i < count($HOTES); $i++) {
  getIPandName($HOTES[$i]);
}
// fim
exit;

//------------------------------------------------
function getIPandName($nomMachine) {
//$nomMachine: nome da máquina cujo endereço se pretende obter IP
// nomMachine-->endereço IP
  $ip = gethostbyname($nomMachine);
  if ($ip != $nomMachine) {
    print "ip[$nomMachine]=$ip\n";
// endereço IP --> nomMachine
    $name = gethostbyaddr($ip);
    if ($name != $ip) {
      print "name[$ip]=$name\n";
    } else {
      print "Erreur, machine[$ip] non trouvée\n";
    }
  } else {
    print "Erreur, machine[$nomMachine] non trouvée\n";
  }
}

Resultados:

ip[istia.univ-angers.fr]=193.49.146.171
name[193.49.146.171]=istia.istia.univ-angers.fr
ip[www.univ-angers.fr]=193.49.144.40
name[193.49.144.40]=ametys-fo.univ-angers.fr
ip[www.ibm.com]=129.42.56.216
Erreur, machine[129.42.56.216] non trouvée
ip[localhost]=127.0.0.1
name[127.0.0.1]=localhost127.0.0.1
ip[]=192.168.1.11
name[192.168.1.11]=st-PC.home
Erreur, machine[xx] non trouvée

Comentários

  • linha 4: solicita-se que os erros de execução não sejam apresentados.

As funções de rede de PHP são utilizadas na função getIpandName da linha 15.

  • linha 18: a função gethostbyname($nom) permite obter o endereço IP «ip3.ip2.ip1.ip0» da máquina denominada $nom. Se a máquina $nom não existir, a função devolve $nom como resultado.
  • linha 22: a função gethostbyaddr($ip) permite obter o nome do computador com o endereço $ip, na forma «ip3.ip2.ip1.ip0». Se a máquina $ip não existir, a função devolve $ip como resultado.

9.2. Um cliente web ( inet_02)

Um script que permite obter o conteúdo da página inicial de um site.


<?php

// gestão de erros
ini_set("display_errors","off");
// obter o texto HTML de URL
// lista de sites
$SITES = array("istia.univ-angers.fr", "www.univ-angers.fr", "www.ibm.com", "xx");
// leitura das páginas de índice dos sites da tabela $SITES
for ($i = 0; $i < count($SITES); $i++) {
// leitura da página de índice do site $SITES[$i]
  $résultat = getIndex($SITES[$i]);
// exibição do resultado
  print "$résultat\n";
}//para
// fim
exit;

//-----------------------------------------------------------------------
function getIndex($site) {
// lê o ficheiro URL $site/ e guarda-o no ficheiro $site.html
// criação do ficheiro $site.html
  $html = fopen("$site.html", "w");
  if (!$html)
    return "Erreur lors de la création du fichier $site.html";

// abertura de uma ligação na porta 80 do $site
  $connexion = fsockopen($site, 80);
// retorno em caso de erro
  if (!$connexion)
    return "Echec de la connexion au site ($site,80) : $erreur";
// $connexion representa um fluxo de comunicação bidirecional
// entre o cliente (este programa) e o servidor web contactado
// este canal é utilizado para a troca de comandos e informações
// o protocolo de comunicação é HTTP
// o cliente envia o comando get para solicitar o URL /
// sintaxe «get» URL HTTP/1.0
// os cabeçalhos (headers) do protocolo HTTP devem terminar com uma linha em branco
  fputs($connexion, "GET / HTTP/1.0\n\n");
// o servidor vai agora responder no canal $connexion. Vai enviar todos
// esses dados e, em seguida, encerrará o canal. O cliente lê, portanto, tudo o que chega de $connexion
// até ao encerramento do canal
  while ($ligne = fgets($connexion, 1000))
    fputs($html, $ligne);
// o cliente, por sua vez, encerra a ligação
  fclose($connexion);
// encerramento do ficheiro $html
  fclose($html);
// retorno
  return "Transfert réussi de la page index du site $site";
}

Resultados: por exemplo, o ficheiro recebido para o site [www.ibm.com]:

HTTP/1.1 302 Found
Date: Wed, 08 Jun 2011 15:43:56 GMT
Server: IBM_HTTP_Server
Content-Type: text/html
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache, must-revalidate
Location: http://www.ibm.com/us/en/
Content-Length: 209
Kp-eeAlive: timeout=10, max=14
Connection: Keep-Alive

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://www.ibm.com/us/en/">here</a>.</p>
</body></html>
  • as linhas 1 a 11 são os cabeçalhos HTTP da resposta do servidor
  • linha 1: o servidor solicita ao cliente que se redirecione para o endereço URL indicado na linha 8
  • linha 2: data e hora da resposta
  • linha 3: identidade do servidor web
  • linha 4: conteúdo enviado pelo servidor. Neste caso, uma página HTML que começa na linha 13
  • linha 12: a linha vazia que encerra os cabeçalhos HTTP
  • linhas 13-19: a página HTML enviada pelo servidor web.

Comentários ao código:

  • linha 7: a lista de URLs dos sites cuja página inicial se pretende obter. Esta será guardada no ficheiro de texto [nomsite.html].
  • linha 11: a função getIndex executa a tarefa
  • linha 19: a função getIndex($site) descarrega a página raiz (ou página inicial) do site $site e armazena-a no ficheiro de texto $site.html.
  • linha 27: a função fsockopen($site,$port) permite estabelecer uma ligação com um serviço TCP / IP que funciona na porta $port da máquina $site. Assim que a ligação cliente/servidor é estabelecida, vários serviços TCP / IP trocam linhas de texto. É o caso, neste caso, do protocolo HTTP (HyperText Transfer Protocol). O fluxo do servidor que chega ao cliente pode então ser tratado como um ficheiro de texto. O mesmo se aplica ao fluxo que parte do cliente para o servidor.
  • linha 38: a função fputs permite ao cliente enviar dados para o servidor. Aqui, a linha de texto enviada tem o seguinte significado: «Quero (GET) a página raiz (/) do site à qual estou ligado. Estou a trabalhar com o protocolo HTTP, versão 1.0». A versão atual deste protocolo é a 1.1.
  • linha 42: as linhas de texto da resposta do servidor podem ser lidas linha a linha com um ciclo while e guardadas no ficheiro de texto [$site.html]. Quando o servidor web envia a página que lhe foi solicitada, encerra a sua ligação com o cliente. Do lado do cliente, isto será detetado como um fim de ficheiro.

9.3. Um cliente SMTP (inet_03)

Entre os protocolos TCP / IP, o SMTP (Protocolo de Transferência SendMail) é o protocolo de comunicação do serviço de envio de mensagens.

Notas:

  • num computador Windows equipado com um antivírus, este irá provavelmente impedir que o script PHP se ligue à porta 25 de um servidor SMTP. Nesse caso, é necessário desativar o antivírus. Para o McAfee, por exemplo, pode proceder da seguinte forma:
  • em [1], ativa-se a consola VirusScan
  • em [2], desativa-se o serviço [Protection lors de l'accès]
  • em [3], o serviço está parado

O script:


<?php

// cliente SMTP (Protocolo de Transferência SendMail) que permite enviar uma mensagem
// as informações são extraídas de um ficheiro $INFOS que contém as seguintes linhas
// linha 1: smtp, remetente, destinatário
// linhas seguintes: o texto da mensagem
// remetente: e-mail do remetente
// destinatário: e-mail do destinatário
// SMTP: nome do servidor SMTP a utilizar
// protocolo de comunicação SMTP cliente-servidor
// -> o cliente liga-se à porta 25 do servidor SMTP
// <- o servidor envia-lhe uma mensagem de boas-vindas
// -> o cliente envia o comando EHLO: nome do seu computador
// <- o servidor responde com OK ou não
// -> o cliente envia o comando mail from: <remetente>
// <- o servidor responde com OK ou não
// -> o cliente envia o comando rcpt para: <destinatário>
// <- o servidor responde com OK ou não
// -> o cliente envia o comando «data»
// <- o servidor responde com OK ou não
// -> o cliente envia todas as linhas da sua mensagem e termina com uma linha contendo o
// único carácter.
// <- o servidor responde com OK ou não
// -> o cliente envia o comando «quit»
// <- o servidor responde com OK ou não
// as respostas do servidor têm o formato xxx texto, em que xxx é um número de 3 dígitos. Qualquer número xxx >=500
// indica um erro. A resposta pode conter várias linhas, todas começando por xxx, exceto a última
// no formato xxx(espaço)
// as linhas de texto trocadas devem terminar com os caracteres RC(#13) e LF(#10)

// dados
$INFOS = "mail.txt"; // os parâmetros de envio do e-mail
// recuperam-se os parâmetros do e-mail
list($erreur, $smtpServer, $expéditeur, $destinataire, $message) = getInfos($INFOS);
// erro?
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire]\n";
// envio do e-mail em modo detalhado
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, 1);
print "Résultat de l'envoi : $résultat\n";
// fim
exit;

//-----------------------------------------------------------------------
function getInfos($fichier) {
// retorna as informações ($smtp,$expéditeur,$destinataire,$message) do ficheiro de texto $fichier
// linha 1: smtp, remetente, destinatário
// linhas seguintes: o texto da mensagem

// abertura do ficheiro $fichier
  $infos = fopen($fichier, "r");
// o ficheiro $fichier existe?
  if (!$infos)
    return array("Le fichier $fichier n'a pu être ouvert en lecture");
// leitura da 1.ª linha
  $ligne = fgets($infos, 1000);
// remoção do caractere de fim de linha
  $ligne = cutNewLineChar($ligne);
// recuperação dos campos smtp, remetente, destinatário
  $champs = explode(",", $ligne);
// Temos o número correto de campos?
  if (count($champs) != 3)
    return "La ligne 1 du fichier $fichier (serveur smtp, expéditeur, destinataire) a un
nombre de champs incorrect";
// «processamento» das informações recuperadas
  for ($i = 0; $i < count($champs); $i++)
    $champs[$i] = trim($champs[$i]);
// recuperação dos campos
  list($smtpServer, $expéditeur, $destinataire) = $champs;
// leitura da mensagem
  $message = "";
  while ($ligne = fgets($infos, 1000))
    $message.=$ligne;
  fclose($infos);
// retorno
  return array("", $smtpServer, $expéditeur, $destinataire, $message);
}

//-----------------------------------------------------------------------

function sendmail($smtpServer, $expéditeur, $destinataire, $message, $verbose) {
// envia $message para o servidor SMTP $smtpserver em nome de $expéditeur
// para $destinataire. Se $verbose=1, efetua um acompanhamento das trocas cliente-servidor
// recupera-se o nome do cliente
  $client = gethostbyaddr(gethostbyname(""));
// abertura de uma ligação na porta 25 de $smtpServer
  $connexion = fsockopen($smtpServer, 25);
// retorno em caso de erro
  if (!$connexion)
    return "Echec de la connexion au site ($smtpServer,25)";
// $connexion representa um fluxo de comunicação bidirecional
// entre o cliente (este programa) e o servidor SMTP contactado
// este canal é utilizado para a troca de comandos e informações

// após a ligação, o servidor envia uma mensagem de boas-vindas que é lida
  $erreur = sendCommand($connexion, "", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// comando «ehlo»:
  $erreur = sendCommand($connexion, "EHLO $client", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// comando mail from:
  $erreur = sendCommand($connexion, "MAIL FROM: <$expéditeur>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// comando rcpt to:
  $erreur = sendCommand($connexion, "RCPT TO: <$destinataire>", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// comando «data»
  $erreur = sendCommand($connexion, "DATA", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// preparação da mensagem a enviar
  // deve conter as seguintes linhas
  // De: remetente
  // Para: destinatário
  // linha em branco
  // Mensagem
  // .
  $data = "From: $expéditeur\r\nTo: $destinataire\r\n$message\r\n.\r\n";
  $erreur = sendCommand($connexion, $data, $verbose, 0);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// comando «quit»
  $erreur = sendCommand($connexion, "QUIT", $verbose, 1);
  if ($erreur) {
    fclose($connexion);
    return $erreur;
  }

// fim
  fclose($connexion);
  return "Message envoyé";
}

// --------------------------------------------------------------------------

function sendCommand($connexion, $commande, $verbose, $withRCLF) {
// envia $commande para o canal $connexion
// modo detalhado se $verbose=1
// se $withRCLF=1, adiciona a sequência RCLF à troca

// dados
  if ($withRCLF)
    $RCLF = "\r\n"; else
    $RCLF="";

// envio de comando se $commande não estiver vazio
  if ($commande) {
    fputs($connexion, "$commande$RCLF");

// eventual resposta
    if ($verbose)
      affiche($commande, 1);
  }//se

// leitura da resposta
  $réponse = fgets($connexion, 1000);

// eco eventual
  if ($verbose)
    affiche($réponse, 2);

// recuperação do código de erro
  $codeErreur = substr($réponse, 0, 3);

// última linha da resposta?
  while (substr($réponse, 3, 1) == "-") {

     // leitura da resposta
    $réponse = fgets($connexion, 1000);

     // eco eventual
    if ($verbose)
      affiche($réponse, 2);
  }//enquanto
// resposta concluída

// erro devolvido pelo servidor?
  if ($codeErreur >= 500)
    return substr($réponse, 4);

// retorno sem erro
  return "";
}

// --------------------------------------------------------------------------

function affiche($échange, $sens) {
// exibe $échange no ecrã
// se $sens=1, exibe -->$echange
// se $sens=2, exibe <-- $échange sem os dois últimos caracteres RCLF
  switch ($sens) {
    case 1:
      print "--> [$échange]\n";
      return;
    case 2:
      $L = strlen($échange);
      print "<-- [" . substr($échange, 0, $L - 2) . "]\n";
      return;
  }//switch
}

// --------------------------------------------------------------------------

function cutNewLinechar($ligne) {
// elimina-se o marcador de fim de linha de $ligne, caso exista
  ...
}

O ficheiro infos.txt:

1
2
3
4
5
6
7
smtp.orange.fr, serge.tahe@univ-angers.fr , serge.tahe@istia.univ-angers.fr
Subject: test

ligne1
ligne2

ligne3
  • linha 1: [smtp.orange.fr], o servidor utilizado para o envio do e-mail; [serge.tahe@univ-angers.fr], o endereço do remetente; [serge.tahe@istia.univ-angers.fr], o endereço do destinatário
  • linha 2: cabeçalhos da mensagem. Aqui existe apenas um, o do assunto da mensagem.
  • linha 3: a linha vazia encerra os cabeçalhos da mensagem
  • linhas 4-7: o texto da mensagem

Resultados no ecrã:

Envoi du message [smtp.orange.fr,serge.tahe@univ-angers.fr,serge.tahe@univ-angers.fr]
<-- [220 mwinf5d05 ME ESMTP server ready]
--> [EHLO st-PC.home]
<-- [250-mwinf5d05 hello [2.1.22.82], pleased to meet you]
<-- [250-HELP]
<-- [250-AUTH LOGIN PLAIN]
<-- [250-SIZE 44000000]
<-- [250-ENHANCEDSTATUSCODES]
<-- [250-8BITMIME]
<-- [250 OK]
--> [MAIL FROM: <serge.tahe@univ-angers.fr>]
<-- [250 2.1.0 <serge.tahe@univ-angers.fr> sender ok]
--> [RCPT TO: <serge.tahe@univ-angers.fr>]
<-- [250 2.1.5 <serge.tahe@univ-angers.fr> recipient ok]
--> [DATA]
<-- [354 enter mail, end with "." on a line by itself]
--> [From: serge.tahe@univ-angers.fr
To: serge.tahe@univ-angers.fr
Subject: test

ligne1
ligne2
ligne3
.
]
<-- [250 2.0.0 Ag3i1h0051mFoG203g3ip1 mail accepted for delivery]
--> [QUIT]
<-- [221 2.0.0 mwinf5d05 ME closing connection]
Résultat de l'envoi : Message envoyé
  • linha 1: mensagem de acompanhamento da execução do script
  • linha 2: primeira resposta do servidor SMTP. Segue-se à ligação do cliente à porta 25 do servidor SMTP. As respostas do servidor são linhas com o formato [xxx message] ou [xxx-message]. A primeira sintaxe indica que a resposta está concluída. xxx é um código de resultado. Um valor igual ou superior a 500 indica um erro. A segunda sintaxe indica que a resposta não está concluída e que se seguirá outra linha.
  • linha 2: o servidor SMTP indica que está pronto para receber comandos
  • linha 3: o cliente envia o comando [EHLO nomDeMachine], em que nomDeMachine é o nome de Internet do computador no qual o cliente está a ser executado
  • linhas 4-10: resposta do servidor SMTP
  • linha 11: o cliente envia o comando [MAIL FROM: <expéditeur>], que indica o endereço de e-mail do remetente.
  • linha 12: o servidor SMTP indica que aceita este endereço. Poderia tê-lo recusado se a sintaxe estivesse incorreta. No entanto, não verifica se o endereço de e-mail existe realmente.
  • linha 13: o cliente envia o comando [RCPT TO: <destinataire>], que indica o endereço de e-mail do destinatário da mensagem.
  • linha 14: o servidor SMTP responde que aceita esse endereço. Mais uma vez, é realizada uma verificação sintática.
  • linha 15: o cliente envia o comando [DATA], que indica ao utilizador que as linhas que se seguem constituem o corpo da mensagem.
  • linha 16: o servidor responde que a mensagem pode ser enviada. Esta consiste numa sequência de linhas de texto que deve terminar com uma linha composta por um único carácter, um ponto.
  • linhas 17-25: a mensagem enviada pelo cliente
  • linhas 17-19: os cabeçalhos da mensagem [From:, To:, Subject:] servem para indicar, respetivamente, o remetente, o destinatário e o assunto da mensagem.
  • linha 20: linha vazia que assinala o fim dos cabeçalhos
  • linhas 21-23: o corpo da mensagem
  • linha 24: a linha composta por um único ponto que assinala o fim da mensagem.
  • linha 26: o servidor SMTP responde que aceita a mensagem
  • linha 27: o cliente envia o comando [QUIT] para indicar que terminou
  • linha 28: o servidor SMTP responde-lhe que vai encerrar a ligação que o liga ao cliente

Comentários sobre o código

Não iremos detalhar muito o código do script, uma vez que este já foi amplamente comentado.

  • linhas 48-80: a função que processa o ficheiro [infos.txt], que contém a mensagem a enviar, bem como as informações necessárias para esse envio. Esta função devolve um array ($erreur, $smtpServer, $expéditeur, $destinataire, $messge) com:
    • $erreur: uma eventual mensagem de erro; caso contrário, fica vazio.
    • $smtpServer: o nome do servidor SMTP ao qual é necessário ligar-se
    • $expéditeur: o endereço de e-mail do remetente
    • $destinataire: o endereço de e-mail do destinatário
    • $message: a mensagem a enviar. Para além do corpo da mensagem, podem existir cabeçalhos.
  • linhas 84-157: a função sendMail encarrega-se de enviar a mensagem. Os seus parâmetros são os seguintes:
    • $smtpServer: o nome do servidor SMTP ao qual é necessário ligar-se
    • $expéditeur: o endereço de e-mail do remetente
    • $destinataire: o endereço de e-mail do destinatário
    • $message: a mensagem a enviar.
    • $verbose: se for 1, indica que as trocas de dados com o servidor SMTP devem ser reproduzidas na consola.

A função sendMail devolve uma mensagem de erro, vazia caso não tenha ocorrido qualquer erro.

  • linha 88: permite obter o nome Windows de um computador que opera com o OS Windows.
  • linha 99: vimos que o diálogo cliente/servidor segue o seguinte padrão:
    • envio, pelo cliente, de um comando numa linha
    • resposta do servidor numa ou mais linhas
  • linhas 161-208: a função sendCommand aceita os seguintes parâmetros:
    • $connexion: o canal TCP / IP que liga o cliente ao servidor
    • $commande: o comando a enviar por este canal. A resposta do servidor a este comando será lida.
    • $verbose: o valor 1 indica que as trocas de dados com o servidor SMTP devem ser reproduzidas na consola.
    • $withRCLF: se for 1, indica que é necessário adicionar o caractere de fim de linha «\r\n» no final do comando
  • linha 173: envio do comando pelo cliente
  • linha 181: leitura da primeira linha da resposta do servidor SMTP no formato xxx texto ou xxx-texto. Este último caso indica que o servidor tem outra linha para enviar. xxx é o código de erro enviado pelo servidor.
  • linha 188 – recuperação do código de erro da resposta
  • linhas 191-199: leitura das restantes linhas da resposta
  • linhas 203-204: se o código de erro for >=500, significa que o servidor SMTP está a sinalizar um erro.

9.4. Um segundo programa para envio de e-mail (inet_04)

Este script tem a mesma funcionalidade que o anterior: enviar um e-mail. Para tal, utilizamos módulos da biblioteca PEAR. Esta biblioteca inclui dezenas de módulos que abrangem diferentes áreas. Vamos utilizar os seguintes:

  • Net/SMTP: um módulo que permite comunicar com um servidor SMTP
  • Mail: um módulo que permite gerir o envio de um e-mail de acordo com diferentes protocolos.
  • Mail/Mime: um módulo que permite criar uma mensagem que pode incluir documentos anexados.

Para dispor destes módulos, é necessário instalá-los primeiro na máquina que executa o script PHP. A instalação do pacote de software WampServer instalou um interpretador PHP. Na estrutura de diretórios deste, é possível instalar módulos PEAR.

  • em [1], a pasta de instalação do interpretador PHP
  • em [2], a pasta PEAR que conterá os módulos PEAR que serão instalados
  • em [3], o ficheiro de comandos [go-pear.bat] que inicializa a biblioteca PEAR

Para inicializar a biblioteca PEAR, abre-se uma janela DOS e executa-se o ficheiro [go-pear.bat]. Este script irá ligar-se ao site da biblioteca PEAR. É, portanto, necessária uma ligação à Internet.

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>go-pear.bat

Uma vez ligado ao site da biblioteca PEAR, o script irá descarregar vários elementos. Entre estes, encontra-se um novo script [pear.bat]. É com este script que iremos instalar os diferentes módulos PEAR de que necessitamos. Este script é chamado com argumentos. Entre estes, o argumento [help] permite obter uma lista dos comandos aceites pelo script:

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>pear help
Commands:
build                  Build an Extension From C Source
bundle                 Unpacks a Pecl Package
channel-add            Add a Channel
channel-alias          Specify an alias to a channel name
channel-delete         Remove a Channel From the List
channel-discover       Initialize a Channel from its server
channel-info           Retrieve Information on a Channel
channel-login          Connects and authenticates to remote channel server
channel-logout         Logs out from the remote channel server
channel-update         Update an Existing Channel
clear-cache            Clear Web Services Cache
config-create          Create a Default configuration file
config-get             Show One Setting
config-help            Show Information About Setting
config-set             Change Setting
config-show            Show All Settings
convert                Convert a package.xml 1.0 to package.xml 2.0 format
cvsdiff                Run a "cvs diff" for all files in a package
cvstag                 Set CVS Release Tag
download               Download Package
download-all           Downloads each available package from the default channel

info                   Display information about a package
install                Install Package
list                   List Installed Packages In The Default Channel
list-all               List All Packages
list-channels          List Available Channels
list-files             List Files In Installed Package
list-upgrades          List Available Upgrades
login                  Connects and authenticates to remote server [Deprecated i
n favor of channel-login]
logout                 Logs out from the remote server [Deprecated in favor of c
hannel-logout]
makerpm                Builds an RPM spec file from a PEAR package
package                Build Package
package-dependencies   Show package dependencies
package-validate       Validate Package Consistency
pickle                 Build PECL Package
remote-info            Information About Remote Packages
remote-list            List Remote Packages
run-scripts            Run Post-Install Scripts bundled with a package
run-tests              Run Regression Tests
search                 Search remote package database
shell-test             Shell Script Test
sign                   Sign a package distribution file
svntag                 Set SVN Release Tag
uninstall              Un-install Package
update-channels        Update the Channel List
upgrade                Upgrade Package
upgrade-all            Upgrade All Packages [Deprecated in favor of calling upgr
ade with no parameters]
Usage: pear [options] command [command-options] <parameters>
Type "pear help options" to list all options.
Type "pear help shortcuts" to list all command shortcuts.
Type "pear help <command>" to get the help for the specified command.

O comando [install] permite instalar os módulos PEAR. É possível obter ajuda sobre o comando [install]:

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>pear help install
pear install [options] [channel/]<package> ...
Installs one or more PEAR packages.  You can specify a package to install in four ways:

"Package-1.0.tgz" : installs from a local file

"http://example.com/Package-1.0.tgz" : installs from anywhere on the net.

"package.xml" : installs the package described in package.xml.  Useful for testing, or for wrapping a PEAR package in another package manager such as RPM.

"Package[-version/state][.tar]" : queries your default channel's server(pear.php.net) and downloads the newest package with the preferred quality/state (stable).

To retrieve Package version 1.1, use "Package-1.1," to retrieve Package state beta, use "Package-beta."  To retrieve an uncompressed file, append .tar (make sure there is no file by the same name first)

To download a package from another channel, prefix with the channel name like "channel/Package"

More than one package may be specified at once.  It is ok to mix these four ways of specifying packages.

Options:
  -f, --force
        will overwrite newer installed packages
  -l, --loose
        do not check for recommended dependency version
  -n, --nodeps
        ignore dependencies, install anyway
  -r, --register-only
        do not install files, only register the package as installed
  -s, --soft
        soft install, fail silently, or upgrade if already installed
  -B, --nobuild
        don't build C extensions
  -Z, --nocompress
        request uncompressed files when downloading
  -R DIR, --installroot=DIR
        root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM
  -P DIR, --packagingroot=DIR
        root directory used when packaging files, like RPM packaging
  --ignore-errors
        force install even if there were errors
  -a, --alldeps
        install all required and optional dependencies
  -o, --onlyreqdeps
        install all required dependencies
  -O, --offline
        do not attempt to download any urls or contact channels
  -p, --pretend
        Only list the packages that would be downloaded

Os módulos PEAR a instalar são os seguintes: [Mail], [Mail_Mime], [Net_SMTP]. Na janela do DOS, introduza sucessivamente os seguintes comandos:

<PHP_installDir>pear install Mail
...
<PHP_installDir>pear install Mail_Mime
<PHP_installDir>pear install Net_SMTP

onde <PHP_installDir> é a pasta de instalação do interpretador PHP (C:\serveursSGBD\wamp21\bin\PHP\php5.3.5 neste exemplo)

É possível ver os módulos instalados:

C:\serveursSGBD\wamp21\bin\PHP\php5.3.5>pear list
INSTALLED PACKAGES, CHANNEL PEAR.php.NET:
=========================================
PACKAGE          VERSION STATE
Archive_Tar      1.3.7   stable
Console_Getopt   1.3.1   stable
Mail             1.2.0   stable
Mail_Mime        1.8.1   stable
Net_SMTP         1.6.0   stable
Net_Socket       1.0.10  stable
PEAR             1.9.4   stable
PHPUnit          1.3.2   stable
Structures_Graph 1.0.4   stable
XML_Util         1.2.1   stable

Os módulos estão instalados na pasta <PHP_installDir>/PEAR:

Com os módulos PEAR instalados, o script PHP para o envio de e-mails passa a ser o seguinte:


<?php

// gestão de erros
ini_set("display_errors", "off");
// módulos
ini_set("include_path", ".;C:\serveursSGBD\wamp21\bin\PHP\php5.3.5\PEAR");
require_once "Mail.php";
require_once "Mail/Mime.php";
require_once "Net/SMTP.php";


// cliente SMTP (Protocolo de Transferência SendMail) que permite enviar uma mensagem
// as informações são extraídas de um ficheiro $INFOS que contém as seguintes linhas
// linha 1: smtp, remetente, destinatário, anexo
// linhas seguintes: o texto da mensagem
// remetente: e-mail do remetente
// destinatário: e-mail do destinatário
// smtp: nome do servidor SMTP a utilizar
// anexo: nome do documento a anexar
// 
// dados
$INFOS = "mail2.txt"; // parâmetros de envio do e-mail
// recuperam-se os parâmetros do e-mail
list($erreur, $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) = getInfos($INFOS);
// erro?
if ($erreur) {
  print "$erreur\n";
  exit;
}
print "Envoi du message [$smtpServer,$expéditeur,$destinataire,$sujet, $attachement]\n";
// envio do e-mail em modo detalhado
$résultat = sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
print "Résultat de l'envoi : $résultat\n";
// fim
exit;

//-----------------------------------------------------------------------
function getInfos($fichier) {
// retorna as informações ($smtp,$expéditeur,$destinataire,$message, $sujet, $attachement) extraídas do ficheiro de texto $fichier
// linha 1: smtp, remetente, destinatário, assunto, anexo
// linhas seguintes: o texto da mensagem
...
// retorno
  return array("", $smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement);
}

//getInfos
//-----------------------------------------------------------------------

function sendmail($smtpServer, $expéditeur, $destinataire, $message, $sujet, $attachement) {
// envia $message para o servidor SMTP $smtpserver em nome de $expéditeur
// para $destinataire. O documento $attachement está anexado à mensagem
//; a mensagem tem como assunto $sujet
// 
  // mensagem
  $msg = new Mail_Mime();
  $msg->setTXTBody($message);
  $msg->addAttachment($attachement);
  $headers = $msg->headers(array("From" => $expéditeur, "To" => $destinataire, "Subject" => $sujet));
  // envio
  $mailer = &Mail::factory("smtp", array("host" => $smtpServer, "port" => 25));
  $envoi = $mailer->send($expéditeur, $headers, $msg->get());
  if ($envoi === TRUE) {
    return "Message envoyé";
  } else {
    return $envoi;
  }
}

// --------------------------------------------------------------------------

function cutNewLinechar($ligne) {
// elimina-se o marcador de fim de linha de $ligne, caso exista
  
}

O ficheiro [mail2.txt]:

1
2
3
4
smtp.orange.fr, serge.tahe@univ-angers.fr , serge.tahe@univ-angers.fr, test, document.pdf
ligne1
ligne2
ligne3
  • linha 1: por ordem, o servidor SMTP, o endereço do remetente, o endereço do destinatário, o assunto da mensagem, o documento a anexar.
  • linhas 2-4: o texto da mensagem

Resultados no ecrã

Envoi du message [smtp.orange.fr,serge.tahe@univ-angers.fr,serge.tahe@univ-angers.fr,test, document.pdf]
Résultat de l'envoi : Message envoyé

Comentários

O script difere do anterior apenas pela sua função sendmail. Descrevemos esta função a seguir:

  • linha 6: os scripts PHP dos módulos PEAR foram instalados num diretório que, por predefinição, não é explorado pelo interpretador PHP. Para que este encontre os módulos PEAR, definimos nós próprios as pastas que o interpretador PHP deve explorar. É possível alterar, durante a execução, determinados parâmetros de configuração do interpretador PHP. Esta alteração só é visível para o script que a efetua e apenas durante o período da sua execução. A configuração por predefinição do interpretador PHP pode ser encontrada no ficheiro <PHP_installdir>/PHP.ini. Este ficheiro contém linhas com o seguinte formato
clé=valeur

O valor da chave pode ser alterado durante a execução através da função ini_set(chave, nouvelle_valeur). A chave para especificar o caminho de pesquisa pelo interpretador das funções e classes PHP referenciadas pelo script é «include_path». Aqui, incluímos no caminho de pesquisa tanto a pasta do script (.) como a pasta PEAR da pasta de instalação do interpretador PHP.

  • linhas 7-9: os scripts PHP para envio de e-mail são carregados.
  • linha 50: a função sendmail, responsável pelo envio do e-mail. Os seus parâmetros são os seguintes:
    • $smtpServer: o nome do servidor SMTP ao qual é necessário ligar-se
    • $expéditeur: o endereço de e-mail do remetente
    • $destinataire: o endereço de e-mail do destinatário
    • $message: a mensagem a enviar.
    • $sujet: o assunto da mensagem
    • $attachement: o nome do documento a anexar à mensagem

A função sendMail devolve uma mensagem de erro, vazia caso não tenha ocorrido qualquer erro.

  • linha 56: criação de uma mensagem do tipo Mail_Mime. Esta mensagem é composta por cabeçalhos (From, To, Subject) e por um corpo (a própria mensagem)
  • linha 57: define-se o corpo da mensagem Mail_Mime.
  • linha 58: anexa-se um documento à mensagem
  • linha 59: definem-se os cabeçalhos (From, To, Subject) da mensagem Mail_Mime
  • linha 61: cria-se a classe responsável pelo envio da mensagem Mail_Mime. O primeiro parâmetro do método é o nome do protocolo a utilizar, neste caso o protocolo SMTP. O segundo parâmetro é um array que define o nome e a porta do serviço SMTP a utilizar
  • linha 62: envio da mensagem. O método send recebe três parâmetros: o endereço do remetente, os cabeçalhos da mensagem Mail_Mime e o corpo da mensagem Mail_Mime. A função «send» devolve o valor booleano TRUE se o envio tiver sido bem-sucedido; caso contrário, devolve uma mensagem de erro.