Answers.Body: <p>Solved it (finally).</p>
  
  <p>First part of the problem (the 302 redirect) was this missing configuration in the ajax call:</p>
  
  <pre class="lang-js prettyprint-override"><code>$.post({
    // ...
    dataType: 'json',
    // ...
  };
  </code></pre>
  
  <p>It tells the server what you expect to get back from it.</p>
  
  <p>Now this was fine, but I ran into a second issue. The xhr request stalled in Safari. When that happend and I reloaded the page (causing the request to finally stop), the email was sent anyways. The reason:</p>
  
  <p>Safari seems to have an issue with this:</p>
  
  <pre class="lang-js prettyprint-override"><code>const formData = new FormData(formElement);
  </code></pre>
  
  <p>I found a hint here <a href="https://stackoverflow.com/a/8797289/2342963">https://stackoverflow.com/a/8797289/2342963</a> that fixes the issue: appending the data manually to the <code>FormData</code> instance instead of passing the form element to the constructor.</p>
  
  <p>So this is the working code:</p>
  
  <pre class="lang-js prettyprint-override"><code>const formData = new FormData();
  
  $.each($('input, textarea, select'), function(i, element) {
      if (element.files) {
        $.each(element.files, function(i, file) {
          formData.append(element.name, file);
        });
      } else {
        formData.append(element.name, element.value);
      }
  });
  
  $.post({
      url: '/',
      data: formData,
      type: 'POST',
      cache: false,
      contentType: false,
      processData: false,
      dataType: 'json',
  
      success: response =&gt; {
          if (response.success) {
          // Show success
          } else {
          // Show error
          }
      },
      error: () =&gt; {
          // Show error
      }
  });
  </code></pre>
  
  <p>Turns out, it wasn’t a Craft issue after all ¯_(ツ)_/¯</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-04T13:19:24.300Z
Answers.LastActivityDate: 2018-08-04T13:19:24.300Z
Answers.UserDisplayName: medoingthings
Answers.Body: <p>My guess would be this check is failing: <a href="https://github.com/craftcms/contact-form/blob/v2/src/controllers/SendController.php#L60-L62" rel="nofollow noreferrer">https://github.com/craftcms/contact-form/blob/v2/src/controllers/SendController.php#L60-L62</a></p>
  
  <pre><code>if ($request-&gt;getAcceptsJson()) {
      return $this-&gt;asJson(['errors' =&gt; $submission-&gt;getErrors()]);
  }
  </code></pre>
  
  <p>So it falls through to this redirect because Craft thinks it's a non-AJAX POST: <a href="https://github.com/craftcms/contact-form/blob/v2/src/controllers/SendController.php#L77" rel="nofollow noreferrer">https://github.com/craftcms/contact-form/blob/v2/src/controllers/SendController.php#L77</a></p>
  
  <p>Setting your <code>contentType</code> to <code>application/json</code> instead of <code>false</code> should resolve it.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-07-27T08:11:33.497Z
Answers.Text: Unfortunately this hasn’t done the trick, yet. Now I get a `400 Bad Request`. These are the headers: https://ibb.co/fS3R68. The response says `<pre>Bad Request: Es ist nicht möglich, Ihre Dateneingabe zu prüfen.</pre>` (It’s not possible to verify your data input). Any ideas?
Answers.UserDisplayName: medoingthings
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-07-27T14:03:53.823Z
Answers.Text: Probably just need to pass CSRF data in? https://craftcms.com/support/csrf-protection#updating-your-javascript (Craft 3 syntax: https://craftcms.stackexchange.com/a/26726/57)
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-07-27T15:03:55.310Z
Answers.Text: I figured out that when I add `dataType: 'json'` to the jQuery.post call, the `302` error goes away. But I still need to set contentType: false. The csrf token is already part of the request (https://ibb.co/cmLw68) – even if I disabled csrf, it wouldn’t work. With `contentType: false` the form works in Chrome, but for some reason not in Safari. It looks like Safari doesn’t get a response and is pending the whole time. In both cases (with contentType set and without).
Answers.UserDisplayName: medoingthings
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-07-26T18:03:54.547Z
Answers.LastActivityDate: 2018-07-26T18:03:54.547Z
Answers.UserDisplayName: Brad Bell
Body: <p>I’m using the Contact Form plugin to submit a form that can also upload files via Ajax. The problem ist that instead of a success (<code>200</code>) I get a status code of <code>302</code>. But I receive the resulting mail properly.</p>
  
  <p>Everything worked fine when I hadn’t set everything up for the file upload. I serialized the form data, expected json, success (<code>200</code>).</p>
  
  <pre><code>...
  dataType: 'json',
  data: $(this).serialize(),
  ...
  </code></pre>
  
  <p>But when I switched to this to enable receiving files, things went south (<code>302</code>):</p>
  
  <pre><code>const formData = new FormData(this.form);
  
  $.post({
      url: '/index.php',
      data: formData,
      type: 'POST',
      cache: false,
      contentType: false,
      processData: false,
  
      success: response =&gt; {
          if (response.success) {
              this.showSuccess();
          } else {
              this.showError();
          }
      },
      error: (xhr) =&gt; {
          // FIXME: This is a workaround because for some reason Craft returns a 302, even though everything works
          //        fine. See stackoverflow question here and fix if there is a solution.
          if (xhr.status === 302) {
          this.showSuccess();
          } else {
          this.showError();
          }
      }
  });
  </code></pre>
  
  <p>I’m on Craft 3.0.15 and set up SMTP in Settings -> EMail. I tried it locally (using MAMP) and on my hosted server. Both give me the <code>302</code>.</p>
  
  <p>Any hint would be much appreciated. </p>
  
  <p>Cheers,
  Mark</p>
  
Tags: <craft3><plugin-contactform>
Title: Contact Form sent via Ajax with file upload returns 302 instead of 200 status code
ThreadText: # Contact Form sent via Ajax with file upload returns 302 instead of 200 status code
  
  (Asked by: username_0 on 2018-07-26)
  
  I’m using the Contact Form plugin to submit a form that can also upload files via Ajax. The problem ist that instead of a success (`200`) I get a status code of `302`. But I receive the resulting mail properly.
  
  Everything worked fine when I hadn’t set everything up for the file upload. I serialized the form data, expected json, success (`200`).
  
  ```
  ...
  dataType: 'json',
  data: $(this).serialize(),
  ...
  
  ```
  
  But when I switched to this to enable receiving files, things went south (`302`):
  
  ```
  const formData = new FormData(this.form);
  
  $.post({
      url: '/index.php',
      data: formData,
      type: 'POST',
      cache: false,
      contentType: false,
      processData: false,
  
      success: response => {
          if (response.success) {
              this.showSuccess();
          } else {
              this.showError();
          }
      },
      error: (xhr) => {
          // FIXME: This is a workaround because for some reason Craft returns a 302, even though everything works
          //        fine. See stackoverflow question here and fix if there is a solution.
          if (xhr.status === 302) {
          this.showSuccess();
          } else {
          this.showError();
          }
      }
  });
  
  ```
  
  I’m on Craft 3.0.15 and set up SMTP in Settings -> EMail. I tried it locally (using MAMP) and on my hosted server. Both give me the `302`.
  
  Any hint would be much appreciated.
  
  Cheers,
  Mark
  
  **Tags:** craft3, plugin-contactform
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_0 on 2018-08-04. Score: 1 | Accepted answer
  
  Solved it (finally).
  
  First part of the problem (the 302 redirect) was this missing configuration in the ajax call:
  
  ```js
  $.post({
    // ...
    dataType: 'json',
    // ...
  };
  
  ```
  
  It tells the server what you expect to get back from it.
  
  Now this was fine, but I ran into a second issue. The xhr request stalled in Safari. When that happend and I reloaded the page (causing the request to finally stop), the email was sent anyways. The reason:
  
  Safari seems to have an issue with this:
  
  ```js
  const formData = new FormData(formElement);
  
  ```
  
  I found a hint here <https://stackoverflow.com/a/8797289/2342963> that fixes the issue: appending the data manually to the `FormData` instance instead of passing the form element to the constructor.
  
  So this is the working code:
  
  ```js
  const formData = new FormData();
  
  $.each($('input, textarea, select'), function(i, element) {
      if (element.files) {
        $.each(element.files, function(i, file) {
          formData.append(element.name, file);
        });
      } else {
        formData.append(element.name, element.value);
      }
  });
  
  $.post({
      url: '/',
      data: formData,
      type: 'POST',
      cache: false,
      contentType: false,
      processData: false,
      dataType: 'json',
  
      success: response => {
          if (response.success) {
          // Show success
          } else {
          // Show error
          }
      },
      error: () => {
          // Show error
      }
  });
  
  ```
  
  Turns out, it wasn’t a Craft issue after all ¯\_(ツ)\_/¯
  
  
  ---
  
  ### Answer by username_1 on 2018-07-26. Score: 0
  
  My guess would be this check is failing: <https://github.com/craftcms/contact-form/blob/v2/src/controllers/SendController.php#L60-L62>
  
  ```
  if ($request->getAcceptsJson()) {
      return $this->asJson(['errors' => $submission->getErrors()]);
  }
  
  ```
  
  So it falls through to this redirect because Craft thinks it's a non-AJAX POST: <https://github.com/craftcms/contact-form/blob/v2/src/controllers/SendController.php#L77>
  
  Setting your `contentType` to `application/json` instead of `false` should resolve it.
  
  > **Comments:**
  > **username_0**: Unfortunately this hasn’t done the trick, yet. Now I get a `400 Bad Request`. These are the headers: https://ibb.co/fS3R68. The response says `<pre>Bad Request: Es ist nicht möglich, Ihre Dateneingabe zu prüfen.</pre>` (It’s not possible to verify your data input). Any ideas?  
  > **username_1**: Probably just need to pass CSRF data in? https://craftcms.com/support/csrf-protection#updating-your-javascript (Craft 3 syntax: https://craftcms.stackexchange.com/a/26726/57)  
  > **username_0**: I figured out that when I add `dataType: 'json'` to the jQuery.post call, the `302` error goes away. But I still need to set contentType: false. The csrf token is already part of the request (https://ibb.co/cmLw68) – even if I disabled csrf, it wouldn’t work. With `contentType: false` the form works in Chrome, but for some reason not in Safari. It looks like Safari doesn’t get a response and is pending the whole time. In both cases (with contentType set and without).  
  
  ---
  
  