Search code examples
phpwordpressemailwp-mail

How to handle wordpress forms via php?


I have a contact form on my wordpress website and I am trying to send an email accordingly. However neither an email nor a response is being send to the client. Even without the condition in the beginning it's not working. I don't get any server logs regarding this issue.

What am I doing wrong?

add_action('wp_ajax_nopriv_mail_before_submit', 'mail_before_submit');
add_action('wp_ajax_mail_before_submit', 'mail_before_submit');
function mail_before_submit() {
    $jsonRequest = json_decode(file_get_contents('php://input'), true);
    if (strcmp($jsonRequest['action'], 'contact_form') !== 0) {
        echo 'failure';
        exit(1);
    };

    $sendMail = wp_mail(
        get_option('admin_email'),
        sprintf('Kontaktformular von %1$s', $jsonRequest['name']),
        sprintf(
            'Name: %1$s
Email: %2$s
Telefonnummer: %3$s
Nachricht: %4$s
JSON: %5$s',
            $jsonRequest['name'],
            $jsonRequest['email'],
            $jsonRequest['phone'],
            $jsonRequest['message'],
            json_encode($jsonRequest),
        ),
        sprintf('From: %1$s <"%2$s">', $jsonRequest['name'], $jsonRequest['email']),
    );

    if ($sendMail) {
        echo 'success';
        exit();
    }

    echo 'failure';

    exit();
}

Best regards

EDIT1:

I used https://ddev.readthedocs.io/en/latest/users/debugging-profiling/step-debugging/#visual-studio-code-vs-code-debugging-setup for debugging and found, that the headers argument of the wp_mail funtion is incorrect, so I replaced it with sprintf('From: %1$s', $jsonRequest['email']),.

Now I am receiving the mail, however no response to the client is being sent. Why is that?

EDIT2:

The code above works with the mentioned change in EDIT2, what I didn't know is, that the response in the browsers network tab will be empty, until in JavaScript something like await response.text() has been called.


Solution

  • The whole working PHP part looks like this:

    add_action('wp_ajax_nopriv_mail_before_submit', 'mail_before_submit');
    add_action('wp_ajax_mail_before_submit', 'mail_before_submit');
    function mail_before_submit() {
        $jsonRequest = json_decode(file_get_contents('php://input'), true);
        if (strcmp($jsonRequest['action'], 'contact_form') !== 0) {
            echo 'failure';
            exit(1);
        };
    
        $sendMail = wp_mail(
            get_option('admin_email'),
            sprintf('Kontaktformular von %1$s', $jsonRequest['name']),
            sprintf(
                'Name: %1$s
    Email: %2$s
    Telefonnummer: %3$s
    Nachricht: %4$s',
                $jsonRequest['name'],
                $jsonRequest['email'],
                $jsonRequest['phone'],
                $jsonRequest['message'],
                // json_encode($jsonRequest),
            ),
            sprintf('From: %1$s', $jsonRequest['email']),
        );
    
        if ($sendMail) {
            echo 'success';
            exit();
        }
    
        echo 'failure';
    
        exit();
    }
    

    On the JavaScript side it's important to call await response.text(), otherwise the response won't be visible in the browsers network tab.

    window.addEventListener("load", () => {
      /**
       * @type Array<HTMLFormElement>
       */
      const forms = Array.from(
        document.querySelectorAll(".contact-form")
      );
    
      forms.forEach((form) => {
        form.addEventListener("submit", async (e) => {
          e.preventDefault();
    
          const response = await fetch(
            "/wp-admin/admin-ajax.php?action=mail_before_submit",
            {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                action: "contact_form",
                ...Object.fromEntries(new FormData(form)),
              }),
            }
          );
    
          console.log({ response });
          if (!response.ok) {
            console.error("ERROR");
    
            return;
          }
    
          if ((await response.text()) === "success") {
            form.classList.add("success");
          }
        });
      });
    });