无法通过REST API发送电子邮件

时间:2021-01-01 作者:drake035

我正在尝试使用发送电子邮件wp_mail() 通过REST 自定义路线,但它在某个地方失败了。

编辑:我找到了,在;sendContactMail()”;,$request->get_json_params(); 不返回任何内容,但$request 包含我的所有表单信息。那么,提取这些信息的正确方法是什么?

// custom route callback function
function sendContactMail(WP_REST_Request $request) {
  $response = array(
    \'status\' => 304,
    \'message\' => \'There was an error sending the form.\'
  );
  $parameters = $request->get_json_params();
  if (count($_POST) > 0) {
    $parameters = $_POST;
  }
  $siteName = wp_strip_all_tags(trim(get_option(\'blogname\')));
  $contactName = wp_strip_all_tags(trim($parameters[\'contact_name\']));
  $contactEmail = wp_strip_all_tags(trim($parameters[\'contact_email\']));
  $contactMessage = wp_strip_all_tags(trim($parameters[\'contact_message\']));

  if (!empty($contactName) && !empty($contactEmail) && !empty($contactMessage)) {
    $subject = "(New message sent from site $siteName) $contactName <$contactEmail>";
    $body = "<h3>$subject</h3><br/>";
    $body .= "<p><b>Name:</b> $contactName</p>";
    $body .= "<p><b>Email:</b> $contactEmail</p>";
    $body .= "<p><b>Message:</b> $contactMessage</p>";

    if (send_email($contactEmail, $contactName, $body)) {
      $response[\'status\'] = 200;
      $response[\'message\'] = \'Form sent successfully.\';
    }
  }
  return new WP_REST_Response($response);
}

// custom route declaration
add_action(\'rest_api_init\', function () {
  register_rest_route( \'contact/v1\', \'send\', array(
    \'methods\' => [\'POST\',\'PUT\'],
    \'callback\' => \'sendContactMail\'
  ));
});
表单相关内容$request:

["body":protected]=> string(382) "------WebKitFormBoundaryoh45oL7PWjTynEQK Content-Disposition: form-data; name="contact_name" Jack ------WebKitFormBoundaryoh45oL7PWjTynEQK Content-Disposition: form-data; name="contact_email" [email protected] ------WebKitFormBoundaryoh45oL7PWjTynEQK Content-Disposition: form-data; name="contact_message" This is my message. ------WebKitFormBoundaryoh45oL7PWjTynEQK-- "

2 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

您没有包括send_email() 函数,但我查看了原始source (修订版1)的问题send_email() 函数很好,但如果这个答案无助于解决问题,那么将函数代码添加到问题正文中

所以我不知道为什么要将(REST)API端点的(HTTP)方法设置为POST和PUT,即。\'methods\' => [\'POST\',\'PUT\'], 因为我认为POST已经足够了(即。\'methods\' => \'POST\'), 但在我看来,您没有正确地将表单数据发送到API端点。

请注意,当您使用FormData (在JavaScript中)使用PUT方法$request->get_json_params() 还有超全球$_POST 是空的,因此如果必须使用PUT方法,则需要将表单数据作为JSON编码的字符串发送。

其次,无论使用何种(HTTP)方法,如果以JSON的形式发送数据,请确保Content-Type 标题设置为application/json 作为值。

这里有两个使用JavaScript的示例,每个HTTP方法一个,这些示例在WordPress 5.6.0上运行良好:

使用fetch(), FormData 以及POST方法

const formData = new FormData();

formData.append( \'contact_name\', \'John Doe\' );
formData.append( \'contact_email\', \'[email protected]\' );
formData.append( \'contact_message\', \'Just testing\' );

fetch( \'https://example.com/wp-json/contact/v1/send\', {
    method: \'POST\',
    body: formData
} )
    .then( res => res.json() )
    .then( data => console.log( data ) )
    .catch( error => console.log( error ) );

使用fetch(), JSON.stringify() 以及PUT方法

const formData = {
    contact_name: \'John Doe\',
    contact_email: \'[email protected]\',
    contact_message: \'Just testing\'
};

fetch( \'https://example.com/wp-json/contact/v1/send\', {
    method: \'PUT\',
    body: JSON.stringify( formData ),
    headers: {
        \'Content-Type\': \'application/json\'
    }
} )
    .then( res => res.json() )
    .then( data => console.log( data ) )
    .catch( error => console.log( error ) );
所以我希望这有帮助,你不必使用fetch() 甚至JavaScript,但我的回答是,确保您的请求使用proper body/content and content type header.

更新如何访问请求参数请检查Extending the REST API → Adding Custom Endpoints → Arguments 中的节REST API handbook 有关更多详细信息,请参阅以下两种访问参数的最常用方法:

使用$request->get_params() 获取所有参数(URL编码的帖子正文、JSON负载、URL查询字符串等)。因此,在您的情况下:

// Instead of this:
$parameters = $request->get_json_params();
if (count($_POST) > 0) {
  $parameters = $_POST;
}

// You could simply do:
$parameters = $request->get_params();
$request 上述变量。例如。

$contactName    = $request[\'contact_name\'];
$contactEmail   = $request[\'contact_email\'];
$contactMessage = $request[\'contact_message\'];

你测试过你的send_email() 通过直接函数调用(即不通过REST API)实现函数

虽然我不知道你的send_email() 函数,您应该通过传递测试数据来测试该函数,并查看该函数是否实际工作,例如,它是否返回true、false、null、是否存在任何错误/通知等。如果是该函数不工作,那么问题不在于REST API,即即使在主页之类的正常请求上,该函数也不会工作。

因此,请测试您的电子邮件发送功能,确认它收到了所有必要的参数,并且确实正确发送了电子邮件(例如,使用正确的标题,如“发件人”和“内容类型”)。

始终设置permission_callback, 并利用validate_callbacksanitize_callback 基本上是为了验证/清理请求参数,除了send_email() 函数,您的代码的工作方式是注册端点并返回良好的响应。但在添加自定义端点时,您应该记住以下几点:

确保始终设置permission_callback 对于端点,因为如果不设置它,则会发生以下情况(但默认情况下,只有在debugging 在您的站点上启用):

从WordPress5.5开始,如果permission_callback 如果未提供,REST API将发出_doing_it_wrong 注意

将发布的通知样本:

的REST API路由定义contact/v1/send 缺少所需的permission_callback 论点对于打算公开的REST API路由,请使用__return_true 作为权限回调。

第三个参数register_rest_route() 接受名为args 这是端点的参数数组,对于每个参数,可以设置验证回调(validate_callback) 和消毒回调(sanitize_callback), 因此,您应该使用它,而不是在端点的主回调中进行验证/清理。下面是您希望使用这些回调的一个很好的原因:

使用sanitize_callbackvalidate_callback 允许maincallback仅处理请求,并使用WP_REST_Response 班通过使用这两个回调,您将能够安全地假设您的输入是有效的,并且在处理时是安全的。

这是摘自API手册(顺便说一句)的(稍微重新格式化)摘录。

试试我的代码

Note: 我最初用一个虚拟测试了您的代码send_email() 函数,但在这里,我使用wp_mail() 直接在主回调中。

// The code is basically based on yours.

function sendContactMail( WP_REST_Request $request ) {
    $response = array(
        \'status\'  => 304,
        \'message\' => \'There was an error sending the form.\'
    );

    $siteName = wp_strip_all_tags( trim( get_option( \'blogname\' ) ) );
    $contactName = $request[\'contact_name\'];
    $contactEmail = $request[\'contact_email\'];
    $contactMessage = $request[\'contact_message\'];

    $subject = "[$siteName] (testing) New message from $contactName";
//  $body = "<h3>$subject</h3><br/>";
    $body = "<p><b>Name:</b> $contactName</p>";
    $body .= "<p><b>Email:</b> $contactEmail</p>";
    $body .= "<p><b>Message:</b> $contactMessage</p>";

    $to = get_option( \'admin_email\' );
    $headers = array(
        \'Content-Type: text/html; charset=UTF-8\',
        "Reply-To: $contactName <$contactEmail>",
    );

    if ( wp_mail( $to, $subject, $body, $headers ) ) {
        $response[\'status\'] = 200;
        $response[\'message\'] = \'Form sent successfully.\';
        $response[\'test\'] = $body;
    }

    return new WP_REST_Response( $response );
}

add_action( \'rest_api_init\', function () {
    register_rest_route( \'contact/v1\', \'send\', array(
        \'methods\'             => \'POST\',
        \'callback\'            => \'sendContactMail\',
        \'permission_callback\' => \'__return_true\',
        \'args\'                => array(
            \'contact_name\'    => array(
                \'required\'          => true,
                \'validate_callback\' => function ( $value ) {
                    return preg_match( \'/[a-z0-9]{2,}/i\', $value ) ? true :
                        new WP_Error( \'invalid_contact_name\', \'Your custom error.\' );
                },
                \'sanitize_callback\' => \'sanitize_text_field\',
            ),
            \'contact_email\'   => array(
                \'required\'          => true,
                \'validate_callback\' => \'is_email\',
                \'sanitize_callback\' => \'sanitize_email\',
            ),
            \'contact_message\' => array(
                \'required\'          => true,
                \'sanitize_callback\' => \'sanitize_textarea_field\',
            ),
        ),
    ) );
} );

SO网友:Zoltan Febert

我试图模拟您在我的测试环境中所做的操作。

当我这样调用AJAX时,它成功了。

$.ajax({
    type: "PUT", //HTTP VERB
    url: "${this.baseUrl}/wp-json/contact/v1/send", //URL
    dataType: \'json\', //What type of response you expect back from the server
    contentType: \'text/plain\', //What type of data you are trying to send
    data: fromData,
    success: function (response, request) {
        alert(response)
        this.success = true
        this.ApiResponse = respone
    },
    error: function (response, request) {
        alert(response)
        this.success = false
        this.ApiResponse = respone
    }

})
我的回调函数非常简单:

function sendContactMail(WP_REST_Request $request) {
  return \'OK\';
}
一旦在Javascript中得到响应,就可以开始调试回调函数。

相关推荐

如何使用WooCommerce在React.js主题中呈现WP REST-API端点

我正在使用React构建一个电子商务Wordpress/Woocommerce主题。js。我正在使用npm软件包:create-react-wptheme此包直接在索引内部呈现react应用程序。wordpress主题的php。我不确定如何访问react中的wordpress api端点。js组件。我已经使用jsx为站点创建了模板,需要访问api端点来呈现动态内容。我可以使用对外部api的http请求访问这些点,但我需要能够访问react wp主题内的完整api。据我所知,我需要使用主干。js api客户