首页 > 解决方案 > PHPMailer 与 Ajax 示例我有错误 Uncaught (in promise) TypeError: error.json is not a function

问题描述

您好我正在使用https://github.com/PHPMailer/PHPMailer/blob/master/examples/contactform-ajax.phps中的示例

我做了一些修改以将此示例与 OAuthGoogle 2.0 一起使用。首先,我可以使用 XAMPP 发送电子邮件而没有任何问题,但现在我进行了测试,出现了一个问题并且电子邮件没有发送。我是使用 AJAX 的新手,所以我需要帮助才能正常工作。

问题是“未捕获(承诺中)TypeError:error.json 不是函数”

PHP

<?php
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\OAuth;
//Alias the League Google OAuth2 provider class
use League\OAuth2\Client\Provider\Google;



//Don't run this unless we're handling a form submission
if (array_key_exists('email', $_POST)) {
  date_default_timezone_set('Etc/UTC');
  require 'vendor/autoload.php';
  $isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
    strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';

  //Create a new PHPMailer instance
  $mail = new PHPMailer();


  //para evitar los errores en pantalla
  $mail->SMTPOptions = array(
    'ssl' => array(
      'verify_peer' => false,
      'verify_peer_name' => false,
      'allow_self_signed' => true
    )
  );

  //Tell PHPMailer to use SMTP
  $mail->isSMTP();

  //Enable SMTP debugging
  //SMTP::DEBUG_OFF = off (for production use)
  //SMTP::DEBUG_CLIENT = client messages
  //SMTP::DEBUG_SERVER = client and server messages
  $mail->SMTPDebug = SMTP::DEBUG_SERVER;

  //Set the hostname of the mail server
  $mail->Host = 'smtp.gmail.com';

  //Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
  $mail->Port = 587;

  //Set the encryption mechanism to use - STARTTLS or SMTPS
  $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

  //Whether to use SMTP authentication
  $mail->SMTPAuth = true;

  //Set AuthType to use XOAUTH2
  $mail->AuthType = 'XOAUTH2';

  //Fill in authentication details here
  //Either the gmail account owner, or the user that gave consent
  $email = 'here the mail';
  $clientId = 'client id';
  $clientSecret = 'here client secret';
  $refreshToken = 'token';

  //Create a new OAuth2 provider instance
  $provider = new Google(
    [
      'clientId' => $clientId,
      'clientSecret' => $clientSecret,
    ]
  );

  //Pass the OAuth provider instance to PHPMailer
  $mail->setOAuth(
    new OAuth(
      [
        'provider' => $provider,
        'clientId' => $clientId,
        'clientSecret' => $clientSecret,
        'refreshToken' => $refreshToken,
        'userName' => $email,
      ]
    )
  );

  $mail->setFrom($_POST['email'], $_POST['name']);
  $mail->addAddress('max************@gmail.com', 'Kraken Web');
  //Put the submitter's address in a reply-to header
  if ($mail->addReplyTo($_POST['email'], $_POST['name'])) {
    $mail->Subject = 'Formulario de Contacto Kraken Web';
    //Keep it simple - don't use HTML
    $mail->isHTML(false);
    //Build a simple message body
    $mail->Body = <<<EOT
Email: {$_POST['email']}
Name: {$_POST['name']}
Phone: {$_POST['phone']}
Message: {$_POST['message']}
EOT;

    //Send the message, check for errors
    if (!$mail->send()) {
      //The reason for failing to send will be in $mail->ErrorInfo
      //but it's unsafe to display errors directly to users - process the error, log it on your server.
      if ($isAjax) {
        http_response_code(500);
      }

      $response = [
        "status" => false,
        "messageText" => 'Sorry, something went wrong. Please try again later.'
      ];
    } else {
      $response = [
        "status" => true,
        "messageText" => 'Message sent! Thanks for contacting us.'
      ];
    }
  } else {
    $response = [
      "status" => false,
      "messageText" => 'Invalid email address, message ignored.'
    ];
  }

  if ($isAjax) {
    header('Content-type:application/json;charset=utf-8');
    echo json_encode($response);

    exit();
  }
}
?>

JS

 const form = document.getElementById("kraken-form")

    function email(data) {
      fetch("", {
          method: "POST",
          body: data,
          headers: {
            'X-Requested-With': 'XMLHttpRequest'
          }
        })
        .then(response => response.json())
        .then(response => {

          if (response.status == true) {
            $('.modal-title').html('<i class="fas fa-check-circle"></i>');
            $('.modal-body').html(response.messageText);
            $('.modal.header').removeClass('bg-danger');
            $('.modal-header').addClass('bg-success');
          } else {
            $('.modal-title').html('<i class="fas fa-exclamation-triangle"></i>');
            $('.modal-body').html(response.messageText);
            $('.modal-header').removeClass('bg-success');
            $('.modal-header').addClass('bg-danger');
          }

          // Display Modal
          $('#exampleModal').modal('show');
          setTimeout(function() {
            $("#kraken-form")[0].reset();
          }, 2000);
        })
        .catch(error => {
          error.json().then(response => {
            console.log(error);
            $('.modal-title').html(response.messageText);
            // Display Modal
            $('#exampleModal').modal('show');
          })
        })
    }


    const submitEvent = form.addEventListener("submit", (event) => {
      event.preventDefault();

      const formData = new FormData(form);

      email(formData);

    })


    document.querySelector('button[id=Aceptar]').addEventListener('click', function(e) {
      e.preventDefault();

      window.location.reload();
    });

表单 HTML

<form method="POST" id="kraken-form" class="contact-form px-md-5">
            <div class="form-floating mb-2">
              <input type="text" class="form-control" id="name" name="name" placeholder="Nombre y Apellido" autocomplete="off" required>
              <label for="name">Nombre y Apellido</label>
            </div>
            <div class="form-floating mb-2">
              <input type="text" class="form-control" id="phone" name="phone" placeholder="Teléfono" autocomplete="off" required>
              <label for="phone">Teléfono</label>
            </div>
            <div class="form-floating mb-2">
              <input type="email" class="form-control form-sm-control" id="email" name="email" placeholder="Email" autocomplete="off" required>
              <label for="email">Email</label>
            </div>
            <div class="form-floating mb-2">
              <textarea class="form-control" placeholder="Deje un comentario" id="message" name="message"></textarea>
              <label for="message">Deje un comentario...</label>
            </div>
            <div class="d-grid py-2 gap-2">
              <input class="btn-option" type="submit" value="Enviar" id="send">
            </div>
          </form>

标签: phpjqueryajaxphpmailer

解决方案


您看到的错误来自error.json().then...

error 参数没有 json() 方法,也不是 promise:它是一个 Error 对象。fetch API 仅通过错误案例报告网络错误——例如无法解析名称、没有可用的网络、超时等。

相反,这样做

.catch(error => console.log(error))

或者

.catch(error => {
   // handle error somehow 
   console.log(error.message));
})

fetch API 将所有响应,包括非 2xx 代码的响应,传递给正常的响应处理程序。这样做的问题:

.then(response => response.json())

是它假设每个响应都有一个 json 正文。这就是您将在简单示例中看到的内容,但并不可靠。相反,您可能想要执行以下操作:

.then(response => {

   // handle specific codes
   if (response.status == 500} {
      throw Error("server error!");
   }

   // or check for non-2xx status
   if (!response.ok) {
      throw Error("Problem - " + response.statusText);
   }

   return response;
})
.then (response => response.json())
.then (json => {
   // do stuff with json payload
)}

推荐阅读