[PHP]SMTP via sockets werkt niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Ik heb me ondertussen alle mogelijkheden geprobeerd die ik ken, maar kom er niet uit. Ook de search helpt me niet bij dit probleem dus ik zit echt helemaal vast.

Het probleem:
Ik ben bezig met een script die verbinding maakt met een SMTP server waarvoor Authenticated login nodig is. Nu is dat geen probleem en kan ik het AUTH LOGIN commando versturen met goede reactie. Daarop volgend de gebruikersnaam met goed resultaat, maar als ik het wachtwoord verstuur krijg ik ineens geen reactie meer. Dit terwijl het wachtwoord wel correct is (en zelfs als ie niet correct was had ie toch een error code moeten terug geven?).

Dit is de functie die ik ervoor wilde gebruiken. Is een class-functie met enige debug regels:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public function Authenticate($username, $password){
    print "Connectie verifieren...<BR>";
    if(!$this->Connected()) return false;
    print "Verbonden<BR>";
    
    print "HELO commando versturen...<BR>";
    if(!$reply = $this->getSocketDataFromCommand("EHLO localhost")) return false;
    print "HELO commando verstuurd en data ontvangen<BR>";
    
    print "Reactie controleren...<BR>";
    if(!$this->matchCode($reply[0], 250, "HELO command refused", 204)) return false;
    print "Reactie ok<BR><BR>";
    
    print "Geaccepteerde commandos:<BR>";
    foreach($reply as $command) print $command."<BR>";
    print "<BR>";
    
    print "Auth commando versturen...<BR>";
    if(!$reply = $this->getSocketDataFromCommand("AUTH LOGIN")) return false;
    print "Auth commando verstuurd en data ontvangen<BR>";
    
    print "Reactie controleren...<BR>";
    if(!$this->matchCode($reply[0], 334, "Authenticated login not supported by server", 201)) return false;
    print "Reactie ok<BR>";
        
    print "Gebruikersnaam versturen...<BR>";
    if(!$reply = $this->getSocketDataFromCommand(base64_encode($username))) return false;
    print "Gebruikersnaam verzonden en data ontvangen<BR>";
    
    print "Reactie controleren...<BR>";
    if(!$this->matchCode($reply[0], 334, "Username refused. ".$reply[0] , 202)) return false;
    print "Reactie ok<BR>";
    
    print "Wachtwoord versturen...<BR>";    
    if(!$reply = $this->getSocketDataFromCommand(base64_encode($password)))return false;
    print "Wachtwoord verzonden en data ontvangen<BR>";
    
    print "Code controleren...<BR>";
    if(!$this->matchCode($reply[0], 235, "Password refused. ".$reply[0], 203))return false;
    print "Code ok<BR>";
    
    print "Authenticatie succesvol!<BR>";       
    return true;
}

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
protected function getSocketData($return_type="array") {
 if(!$this->Connected()) return false;
  
  $break = false;
  while($str = fgets($this->con,1024)) {
    if(!$str){
        $this->error = "Failed to retrieve data";
        $this->errno = 501;
        throw new Exception($this->error, $this->errno);
        return false;
    }
    
    if(substr($str,3,1) == " ")$break = true;;
    
    switch(strtolower($return_type)){
        case "string": $data .= "\n".$str; break;
            case "array":
            default: $data[] = $str;
        }
        
        if($break) break;
  }
  return $data;
}

public function getSocketDataFromCommand($command, $return_type="array"){
    // Execute command and get results
    if(!$this->Connected()) return false;
    
    if(ereg("\n", $command)) $command = ereg_replace("\n.*$", "", $command); // search and remove any line-end data to prevent a double line-end
    if(ereg("\r", $command)) $command = ereg_replace("\r.*$", "", $command); // and also remove any commands afterwords
    
    fputs($this->con, $command."\r\n"); // now add the line-end once
    
    if(!$result = $this->getSocketData($return_type)) return false;
    return $result;
}

De reactie van de server op deze manier is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Connectie verifieren...
Verbonden
HELO commando versturen...
HELO commando verstuurd en data ontvangen
Reactie controleren...
Reactie ok

Geaccepteerde commandos:
250-helderhosting.nl 
250-PIPELINING 
250-SIZE 10240000 
250-VRFY 
250-ETRN 
250-STARTTLS 
250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5 
250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5 
250 8BITMIME 

Auth commando versturen...
Auth commando verstuurd en data ontvangen
Reactie controleren...
Reactie ok
Gebruikersnaam versturen...
Gebruikersnaam verzonden en data ontvangen
Reactie controleren...
Reactie ok
Wachtwoord versturen...

Weet iemand wat er mis gaat?

telefoontoestel


Acties:
  • 0 Henk 'm!

  • R4NCOR
  • Registratie: December 2000
  • Laatst online: 16-09 12:26

R4NCOR

eigenlijk gewoon Niels

Op line 7 van je function heb je staan:
code:
1
EHLO localhost

is dat een typo?

Ik heb er verder geen flauw idee van om eerlijk te zijn. Misschien kun je eens handmatig inloggen met het spul dat je script uitpoept, om te kijken wat de eigenlijke antwoorden van de SMTP-server zijn?

Acties:
  • 0 Henk 'm!

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Probeer in ieder geval die regels van
PHP:
1
if(!$reply = $this->getSocketDataFromCommand(base64_encode($password)))return false;

te veranderen in
PHP:
1
2
3
4
$reply = $this->getSocketDataFromCommand(base64_encode($password));
if($reply === false) {
    die("Error on receive!");
}

zodat je kunt zien dat je functies false returnen want dat zou nu namelijk ook kunnen gebeuren maar dan heb je het niet door.
En wat doet dit:
PHP:
1
2
3
print "Reactie controleren...<BR>";
if(!$this->matchCode($reply[0], 334, "Authenticated login not supported by server", 201)) return false;
print "Reactie ok<BR>";

Is het nu wel of niet OK als die mail server geen AUTH LOGIN ondersteund? En wat doe je als dat niet zo is?

@R4NCOR
Nee EHLO is goed, staat voor Extended HeLlO

Nu met Land Rover Series 3 en Defender 90


Acties:
  • 0 Henk 'm!

  • stekkel
  • Registratie: Augustus 2001
  • Laatst online: 17-09 08:05
Ik heb het vermoeden dat fgets aan het wachten is op een response op de socket. Wanneer die niet komt blijft het script ongeveer 10 minuten hangen.

Ik denk dat je moet richten op de fgetssocketdata functie en dat daar het een en ander mis gaat. Dus een fgets te veel.

Acties:
  • 0 Henk 'm!

  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
MTWZZ schreef op donderdag 03 maart 2005 @ 08:36:
Probeer in ieder geval die regels van
PHP:
1
if(!$reply = $this->getSocketDataFromCommand(base64_encode($password)))return false;

te veranderen in
PHP:
1
2
3
4
$reply = $this->getSocketDataFromCommand(base64_encode($password));
if($reply === false) {
    die("Error on receive!");
}

zodat je kunt zien dat je functies false returnen want dat zou nu namelijk ook kunnen gebeuren maar dan heb je het niet door.
Om deze reden heb ik ook de beide functies socketGetData en socketGetDataFromCommand erbij geplaatst. Op het moment dat er een error plaats vind wordt er een exception gegeven welke wordt afgevangen op het moment dat de auth functie false terug geeft. Deze wordt dan ook netjes weergegeven. Er is dus geen fout opgetreden in het script.
En wat doet dit:
PHP:
1
2
3
print "Reactie controleren...<BR>";
if(!$this->matchCode($reply[0], 334, "Authenticated login not supported by server", 201)) return false;
print "Reactie ok<BR>";

Is het nu wel of niet OK als die mail server geen AUTH LOGIN ondersteund? En wat doe je als dat niet zo is?
Deze functie controleerd of een reply de opgegeven code bevat. Is dit niet zo dan is de return waarde onjuist en wordt er een exception gegeven welke op zijn beurt dus ook weer wordt afgevangen en verwerkt. Het is dan dus niet ok als er geen auth login wordt ondersteund, want dan heeft de functie dus geen zin.
stekkel schreef op donderdag 03 maart 2005 @ 13:31:
Ik heb het vermoeden dat fgets aan het wachten is op een response op de socket. Wanneer die niet komt blijft het script ongeveer 10 minuten hangen.

Ik denk dat je moet richten op de fgetssocketdata functie en dat daar het een en ander mis gaat. Dus een fgets te veel.
Dat is het vreemde dus juist. Normaal gesproken hangt ie ook als er geen data wordt terug gegeven, maar het script is binnen 2 seconden klaar met parsen. Dus de verbinding en teruggifte van data gaat dus allemaal goed. Ook als ik het script gewoon puur schrijf op deze mogelijkheid krijg ik hetzelfde resultaat. Op alles antwoord behalve op het wachtwoord. Daar lijk ik ineens lege data terug te krijgen van de server.

telefoontoestel


Acties:
  • 0 Henk 'm!

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

telefoontoestel schreef op donderdag 03 maart 2005 @ 15:30:
[...]

Om deze reden heb ik ook de beide functies socketGetData en socketGetDataFromCommand erbij geplaatst. Op het moment dat er een error plaats vind wordt er een exception gegeven welke wordt afgevangen op het moment dat de auth functie false terug geeft. Deze wordt dan ook netjes weergegeven. Er is dus geen fout opgetreden in het script.
En laat ik nou over die Exception heen gekeken hebben :|

Ik heb nog even zitten kijken naar de documentatie van fgets en daar worden wat voorbeeldjes gegeven icm feof().
Het is misschien te proberen om dit te doen bij de getSocketData functie
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$buff = "";
while(!feof($this->con)) {
    $tmp = fgets($this->con,1024);
    // checken of $buff leeg is hoeft niet aangezien feof dan true zou returnen
    // maar wel checken of fgets een error uitgespuugd heeft
    if($tmp === false) {
        $this->error = "Failed to retrieve data";
        $this->errno = 501;
        throw new Exception($this->error, $this->errno); 
        return false;
    }
    $buff .= $tmp;
}

if($buff == "") {
    $this->error = "Failed to retrieve data";
    $this->errno = 501;
    throw new Exception($this->error, $this->errno); 
    return false;
}
return $buff;


Je zou ook nog even kunnen proberen om met ethereal de verbinding te sniffen.

Nu met Land Rover Series 3 en Defender 90


Acties:
  • 0 Henk 'm!

  • telefoontoestel
  • Registratie: Oktober 2002
  • Laatst online: 29-06-2024

telefoontoestel

Maak me gelukkig....Bel!!

Topicstarter
Dat wat jij zegt had ik dus ook geprobeerd, maar dan blijft de functie dus juist hangen. Dat vond ik eigenlijk ook erg vreemd dat hij wel op de manier werkt zoals hij nu geschreven is, bewijze dat de andere aanvragen wel gewoon worden verwerkt.

Dat sniffer idee wil ik nog wel ff uitproberen. Ik kom er nog ff op terug.

telefoontoestel


Acties:
  • 0 Henk 'm!

  • stekkel
  • Registratie: Augustus 2001
  • Laatst online: 17-09 08:05
Misschien heb je hier wat aan:

Een progseltje van mij wat wel werkt ;)

http://cvs.sourceforge.ne....php?rev=1.28&view=markup
Pagina: 1