public function Validate() { if (parent::Validate()) { if (strlen(trim($this->strText))) { // RegExp taken from php.net $this->strText = trim($this->strText); $strEmailAddressArray = QEmailServer::GetEmailAddresses($this->strText); if (count($strEmailAddressArray) != 1 || strtolower($strEmailAddressArray[0]) != strtolower($this->strText)) { $this->strValidationError = "Invalid e-mail address"; return false; } } } else { return false; } $this->strValidationError = ""; return true; }
/** * Sends a message out via SMTP according to the server, ip, etc. preferences * as set up on the class. Takes in a QEmailMessage object. * * Will throw a QEmailException exception on any error. * * @param QEmailMessage $objMessage Message to Send * @return void */ public static function Send(QEmailMessage $objMessage) { $objResource = null; if (QEmailServer::$TestMode) { // Open up a File Resource to the TestModeDirectory $strArray = explode(' ', microtime()); $strFileName = sprintf('%s/email_%s%s.txt', QEmailServer::$TestModeDirectory, $strArray[1], substr($strArray[0], 1)); $objResource = fopen($strFileName, 'w'); if (!$objResource) { throw new QEmailException(sprintf('Unable to open Test SMTP connection to: %s', $strFileName)); } // Clear the Read Buffer if (!feof($objResource)) { fgets($objResource, 4096); } // Write the Connection Command fwrite($objResource, sprintf("telnet %s %s\r\n", QEmailServer::$SmtpServer, QEmailServer::$SmtpPort)); } else { $objResource = fsockopen(QEmailServer::$SmtpServer, QEmailServer::$SmtpPort); if (!$objResource) { throw new QEmailException(sprintf('Unable to open SMTP connection to: %s %s', QEmailServer::$SmtpServer, QEmailServer::$SmtpPort)); } } // Connect $strResponse = null; if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); // Iterate through all "220-" responses (stop at "220 ") while (substr($strResponse, 0, 3) == "220" && substr($strResponse, 0, 4) != "220 ") { if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } } // Check for a "220" response if (strpos($strResponse, "220") === false || strpos($strResponse, "220") != 0) { throw new QEmailException(sprintf('Error Response on Connect: %s', $strResponse)); } } // Send: EHLO fwrite($objResource, sprintf("EHLO %s\r\n", QEmailServer::$OriginatingServerIp)); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); // Iterate through all "250-" responses (stop at "250 ") while (substr($strResponse, 0, 3) == "250" && substr($strResponse, 0, 4) != "250 ") { if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } } // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on EHLO: %s', $strResponse)); } } // Send Authentication if (QEmailServer::$AuthPlain) { fwrite($objResource, "AUTH PLAIN " . base64_encode(QEmailServer::$SmtpUsername . "" . QEmailServer::$SmtpUsername . "" . QEmailServer::$SmtpPassword) . "\r\n"); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); if (strpos($strResponse, "235") === false || strpos($strResponse, "235") != 0) { throw new QEmailException(sprintf('Error in response from AUTH PLAIN: %s', $strResponse)); } } } if (QEmailServer::$AuthLogin) { fwrite($objResource, "AUTH LOGIN\r\n"); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); if (strpos($strResponse, "334") === false || strpos($strResponse, "334") != 0) { throw new QEmailException(sprintf('Error in response from AUTH LOGIN: %s', $strResponse)); } } fwrite($objResource, base64_encode(QEmailServer::$SmtpUsername) . "\r\n"); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); if (strpos($strResponse, "334") === false || strpos($strResponse, "334") != 0) { throw new QEmailException(sprintf('Error in response from AUTH LOGIN: %s', $strResponse)); } } fwrite($objResource, base64_encode(QEmailServer::$SmtpPassword) . "\r\n"); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); if (strpos($strResponse, "235") === false || strpos($strResponse, "235") != 0) { throw new QEmailException(sprintf('Error in response from AUTH LOGIN: %s', $strResponse)); } } } // Setup MAIL FROM line $strAddressArray = QEmailServer::GetEmailAddresses($objMessage->From); if (count($strAddressArray) != 1) { throw new QEmailException(sprintf('Not a valid From address: %s', $objMessage->From)); } // Send: MAIL FROM line fwrite($objResource, sprintf("MAIL FROM: <%s>\r\n", $strAddressArray[0])); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on MAIL FROM: %s', $strResponse)); } } // Setup RCPT TO line(s) $strAddressToArray = QEmailServer::GetEmailAddresses($objMessage->To); if (!$strAddressToArray) { throw new QEmailException(sprintf('Not a valid To address: %s', $objMessage->To)); } $strAddressCcArray = QEmailServer::GetEmailAddresses($objMessage->Cc); if (!$strAddressCcArray) { $strAddressCcArray = array(); } $strAddressBccArray = QEmailServer::GetEmailAddresses($objMessage->Bcc); if (!$strAddressBccArray) { $strAddressBccArray = array(); } $strAddressCcBccArray = array_merge($strAddressCcArray, $strAddressBccArray); $strAddressArray = array_merge($strAddressToArray, $strAddressCcBccArray); // Send: RCPT TO line(s) foreach ($strAddressArray as $strAddress) { fwrite($objResource, sprintf("RCPT TO: <%s>\r\n", $strAddress)); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on RCPT TO: %s', $strResponse)); } } } // Send: DATA fwrite($objResource, "DATA\r\n"); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "354" response if (strpos($strResponse, "354") === false || strpos($strResponse, "354") != 0) { throw new QEmailException(sprintf('Error Response on DATA: %s', $strResponse)); } } // Send: Required Headers fwrite($objResource, sprintf("Date: %s\r\n", QDateTime::NowToString(QDateTime::FormatRfc822))); fwrite($objResource, sprintf("To: %s\r\n", $objMessage->To)); fwrite($objResource, sprintf("From: %s\r\n", $objMessage->From)); // Send: Optional Headers if ($objMessage->Subject) { fwrite($objResource, sprintf("Subject: %s\r\n", $objMessage->Subject)); } if ($objMessage->Cc) { fwrite($objResource, sprintf("Cc: %s\r\n", $objMessage->Cc)); } // Send: Content-Type Header (if applicable) $semi_random = md5(time()); $strBoundary = sprintf('==qcodo_qemailserver_multipart_boundary____x%sx', $semi_random); // Send: Other Headers (if any) foreach ($objArray = $objMessage->HeaderArray as $strKey => $strValue) { fwrite($objResource, sprintf("%s: %s\r\n", $strKey, $strValue)); } // if we are adding an html or files to the message we need these headers. if ($objMessage->HasFiles || $objMessage->HtmlBody) { fwrite($objResource, "MIME-Version: 1.0\r\n"); fwrite($objResource, sprintf("Content-Type: multipart/mixed;\r\n boundary=\"%s\"\r\n", $strBoundary)); fwrite($objResource, sprintf("This is a multipart message in MIME format.\r\n\r\n", $strBoundary)); fwrite($objResource, sprintf("--%s\r\n", $strBoundary)); } $strAltBoundary = sprintf('==qcodo_qemailserver_alternative_boundary____x%sx', $semi_random); // Send: Body // Setup Encoding Type (use QEmailServer if specified, otherwise default to QApplication's) if (!($strEncodingType = QEmailServer::$EncodingType)) { $strEncodingType = QApplication::$EncodingType; } if ($objMessage->HtmlBody) { fwrite($objResource, sprintf("Content-Type: multipart/alternative;\r\n boundary=\"%s\"\r\n\r\n", $strAltBoundary)); fwrite($objResource, sprintf("--%s\r\n", $strAltBoundary)); fwrite($objResource, sprintf("Content-Type: text/plain; charset=\"%s\"\r\n", $strEncodingType)); fwrite($objResource, sprintf("Content-Transfer-Encoding: 7bit\r\n\r\n")); fwrite($objResource, $objMessage->Body); fwrite($objResource, "\r\n\r\n"); fwrite($objResource, sprintf("--%s\r\n", $strAltBoundary)); fwrite($objResource, sprintf("Content-Type: text/html; charset=\"%s\"\r\n", $strEncodingType)); // fwrite($objResource, sprintf("Content-Transfer-Encoding: quoted-printable\r\n\r\n")); fwrite($objResource, sprintf("Content-Transfer-Encoding: 7bit\r\n\r\n")); fwrite($objResource, $objMessage->HtmlBody); fwrite($objResource, "\r\n\r\n"); fwrite($objResource, sprintf("--%s--\r\n", $strAltBoundary)); } elseif ($objMessage->HasFiles) { fwrite($objResource, sprintf("Content-Type: multipart/alternative;\r\n boundary=\"%s\"\r\n\r\n", $strAltBoundary)); fwrite($objResource, sprintf("--%s\r\n", $strAltBoundary)); fwrite($objResource, sprintf("Content-Type: text/plain; charset=\"%s\"\r\n", $strEncodingType)); fwrite($objResource, sprintf("Content-Transfer-Encoding: 7bit\r\n\r\n")); fwrite($objResource, $objMessage->Body); fwrite($objResource, "\r\n\r\n"); fwrite($objResource, sprintf("--%s--\r\n", $strAltBoundary)); } else { fwrite($objResource, sprintf("Content-Type: text/plain; charset=\"%s\"\r\n", $strEncodingType)); fwrite($objResource, sprintf("Content-Transfer-Encoding: 7bit\r\n\r\n")); fwrite($objResource, "\r\n" . $objMessage->Body); } // Send: File Attachments if ($objMessage->HasFiles) { foreach ($objArray = $objMessage->FileArray as $objFile) { fwrite($objResource, sprintf("--%s\r\n", $strBoundary)); fwrite($objResource, sprintf("Content-Type: %s;\r\n", $objFile->MimeType)); fwrite($objResource, sprintf(" name=\"%s\"\r\n", $objFile->FileName)); fwrite($objResource, "Content-Transfer-Encoding: base64\r\n"); fwrite($objResource, sprintf("Content-Length: %s\r\n", strlen($objFile->EncodedFileData))); fwrite($objResource, "Content-Disposition: attachment;\r\n"); fwrite($objResource, sprintf(" filename=\"%s\"\r\n\r\n", $objFile->FileName)); fwrite($objResource, $objFile->EncodedFileData); // foreach (explode("\n", $objFile->EncodedFileData) as $strLine) { // $strLine = trim($strLine); // fwrite($objResource, $strLine . "\r\n"); // } } } // close a message with these boundaries if the message had files or had html if ($objMessage->HasFiles || $objMessage->HtmlBody) { fwrite($objResource, sprintf("\r\n\r\n--%s--\r\n", $strBoundary)); } // send end of file attachments... // Send: Message End fwrite($objResource, "\r\n.\r\n"); if (!QEmailServer::$TestMode && !feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on MAIL FROM: %s', $strResponse)); } } // Send: QUIT fwrite($objResource, "QUIT\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } // Close the Resource fclose($objResource); }
/** * Uses SendRawMessage to sends a message out via SMTP according to the server, ip, etc. preferences * as set up on the class. Takes in a QEmailMessage object to calculate the appropriate fields * to SendRawMesage. * * Will throw a QEmailException exception on any error. * * @param QEmailMessage $objMessage Message to Send * @return void */ public static function Send(QEmailMessage $objMessage) { // Set Up Fields $strAddressArray = QEmailServer::GetEmailAddresses($objMessage->From); if (count($strAddressArray) != 1) { throw new QEmailException(sprintf('Not a valid From address: %s', $objMessage->From)); } $strMailFrom = $strAddressArray[0]; // Setup RCPT TO Addresses $strAddressToArray = QEmailServer::GetEmailAddresses($objMessage->To); if (!$strAddressToArray || !count($strAddressToArray)) { throw new QEmailException(sprintf('Not a valid To address: %s', $objMessage->To)); } $strAddressCcArray = QEmailServer::GetEmailAddresses($objMessage->Cc); if (!$strAddressCcArray) { $strAddressCcArray = array(); } $strAddressBccArray = QEmailServer::GetEmailAddresses($objMessage->Bcc); if (!$strAddressBccArray) { $strAddressBccArray = array(); } $strAddressCcBccArray = array_merge($strAddressCcArray, $strAddressBccArray); $strRcptToArray = array_merge($strAddressToArray, $strAddressCcBccArray); $strMessageArray = $objMessage->CalculateMessageHeaderAndBody(self::$EncodingType); self::SendRawMessage($strMailFrom, $strRcptToArray, $strMessageArray[0], $strMessageArray[1]); }
/** * Sends a message out via SMTP according to the server, ip, etc. preferences * as set up on the class. Takes in a QEmailMessage object. * * Will throw a QEmailException exception on any error. * * @param QEmailMessage $objMessage Message to Send * @return void */ public static function Send(QEmailMessage $objMessage) { $objResource = null; if (QEmailServer::$TestMode) { // Open up a File Resource to the TestModeDirectory $strArray = split(' ', microtime()); $strFileName = sprintf('%s/email_%s%s.txt', QEmailServer::$TestModeDirectory, $strArray[1], substr($strArray[0], 1)); $objResource = fopen($strFileName, 'w'); if (!$objResource) { throw new QEmailException(sprintf('Unable to open Test SMTP connection to: %s', $strFileName)); } // Clear the Read Buffer if (!feof($objResource)) { fgets($objResource, 4096); } // Write the Connection Command fwrite($objResource, sprintf("telnet %s %s\r\n", QEmailServer::$SmtpServer, QEmailServer::$SmtpPort)); } else { $objResource = fsockopen(QEmailServer::$SmtpServer, QEmailServer::$SmtpPort); if (!$objResource) { throw new QEmailException(sprintf('Unable to open SMTP connection to: %s %s', QEmailServer::$SmtpServer, QEmailServer::$SmtpPort)); } } // Connect $strResponse = null; if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "220" response if (strpos($strResponse, "220") === false || strpos($strResponse, "220") != 0) { throw new QEmailException(sprintf('Error Response on Connect: %s', $strResponse)); } } // Send: EHLO fwrite($objResource, sprintf("EHLO %s\r\n", QEmailServer::$OriginatingServerIp)); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); // Iterate through all "250-" responses (stop at "250 ") while (substr($strResponse, 0, 3) == "250" && substr($strResponse, 0, 4) != "250 ") { if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } } // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on EHLO: %s', $strResponse)); } } // Send Authentication if (QEmailServer::$AuthPlain) { fwrite($objResource, "AUTH PLAIN " . base64_encode(QEmailServer::$SmtpUsername . "" . QEmailServer::$SmtpUsername . "" . QEmailServer::$SmtpPassword) . "\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } if (strpos($strResponse, "235") === false || strpos($strResponse, "235") != 0) { throw new QEmailException(sprintf('Error in response from AUTH PLAIN: %s', $strResponse)); } } if (QEmailServer::$AuthLogin) { fwrite($objResource, "AUTH LOGIN\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } if (strpos($strResponse, "334") === false || strpos($strResponse, "334") != 0) { throw new QEmailException(sprintf('Error in response from AUTH LOGIN: %s', $strResponse)); } fwrite($objResource, base64_encode(QEmailServer::$SmtpUsername) . "\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } if (strpos($strResponse, "334") === false || strpos($strResponse, "334") != 0) { throw new QEmailException(sprintf('Error in response from AUTH LOGIN: %s', $strResponse)); } fwrite($objResource, base64_encode(QEmailServer::$SmtpPassword) . "\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } if (strpos($strResponse, "235") === false || strpos($strResponse, "235") != 0) { throw new QEmailException(sprintf('Error in response from AUTH LOGIN: %s', $strResponse)); } } // Setup MAIL FROM line $strAddressArray = QEmailServer::GetEmailAddresses($objMessage->From); if (count($strAddressArray) != 1) { throw new QEmailException(sprintf('Not a valid From address: %s', $objMessage->From)); } // Send: MAIL FROM line fwrite($objResource, sprintf("MAIL FROM: %s\r\n", $strAddressArray[0])); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on MAIL FROM: %s', $strResponse)); } } // Setup RCPT TO line(s) $strAddressToArray = QEmailServer::GetEmailAddresses($objMessage->To); if (!$strAddressToArray) { throw new QEmailException(sprintf('Not a valid To address: %s', $objMessage->To)); } $strAddressCcArray = QEmailServer::GetEmailAddresses($objMessage->Cc); if (!$strAddressCcArray) { $strAddressCcArray = array(); } $strAddressBccArray = QEmailServer::GetEmailAddresses($objMessage->Bcc); if (!$strAddressBccArray) { $strAddressBccArray = array(); } $strAddressCcBccArray = array_merge($strAddressCcArray, $strAddressBccArray); $strAddressArray = array_merge($strAddressToArray, $strAddressCcBccArray); // Send: RCPT TO line(s) foreach ($strAddressArray as $strAddress) { fwrite($objResource, sprintf("RCPT TO: %s\r\n", $strAddress)); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on RCPT TO: %s', $strResponse)); } } } // Send: DATA fwrite($objResource, "DATA\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "354" response if (strpos($strResponse, "354") === false || strpos($strResponse, "354") != 0) { throw new QEmailException(sprintf('Error Response on DATA: %s', $strResponse)); } } // Send: Required Headers fwrite($objResource, sprintf("Date: %s\r\n", QDateTime::NowToString(QDateTime::FormatRfc822))); fwrite($objResource, sprintf("To: %s\r\n", $objMessage->To)); fwrite($objResource, sprintf("From: %s\r\n", $objMessage->From)); // Send: Optional Headers if ($objMessage->Subject) { fwrite($objResource, sprintf("Subject: %s\r\n", $objMessage->Subject)); } if ($objMessage->Cc) { fwrite($objResource, sprintf("Cc: %s\r\n", $objMessage->Cc)); } // Send: Content-Type Header (if applicable) $strBoundary = 'qcodo_qemailserver_multipart_boundary____'; if ($objMessage->HtmlBody) { fwrite($objResource, sprintf("Content-Type: multipart/alternative; boundary=\"%s\"\r\n", $strBoundary)); } // Send: Other Headers (if any) foreach ($objArray = $objMessage->HeaderArray as $strKey => $strValue) { fwrite($objResource, sprintf("%s: %s\r\n", $strKey, $strValue)); } // Send: Body fwrite($objResource, "\r\n"); if ($objMessage->HtmlBody) { fwrite($objResource, sprintf("--%s\r\n", $strBoundary)); fwrite($objResource, sprintf("Content-Type: text/plain; charset=%s\r\n\r\n", QApplication::$EncodingType)); fwrite($objResource, $objMessage->Body); fwrite($objResource, "\r\n\r\n\r\n"); fwrite($objResource, sprintf("--%s\r\n", $strBoundary)); fwrite($objResource, sprintf("Content-Type: text/html; charset=%s\r\n\r\n", QApplication::$EncodingType)); fwrite($objResource, $objMessage->HtmlBody); fwrite($objResource, "\r\n\r\n\r\n"); fwrite($objResource, sprintf("--%s--\r\n", $strBoundary)); } else { fwrite($objResource, $objMessage->Body); } // Send: Message End fwrite($objResource, "\r\n.\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); // Check for a "250" response if (strpos($strResponse, "250") === false || strpos($strResponse, "250") != 0) { throw new QEmailException(sprintf('Error Response on MAIL FROM: %s', $strResponse)); } } // Send: QUIT fwrite($objResource, "QUIT\r\n"); if (!feof($objResource)) { $strResponse = fgets($objResource, 4096); } // Close the Resource fclose($objResource); }
/** * Given the "To" and "Cc" in the header, create an array of Email Addresses that should be looked up * @return string[] */ protected function CalculateEmailArray() { $strTo = $this->GetHeaderValue('To') . ', ' . $this->GetHeaderValue('Cc') . ', ' . $this->GetHeaderValue('TO') . ', ' . $this->GetHeaderValue('CC') . ', ' . $this->GetHeaderValue('to') . ', ' . $this->GetHeaderValue('cc'); $strArrayToReturn = array(); $strArrayToCheck = QEmailServer::GetEmailAddresses($strTo); if ($strArrayToCheck) { foreach ($strArrayToCheck as $strEmailAddress) { $strEmailAddress = strtolower($strEmailAddress); if (strpos($strEmailAddress, '@groups.alcf.net')) { $strArrayToReturn[$strEmailAddress] = $strEmailAddress; } } } return $strArrayToReturn; }