| [ Index ] |
WordPress Source Cross Reference |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * mail_fetch/setup.php 5 * 6 * Copyright (c) 1999-2002 The SquirrelMail Project Team 7 * 8 * Copyright (c) 1999 CDI (cdi@thewebmasters.net) All Rights Reserved 9 * Modified by Philippe Mingo 2001 mingo@rotedic.com 10 * An RFC 1939 compliant wrapper class for the POP3 protocol. 11 * 12 * Licensed under the GNU GPL. For full terms see the file COPYING. 13 * 14 * pop3 class 15 * 16 * $Id: class-pop3.php 2066 2005-01-07 01:29:49Z saxmatt $ 17 */ 18 19 class POP3 { 20 var $ERROR = ''; // Error string. 21 22 var $TIMEOUT = 60; // Default timeout before giving up on a 23 // network operation. 24 25 var $COUNT = -1; // Mailbox msg count 26 27 var $BUFFER = 512; // Socket buffer for socket fgets() calls. 28 // Per RFC 1939 the returned line a POP3 29 // server can send is 512 bytes. 30 31 var $FP = ''; // The connection to the server's 32 // file descriptor 33 34 var $MAILSERVER = ''; // Set this to hard code the server name 35 36 var $DEBUG = FALSE; // set to true to echo pop3 37 // commands and responses to error_log 38 // this WILL log passwords! 39 40 var $BANNER = ''; // Holds the banner returned by the 41 // pop server - used for apop() 42 43 var $RFC1939 = TRUE; // Set by noop(). See rfc1939.txt 44 // 45 46 var $ALLOWAPOP = FALSE; // Allow or disallow apop() 47 // This must be set to true 48 // manually 49 50 function POP3 ( $server = '', $timeout = '' ) { 51 settype($this->BUFFER,"integer"); 52 if( !empty($server) ) { 53 // Do not allow programs to alter MAILSERVER 54 // if it is already specified. They can get around 55 // this if they -really- want to, so don't count on it. 56 if(empty($this->MAILSERVER)) 57 $this->MAILSERVER = $server; 58 } 59 if(!empty($timeout)) { 60 settype($timeout,"integer"); 61 $this->TIMEOUT = $timeout; 62 set_time_limit($timeout); 63 } 64 return true; 65 } 66 67 function update_timer () { 68 set_time_limit($this->TIMEOUT); 69 return true; 70 } 71 72 function connect ($server, $port = 110) { 73 // Opens a socket to the specified server. Unless overridden, 74 // port defaults to 110. Returns true on success, false on fail 75 76 // If MAILSERVER is set, override $server with it's value 77 78 if(!empty($this->MAILSERVER)) 79 $server = $this->MAILSERVER; 80 81 if(empty($server)){ 82 $this->ERROR = _("POP3 connect:") . ' ' . _("No server specified"); 83 unset($this->FP); 84 return false; 85 } 86 87 $fp = fsockopen("$server", $port, $errno, $errstr); 88 89 if(!$fp) { 90 $this->ERROR = _("POP3 connect:") . ' ' . _("Error ") . "[$errno] [$errstr]"; 91 unset($this->FP); 92 return false; 93 } 94 95 socket_set_blocking($fp,-1); 96 $this->update_timer(); 97 $reply = fgets($fp,$this->BUFFER); 98 $reply = $this->strip_clf($reply); 99 if($this->DEBUG) 100 error_log("POP3 SEND [connect: $server] GOT [$reply]",0); 101 if(!$this->is_ok($reply)) { 102 $this->ERROR = _("POP3 connect:") . ' ' . _("Error ") . "[$reply]"; 103 unset($this->FP); 104 return false; 105 } 106 $this->FP = $fp; 107 $this->BANNER = $this->parse_banner($reply); 108 $this->RFC1939 = $this->noop(); 109 if($this->RFC1939) { 110 $this->ERROR = _("POP3: premature NOOP OK, NOT an RFC 1939 Compliant server"); 111 $this->quit(); 112 return false; 113 } else 114 return true; 115 } 116 117 function noop () { 118 119 if(!isset($this->FP)) { 120 $this->ERROR = _("POP3 noop:") . ' ' . _("No connection to server"); 121 return false; 122 } else { 123 $cmd = "NOOP"; 124 $reply = $this->send_cmd( $cmd ); 125 return( $this->is_ok( $reply ) ); 126 } 127 } 128 129 function user ($user = "") { 130 // Sends the USER command, returns true or false 131 132 if( empty($user) ) { 133 $this->ERROR = _("POP3 user:") . ' ' . _("no login ID submitted"); 134 return false; 135 } elseif(!isset($this->FP)) { 136 $this->ERROR = _("POP3 user:") . ' ' . _("connection not established"); 137 return false; 138 } else { 139 $reply = $this->send_cmd("USER $user"); 140 if(!$this->is_ok($reply)) { 141 $this->ERROR = _("POP3 user:") . ' ' . _("Error ") . "[$reply]"; 142 return false; 143 } else 144 return true; 145 } 146 } 147 148 function pass ($pass = "") { 149 // Sends the PASS command, returns # of msgs in mailbox, 150 // returns false (undef) on Auth failure 151 152 if(empty($pass)) { 153 $this->ERROR = _("POP3 pass:") . ' ' . _("No password submitted"); 154 return false; 155 } elseif(!isset($this->FP)) { 156 $this->ERROR = _("POP3 pass:") . ' ' . _("connection not established"); 157 return false; 158 } else { 159 $reply = $this->send_cmd("PASS $pass"); 160 if(!$this->is_ok($reply)) { 161 $this->ERROR = _("POP3 pass:") . ' ' . _("authentication failed ") . "[$reply]"; 162 $this->quit(); 163 return false; 164 } else { 165 // Auth successful. 166 $count = $this->last("count"); 167 $this->COUNT = $count; 168 $this->RFC1939 = $this->noop(); 169 if(!$this->RFC1939) { 170 $this->ERROR = _("POP3 pass:") . ' ' . _("NOOP failed. Server not RFC 1939 compliant"); 171 $this->quit(); 172 return false; 173 } else 174 return $count; 175 } 176 } 177 } 178 179 function apop ($login,$pass) { 180 // Attempts an APOP login. If this fails, it'll 181 // try a standard login. YOUR SERVER MUST SUPPORT 182 // THE USE OF THE APOP COMMAND! 183 // (apop is optional per rfc1939) 184 185 if(!isset($this->FP)) { 186 $this->ERROR = _("POP3 apop:") . ' ' . _("No connection to server"); 187 return false; 188 } elseif(!$this->ALLOWAPOP) { 189 $retVal = $this->login($login,$pass); 190 return $retVal; 191 } elseif(empty($login)) { 192 $this->ERROR = _("POP3 apop:") . ' ' . _("No login ID submitted"); 193 return false; 194 } elseif(empty($pass)) { 195 $this->ERROR = _("POP3 apop:") . ' ' . _("No password submitted"); 196 return false; 197 } else { 198 $banner = $this->BANNER; 199 if( (!$banner) or (empty($banner)) ) { 200 $this->ERROR = _("POP3 apop:") . ' ' . _("No server banner") . ' - ' . _("abort"); 201 $retVal = $this->login($login,$pass); 202 return $retVal; 203 } else { 204 $AuthString = $banner; 205 $AuthString .= $pass; 206 $APOPString = md5($AuthString); 207 $cmd = "APOP $login $APOPString"; 208 $reply = $this->send_cmd($cmd); 209 if(!$this->is_ok($reply)) { 210 $this->ERROR = _("POP3 apop:") . ' ' . _("apop authentication failed") . ' - ' . _("abort"); 211 $retVal = $this->login($login,$pass); 212 return $retVal; 213 } else { 214 // Auth successful. 215 $count = $this->last("count"); 216 $this->COUNT = $count; 217 $this->RFC1939 = $this->noop(); 218 if(!$this->RFC1939) { 219 $this->ERROR = _("POP3 apop:") . ' ' . _("NOOP failed. Server not RFC 1939 compliant"); 220 $this->quit(); 221 return false; 222 } else 223 return $count; 224 } 225 } 226 } 227 } 228 229 function login ($login = "", $pass = "") { 230 // Sends both user and pass. Returns # of msgs in mailbox or 231 // false on failure (or -1, if the error occurs while getting 232 // the number of messages.) 233 234 if( !isset($this->FP) ) { 235 $this->ERROR = _("POP3 login:") . ' ' . _("No connection to server"); 236 return false; 237 } else { 238 $fp = $this->FP; 239 if( !$this->user( $login ) ) { 240 // Preserve the error generated by user() 241 return false; 242 } else { 243 $count = $this->pass($pass); 244 if( (!$count) || ($count == -1) ) { 245 // Preserve the error generated by last() and pass() 246 return false; 247 } else 248 return $count; 249 } 250 } 251 } 252 253 function top ($msgNum, $numLines = "0") { 254 // Gets the header and first $numLines of the msg body 255 // returns data in an array with each returned line being 256 // an array element. If $numLines is empty, returns 257 // only the header information, and none of the body. 258 259 if(!isset($this->FP)) { 260 $this->ERROR = _("POP3 top:") . ' ' . _("No connection to server"); 261 return false; 262 } 263 $this->update_timer(); 264 265 $fp = $this->FP; 266 $buffer = $this->BUFFER; 267 $cmd = "TOP $msgNum $numLines"; 268 fwrite($fp, "TOP $msgNum $numLines\r\n"); 269 $reply = fgets($fp, $buffer); 270 $reply = $this->strip_clf($reply); 271 if($this->DEBUG) { 272 @error_log("POP3 SEND [$cmd] GOT [$reply]",0); 273 } 274 if(!$this->is_ok($reply)) 275 { 276 $this->ERROR = _("POP3 top:") . ' ' . _("Error ") . "[$reply]"; 277 return false; 278 } 279 280 $count = 0; 281 $MsgArray = array(); 282 283 $line = fgets($fp,$buffer); 284 while ( !ereg("^\.\r\n",$line)) 285 { 286 $MsgArray[$count] = $line; 287 $count++; 288 $line = fgets($fp,$buffer); 289 if(empty($line)) { break; } 290 } 291 292 return $MsgArray; 293 } 294 295 function pop_list ($msgNum = "") { 296 // If called with an argument, returns that msgs' size in octets 297 // No argument returns an associative array of undeleted 298 // msg numbers and their sizes in octets 299 300 if(!isset($this->FP)) 301 { 302 $this->ERROR = _("POP3 pop_list:") . ' ' . _("No connection to server"); 303 return false; 304 } 305 $fp = $this->FP; 306 $Total = $this->COUNT; 307 if( (!$Total) or ($Total == -1) ) 308 { 309 return false; 310 } 311 if($Total == 0) 312 { 313 return array("0","0"); 314 // return -1; // mailbox empty 315 } 316 317 $this->update_timer(); 318 319 if(!empty($msgNum)) 320 { 321 $cmd = "LIST $msgNum"; 322 fwrite($fp,"$cmd\r\n"); 323 $reply = fgets($fp,$this->BUFFER); 324 $reply = $this->strip_clf($reply); 325 if($this->DEBUG) { 326 @error_log("POP3 SEND [$cmd] GOT [$reply]",0); 327 } 328 if(!$this->is_ok($reply)) 329 { 330 $this->ERROR = _("POP3 pop_list:") . ' ' . _("Error ") . "[$reply]"; 331 return false; 332 } 333 list($junk,$num,$size) = explode(" ",$reply); 334 return $size; 335 } 336 $cmd = "LIST"; 337 $reply = $this->send_cmd($cmd); 338 if(!$this->is_ok($reply)) 339 { 340 $reply = $this->strip_clf($reply); 341 $this->ERROR = _("POP3 pop_list:") . ' ' . _("Error ") . "[$reply]"; 342 return false; 343 } 344 $MsgArray = array(); 345 $MsgArray[0] = $Total; 346 for($msgC=1;$msgC <= $Total; $msgC++) 347 { 348 if($msgC > $Total) { break; } 349 $line = fgets($fp,$this->BUFFER); 350 $line = $this->strip_clf($line); 351 if(ereg("^\.",$line)) 352 { 353 $this->ERROR = _("POP3 pop_list:") . ' ' . _("Premature end of list"); 354 return false; 355 } 356 list($thisMsg,$msgSize) = explode(" ",$line); 357 settype($thisMsg,"integer"); 358 if($thisMsg != $msgC) 359 { 360 $MsgArray[$msgC] = "deleted"; 361 } 362 else 363 { 364 $MsgArray[$msgC] = $msgSize; 365 } 366 } 367 return $MsgArray; 368 } 369 370 function get ($msgNum) { 371 // Retrieve the specified msg number. Returns an array 372 // where each line of the msg is an array element. 373 374 if(!isset($this->FP)) 375 { 376 $this->ERROR = _("POP3 get:") . ' ' . _("No connection to server"); 377 return false; 378 } 379 380 $this->update_timer(); 381 382 $fp = $this->FP; 383 $buffer = $this->BUFFER; 384 $cmd = "RETR $msgNum"; 385 $reply = $this->send_cmd($cmd); 386 387 if(!$this->is_ok($reply)) 388 { 389 $this->ERROR = _("POP3 get:") . ' ' . _("Error ") . "[$reply]"; 390 return false; 391 } 392 393 $count = 0; 394 $MsgArray = array(); 395 396 $line = fgets($fp,$buffer); 397 while ( !ereg("^\.\r\n",$line)) 398 { 399 $MsgArray[$count] = $line; 400 $count++; 401 $line = fgets($fp,$buffer); 402 if(empty($line)) { break; } 403 } 404 return $MsgArray; 405 } 406 407 function last ( $type = "count" ) { 408 // Returns the highest msg number in the mailbox. 409 // returns -1 on error, 0+ on success, if type != count 410 // results in a popstat() call (2 element array returned) 411 412 $last = -1; 413 if(!isset($this->FP)) 414 { 415 $this->ERROR = _("POP3 last:") . ' ' . _("No connection to server"); 416 return $last; 417 } 418 419 $reply = $this->send_cmd("STAT"); 420 if(!$this->is_ok($reply)) 421 { 422 $this->ERROR = _("POP3 last:") . ' ' . _("Error ") . "[$reply]"; 423 return $last; 424 } 425 426 $Vars = explode(" ",$reply); 427 $count = $Vars[1]; 428 $size = $Vars[2]; 429 settype($count,"integer"); 430 settype($size,"integer"); 431 if($type != "count") 432 { 433 return array($count,$size); 434 } 435 return $count; 436 } 437 438 function reset () { 439 // Resets the status of the remote server. This includes 440 // resetting the status of ALL msgs to not be deleted. 441 // This method automatically closes the connection to the server. 442 443 if(!isset($this->FP)) 444 { 445 $this->ERROR = _("POP3 reset:") . ' ' . _("No connection to server"); 446 return false; 447 } 448 $reply = $this->send_cmd("RSET"); 449 if(!$this->is_ok($reply)) 450 { 451 // The POP3 RSET command -never- gives a -ERR 452 // response - if it ever does, something truely 453 // wild is going on. 454 455 $this->ERROR = _("POP3 reset:") . ' ' . _("Error ") . "[$reply]"; 456 @error_log("POP3 reset: ERROR [$reply]",0); 457 } 458 $this->quit(); 459 return true; 460 } 461 462 function send_cmd ( $cmd = "" ) 463 { 464 // Sends a user defined command string to the 465 // POP server and returns the results. Useful for 466 // non-compliant or custom POP servers. 467 // Do NOT includ the \r\n as part of your command 468 // string - it will be appended automatically. 469 470 // The return value is a standard fgets() call, which 471 // will read up to $this->BUFFER bytes of data, until it 472 // encounters a new line, or EOF, whichever happens first. 473 474 // This method works best if $cmd responds with only 475 // one line of data. 476 477 if(!isset($this->FP)) 478 { 479 $this->ERROR = _("POP3 send_cmd:") . ' ' . _("No connection to server"); 480 return false; 481 } 482 483 if(empty($cmd)) 484 { 485 $this->ERROR = _("POP3 send_cmd:") . ' ' . _("Empty command string"); 486 return ""; 487 } 488 489 $fp =