You are here

public function SMTP::Data in SMTP Authentication Support 7.2

Same name and namespace in other branches
  1. 5 smtp.module \SMTP::Data()
  2. 7 smtp.transport.inc \SMTP::Data()

Issues a data command and sends the msg_data to the server finializing the mail transaction. $msg_data is the message that is to be send with the headers. Each header needs to be on a single line followed by a <CRLF> with the message headers and the message body being separated by and additional <CRLF>.

Implements rfc 821: DATA <CRLF>

SMTP CODE INTERMEDIATE: 354 [data] <CRLF>.<CRLF> SMTP CODE SUCCESS: 250 SMTP CODE FAILURE: 552,554,451,452 SMTP CODE FAILURE: 451,554 SMTP CODE ERROR : 500,501,503,421 @access public

Return value

bool

File

./smtp.transport.inc, line 331
SMTP mail transport class for the smtp module,based on code of the phpmailer library, customized and relicensed to GPLv2

Class

SMTP
SMTP is rfc 821 compliant and implements all the rfc 821 SMTP commands except TURN which will always return a not implemented error. SMTP also provides some utility methods for sending mail to an SMTP server. original author: Chris Ryan

Code

public function Data($msg_data) {
  $this->error = NULL;

  // so no confusion is caused
  if (!$this
    ->connected()) {
    $this->error = array(
      "error" => "Called Data() without being connected",
    );
    return FALSE;
  }
  fputs($this->smtp_conn, "DATA" . $this->CRLF);
  $rply = $this
    ->get_lines();
  $code = substr($rply, 0, 3);
  if ($this->do_debug >= 2) {
    drupal_set_message(t("SMTP -> FROM SERVER: @rply", array(
      "@rply" => $rply,
    )));
  }
  if ($code != 354) {
    $this->error = array(
      "error" => "DATA command not accepted from server",
      "smtp_code" => $code,
      "smtp_msg" => substr($rply, 4),
    );
    if ($this->do_debug >= 1) {
      drupal_set_message(t("SMTP -> ERROR: @error: @rply", array(
        "@error" => $this->error["error"],
        "@rply" => $rply,
      )));
    }
    return FALSE;
  }

  /* the server is ready to accept data!
   * according to rfc 821 we should not send more than 1000
   * including the CRLF
   * characters on a single line so we will break the data up
   * into lines by \r and/or \n then if needed we will break
   * each of those into smaller lines to fit within the limit.
   * in addition we will be looking for lines that start with
   * a period '.' and append and additional period '.' to that
   * line. NOTE: this does not count towards limit.
   */

  // normalize the line breaks so we know the explode works
  $msg_data = str_replace("\r\n", "\n", $msg_data);
  $msg_data = str_replace("\r", "\n", $msg_data);
  $lines = explode("\n", $msg_data);

  /* we need to find a good way to determine is headers are
   * in the msg_data or if it is a straight msg body
   * currently I am assuming rfc 822 definitions of msg headers
   * and if the first field of the first line (':' sperated)
   * does not contain a space then it _should_ be a header
   * and we can process all lines before a blank "" line as
   * headers.
   */
  $field = substr($lines[0], 0, strpos($lines[0], ":"));
  $in_headers = FALSE;
  if (!empty($field) && !strstr($field, " ")) {
    $in_headers = TRUE;
  }
  $max_line_length = 998;

  // used below; set here for ease in change
  while (list(, $line) = @each($lines)) {
    $lines_out = NULL;
    if ($line == "" && $in_headers) {
      $in_headers = FALSE;
    }

    // ok we need to break this line up into several smaller lines
    while (strlen($line) > $max_line_length) {
      $pos = strrpos(substr($line, 0, $max_line_length), " ");

      // Patch to fix DOS attack
      if (!$pos) {
        $pos = $max_line_length - 1;
        $lines_out[] = substr($line, 0, $pos);
        $line = substr($line, $pos);
      }
      else {
        $lines_out[] = substr($line, 0, $pos);
        $line = substr($line, $pos + 1);
      }

      /* if processing headers add a LWSP-char to the front of new line
       * rfc 822 on long msg headers
       */
      if ($in_headers) {
        $line = "\t" . $line;
      }
    }
    $lines_out[] = $line;

    // send the lines to the server
    while (list(, $line_out) = @each($lines_out)) {
      if (strlen($line_out) > 0) {
        if (substr($line_out, 0, 1) == ".") {
          $line_out = "." . $line_out;
        }
      }
      fputs($this->smtp_conn, $line_out . $this->CRLF);
    }
  }

  // message data has been sent
  fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
  $rply = $this
    ->get_lines();
  $code = substr($rply, 0, 3);
  if ($this->do_debug >= 2) {
    drupal_set_message(t("SMTP -> FROM SERVER: @rply", array(
      "@rply" => $rply,
    )));
  }
  if ($code != 250) {
    $this->error = array(
      "error" => "DATA not accepted from server",
      "smtp_code" => $code,
      "smtp_msg" => substr($rply, 4),
    );
    if ($this->do_debug >= 1) {
      drupal_set_message(t("SMTP -> ERROR: @error: @rply", array(
        "@error" => $this->error["error"],
        "@rply" => $rply,
      )));
    }
    return FALSE;
  }
  return TRUE;
}