So I'm developing this plugin to take the input of a form, puts it in a .CSV document then send the .CSV document over via email. And all this works fine. However, on pressing submit, a rouge file downloads named 'download'. When this file is opened up in my text editor, it seems to just be the complied code of the page. It's odd. Here's the source code to my plugin:


Plugin Name: Form To CSV
Plugin URI: N/A
Description: A plugin to put login credentials in CSV and send via email, built originally for Relo Solutions Group.
Version: 1
Author: Joseph Roberts
Author URI: http://josephrobertsdesigns.com
License: GPL2

// Make sure we don't expose any info if called directly
if ( !function_exists( 'add_action' ) ) {
    echo 'Hi there!  I\'m just a plugin, not much I can do when called directly.';

define( 'FORM_TO_CSV__VERSION', '1' );
define( 'FORM_TO_CSV__MINIMUM_WP_VERSION', '4.7.2' );
define( 'FORM_TO_CSV__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'FORM_TO_CSV__DELETE_LIMIT', 100000 );

register_activation_hook( __FILE__, array( 'Form_To_CSV', 'plugin_activation' ) );
register_deactivation_hook( __FILE__, array( 'Form_To_CSV', 'plugin_deactivation' ) );

require_once( FORM_TO_CSV__PLUGIN_DIR . 'form-to-csv_run.php' );

And also the form-to-csv_run.php file, which is where I believe the issue resides

function formToCsv_shortcode()  {
    /* ---------- LOGIN-FORM ---------- */
    #login-form {
      width: 300px;
      margin:100px auto;

    #login-form h3 {
      background-color: #282830;
      border-radius: 5px 5px 0 0;
      color: #fff;
      font-size: 14px;
      padding: 20px;
      text-align: center;
      text-transform: uppercase;

    #login-form fieldset {
      background: inherit;
      border-radius: 0 0 5px 5px;
      padding: 20px;
      position: relative;

    #login-form fieldset:before {
      background-color: inherit;
      content: "";
      height: 8px;
      left: 50%;
      margin: -4px 0 0 -4px;
      position: absolute;
      top: 0;
      -webkit-transform: rotate(45deg);
         -moz-transform: rotate(45deg);
          -ms-transform: rotate(45deg);
           -o-transform: rotate(45deg);
              transform: rotate(45deg);
      width: 8px;

    #login-form input {
      font-size: 14px;

    #login-form input[type="email"],
    #login-form input[type="password"] {
      border: 1px solid #dcdcdc;
      padding: 12px 10px;
      width: 100%;

    #login-form input[type="email"] {
      border-radius: 3px 3px 0 0;

    #login-form input[type="password"] {
      border-top: none;
      border-radius: 0px 0px 3px 3px;

    #login-form input[type="submit"] {
      background: #1dabb8;
      border-radius: 3px;
      color: #fff;
      float: right;
      font-weight: bold;
      margin-top: 20px;
      padding: 12px 20px;

    #login-form input[type="submit"]:hover {
      background: #198d98;

    #login-form footer {
      font-size: 12px;
      margin-top: 16px;

    .info {
      background: #e5e5e5;
      border-radius: 50%;
      display: inline-block;
      height: 20px;
      line-height: 20px;
      margin: 0 10px 0 0;
      text-align: center;
      width: 20px;

        function debug_to_console( $data ) {

            if ( is_array( $data ) )
                $output = "<script>console.log( 'Debug Objects: " . implode( ',', $data) . "' );</script>";
                $output = "<script>console.log( 'Debug Objects: " . $data . "' );</script>";

            echo $output;

        //collect form data
        $email = $_POST['email'];
        $password = $_POST['password'];

        //check name is set
        if($email ==''){
            $error[] = 'Email is required';
        }elseif($password == ''){
            $error[] = 'Password is required';

        //check for a valid email address
        if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
            $error[] = 'Please enter a valid email address';

        //if no errors carry on

            # set the file name and create CSV file
            $FileName = "formdata-".date("d-m-y-h:i:s").".csv";
            header('Content-Type: application/csv'); 

            // open the file "demosaved.csv" for writing
            $file = fopen(FORM_TO_CSV__PLUGIN_DIR . 'CSVs/' . $FileName, 'w');

            // save the column headers
            fputcsv($file, array('Email', 'Password'));

            // Sample data. This can be fetched from mysql too
            $data = array(
                array($email, $password)

            // save each row of the data
            foreach ($data as $row)
                fputcsv($file, $row);

            // Close the file
            debug_to_console("CSV FILE WAS CREATED.");

            // Mail the file
            $mailto = "[email protected]";
            $subject = "Login Details";

            $content = chunk_split(base64_encode(file_get_contents($file)));

            $uid = md5(uniqid(time()));
            $name = basename($file);
            $header = "From: <" . $email . ">\r\n";
            $header .= "Reply-To: " . $email . "\r\n";

            $header .= "MIME-Version: 1.0\r\n";
            $header .= "Content-Type: multipart/mixed; boundary=\"" . $uid . "\"\r\n\r\n";
            $header .= "This is a multi-part message in MIME format.\r\n";
            $header .= "--" . $uid . "\r\n";

            // You add html "Content-type: text/html; charset=utf-8\n" or for Text "Content-type:text/plain; charset=iso-8859-1\r\n" by I.khan
            $header .= "Content-type:text/html; charset=utf-8\n";
            $header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";

            $header .= "--" . $uid . "\r\n";
            $header .= "Content-Type: application/octet-stream; name=\"" . $FileName . "\"\r\n"; // use different content types here
            $header .= "Content-Transfer-Encoding: base64\r\n";
            $header .= "Content-Disposition: attachment; filename=\"" . $FileName . "\"\r\n\r\n"; // For Attachment
            $header .= $content . "\r\n\r\n";
            $header .= "--" . $uid . "--";
            if (mail($mailto, $subject, "", $header)) {
                echo "<script>alert('Success');</script>"; // or use booleans here
            } else {
                echo "<script>alert('Failed');</script>";

    <div class="container">
      <div id="login-form">
          <form action='' method="post">
            <input name="email" type="email" required value="Email" onBlur="if(this.value=='')this.value='Email'" onFocus="if(this.value=='Email')this.value='' "> <!-- JS because of IE support; better: placeholder="Email" -->
            <input name="password" type="password" required value="Password" onBlur="if(this.value=='')this.value='Password'" onFocus="if(this.value=='Password')this.value='' "> <!-- JS because of IE support; better: placeholder="Password" -->
            <input name="submit" type="submit" value="Login">
            <footer class="clearfix">
              <p><span class="info">?</span><a href="#">Forgot Password</a></p>
      </div> <!-- end login-form -->
add_shortcode('formToCsv', 'formToCsv_shortcode');

Also, screenshots of what it does:

the rouge download

And what that file displays in text editor, I'm 100% sure its just the page im on:

the rouge download's source code

As usual, it's probably just some small mistake somewhere, but I've been banging my head against the wall for a while trying to figure this out. So any help would be greatly appreciated.


I tried removing the 'header' line and changing the 'mail' line to:

wp_mail($mailto, $subject, $header, '', $file);

And it doesn't download a file randomly! And it still sends the email, however now the csv file is not attached. So still stumped unfortunately.

3 Answers 3


To attach a file to the email, you need to specify the Path to it like this:

$attachments = array( WP_CONTENT_DIR . '/uploads/file_to_attach.zip' );
$headers = 'From: Test Name <[email protected]>' . "\r\n";
wp_mail( '[email protected]', 'subject', 'message', $headers, $attachments );

either is a string or an Array (for multiple files), you can see the accepted parameters here wp_email . Not in the header like i can see here:

$header .= "Content-Disposition: attachment; filename=\"" . $FileName . "\"\r\n\r\n"; // For Attachment

form action is set to empty string. I believe this may be part of the problem. Not 100% sure, but hope that helps!

  • Removed it all together, same result unfortunately.
    – J Robz
    Commented Feb 3, 2017 at 21:48

Just a small thing, use wp_mail(); instead of mail();

See what happens then.

Also don't think you need header('Content-Type: application/csv');.

That sets the header of the returned page to a CSV file. CSV files cannot be opened by web pages and instead it downloads the file.

Is the file downloaded a CSV file by any chance?

  • The file does is not a csv file that's downloaded. However on removing the 'header' line and changing the 'mail' line to: wp_mail($mailto, $subject, $header, '', $file); it sends the email, however now nothing is attached. Any idea why?
    – J Robz
    Commented Feb 4, 2017 at 3:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.