/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { parent::execute(); //we only expect 221 response, any other is not acceptable if (!$this->response->isOfType($this->successResponses)) { throw new InvalidStateException('Connection to the SMTP server could not be correctly closed. ' . 'The server provided the following response to the QUIT command:' . $this->response); } return NULL; }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } return NULL; }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { parent::execute(); return NULL; }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL|array of key=>val If the command has some interesting * output, return it in the assoc. array * and these values should be then stored * in the client's data store * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { if ($this->data === '') { throw new InvalidStateException('Trying to send email, but its contents were not specified.' . 'Please call DataCommand::setData before executing it.'); } $this->command = $this->initialCommand; $this->successResponses = $this->initialSuccessResponses; $this->failResponses = $this->initialFailResponses; parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } $this->command = $this->data; $this->successResponses = $this->dataSuccessResponses; $this->failResponses = $this->dataFailResponses; parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } return NULL; }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL|array: * extensions => Array of supported server extensions * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { $this->command = 'EHLO'; $this->failResponses = array('500'); parent::execute(); if ($this->response->isOfType('500')) { //EHLO was not recognized, so try HELO $this->command = 'HELO'; $this->failResponses = array(); parent::execute(); return NULL; } else { $extensions = $this->response->getMessage(); array_shift($extensions); return array('extensions' => $extensions); } }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return array of key=>val: * undelivered => Array of addresses the mail couldn't be delivered to * toDeliver => Array of internal format of the addresses not yet * tried to send the email to. If set, causes the client to repeat * the message sending procedure with these recipients (possible * infinte loop - be sure this array always gets smaller than * before) * recipientsCount => Number of the recipients the message will really * be sent to * * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { $undeliveredRecipients = array(); $recipientsCount = 0; while (count($this->recipients) >= 1) { //send the command and read the response parent::execute(); $recipient = array_pop($this->recipients); switch ($this->response->getCode()) { case '250': case '251': if (isset($recipient['original_email'])) { //we finally delivered mail to a user that provided a //forward-address $key = array_search($recipient['original_email'], $undeliveredRecipients); if ($key !== FALSE) { unset($undeliveredRecipients[$key]); } } $recipientsCount++; break; case '450': case '451': //add the recipient to the begginning of the queue to try again //later if ($recipient['retries'] > 0) { $recipient['retries']--; array_unshift($this->recipients, $recipient); } break; /* Handle too much recipients by splitting the message to chunks * * RFC 821 [30] incorrectly listed the error where an SMTP server * exhausts its implementation limit on the number of RCPT commands * ("too many recipients") as having reply code 552. The correct * reply code for this condition is 452. Clients SHOULD treat a * 552 code in this case as a temporary, rather than permanent, * failure so the logic below works. */ /* Handle too much recipients by splitting the message to chunks * * RFC 821 [30] incorrectly listed the error where an SMTP server * exhausts its implementation limit on the number of RCPT commands * ("too many recipients") as having reply code 552. The correct * reply code for this condition is 452. Clients SHOULD treat a * 552 code in this case as a temporary, rather than permanent, * failure so the logic below works. */ case '452': case '552': array_push($this->recipients, $recipient); $result['undelivered'] = $undeliveredRecipients; //this causes the client to append a new mail sending sequence //for the rest of recipients $result['toDeliver'] = $this->recipients; $result['recipientsCount'] = $recipientsCount; return $result; break; //unreachable //unreachable case '550': case '553': $undeliveredRecipients[] = $recipient['email']; break; case '551': if (preg_match('/<\\([^>]*\\)>/', $this->response, $matches)) { $forward = array(); $forward['email'] = $matches[1]; $forward['retries'] = 2; if (isset($recipient['original_email'])) { $forward['original_email'] = $recipient['original_email']; } else { $forward['original_email'] = $recipient['email']; $undeliveredRecipients[] = $recipient['email']; } $this->recipients[] = $forward; } break; } } return array('undelivered' => $undeliveredRecipients, 'recipientsCount' => $recipientsCount); }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { switch ($this->mechanism) { case 'LOGIN': if (count($this->credentials) < 2) { throw new InvalidStateException('You must provide username and password when using ' . 'LOGIN authentication mechanism'); } $this->successResponses = array('334'); // -> AUTH LOGIN $this->command = 'AUTH LOGIN'; parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } // <- Username: // -> username $this->command = base64_encode($this->credentials[0]); parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } $this->successResponses = array('235'); // <- Password: // -> password $this->command = base64_encode($this->credentials[1]); parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } break; case 'PLAIN': if (count($this->credentials) < 3) { throw new InvalidStateException('You must provide authId, username and password when ' . 'using PLAIN authentication mechanism'); } $this->successResponses = array('235'); // -> AUTH PLAIN authId\0username\0password $this->command = 'AUTH PLAIN ' . base64_encode($this->credentials[0] . "" . $this->credentials[1] . "" . $this->credentials[2]); parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } break; case 'CRAM-MD5': if (count($this->credentials) < 2) { throw new InvalidStateException('You must provide username and password when using ' . 'CRAM-MD5 authentication mechanism'); } $this->successResponses = array('334'); $this->command = 'AUTH CRAM-MD5'; parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } $challenge = base64_decode(implode(' ', $this->response->getMessage())); $this->successResponses = array('235'); $this->command = base64_encode($this->credentials[0] . ' ' . hash_hmac('md5', $challenge, $this->credentials[1])); parent::execute(); if ($this->response->isOfType($this->failResponses)) { return array('retry' => TRUE); } break; default: throw new InvalidStateException('Unsupported authentication mechanism: ' . $this->mechanism); break; } return NULL; }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { parent::execute(); stream_socket_enable_crypto($this->getCommunicator()->getConnection(), TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT); return NULL; }
/** * Execute the command, handle error states and throw InvalidStateException * if an unrecoverable error occurs. Should be overridden, but always call * parent::execute() !!! * * @return NULL * @throws InvalidStateException If an unrecoverable error occurs */ public function execute() { parent::execute(); //we only expect 220 response, any other non-5xy is not acceptable if (!$this->response->isOfType($this->successResponses)) { throw new InvalidStateException('The server\' s response to command ' . $this->name . 'was not recognized by the client. The response was: ' . $this->response); } return NULL; }