3

I'm getting an error when I try to send an email matching the criteria to pipe the emails to my php script. The error is:

pipe to |/home/**********/**********/script.php
  generated by f1c8f287-02ea81a3-11a218b30839@**********.com

The following text was generated during the delivery attempt:

------ pipe to |/home/**********/**********/script.php
     generated by f1c8f287-02ea81a3-11a218b30839@*********.com ------

Error in argument 1, char 3: option not found 
Usage: php-cgi [-q] [-h] [-s] [-v] [-i] [-f <file>]
     php-cgi <file> [args...]
-a               Run interactively
-b <address:port>|<port> Bind Path for external FASTCGI Server mode
-C               Do not chdir to the script's directory
-c <path>|<file> Look for php.ini file in this directory
-n               No php.ini file will be used
-d foo[=bar]     Define INI entry foo with value 'bar'
-e               Generate extended information for debugger/profiler
-f <file>        Parse <file>.  Implies `-q'
-h               This help
-i               PHP information
-l               Syntax check only (lint)
-m               Show compiled in modules
-q               Quiet-mode.  Suppress HTTP Header output.
-s               Display colour syntax highlighted source.
-v               Version number
-w               Display source with stripped comments and whitespace.
-z <file>        Load Zend extension <file>.
-T <count>       Measure execution time of script repeated <count> times.


Reporting-MTA: dns; srv28.hostserv.com

Action: failed
Final-Recipient: rfc822;|/home/**********/**********/script.php
Status: 5.0.0

I wish not to make this question unnecessarily verbose...

Here's my full script.php code just in case:

#!/usr/bin/php -q
<?php

// config
$dbHost = "********";
$dbUser = "********";
$dbPass = "********";
$dbName = "********";

//$conn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName) or die(mysqli_error($conn));
$notify= 'admin@*********.com'; // an email address required in case of errors

function mailRead($iKlimit = "") 
    { 
        // Purpose: 
        //   Reads piped mail from STDIN 
        // 
        // Arguments: 
        //   $iKlimit (integer, optional): specifies after how many kilobytes reading of mail should stop 
        //   Defaults to 1024k if no value is specified 
        //     A value of -1 will cause reading to continue until the entire message has been read 
        // 
        // Return value: 
        //   A string containing the entire email, headers, body and all. 
         
        // Variable perparation         
            // Set default limit of 1024k if no limit has been specified 
            if ($iKlimit == "") { 
                $iKlimit = 1024; 
            } 
             
            // Error strings 
            $sErrorSTDINFail = "Error - failed to read mail from STDIN!"; 
         
        // Attempt to connect to STDIN 
        $fp = fopen("php://stdin", "r"); 
         
        // Failed to connect to STDIN? (shouldn't really happen) 
        if (!$fp) { 
            echo $sErrorSTDINFail; 
            exit(); 
        } 
         
        // Create empty string for storing message 
        $sEmail = ""; 
         
        // Read message up until limit (if any) 
        if ($iKlimit == -1) { 
            while (!feof($fp)) { 
                $sEmail .= fread($fp, 1024); 
            }                     
        } else { 
            while (!feof($fp) && $i_limit < $iKlimit) { 
                $sEmail .= fread($fp, 1024); 
                $i_limit++; 
            }         
        } 
         
        // Close connection to STDIN 
        fclose($fp); 
         
        // Return message 
        return $sEmail; 
    }

// call function
$email = mailRead();

// handle email
$lines = explode("\n", $email);

// empty vars
$from = "";
$subject = "";
$headers = "";
$message = "";
$splittingheaders = true;

for ($i=0; $i < count($lines); $i++) {
    if ($splittingheaders) {
        // this is a header
        $headers .= $lines[$i]."\n";

        // look out for special headers
        if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) {
            $subject = $matches[1];
        }
        if (preg_match("/^From: (.*)/", $lines[$i], $matches)) {
            $from = $matches[1];
        }
        if (preg_match("/^To: (.*)/", $lines[$i], $matches)) {
            $to = $matches[1];
        }
    } else {
        // not a header, but message
        $message .= $lines[$i]."\n";
    }

    if (trim($lines[$i])=="") {
        // empty line, header section has ended
        $splittingheaders = false;
    }
}

if ($conn = mysqli_connect($dbHost,$dbUser,$dbPass)) {
  if(!mysqli_select_db($dbName,$conn))
    mail($email,'Email Logger Error',"There was an error selecting the email logger database.\n\n".mysqli_error());
  $from    = mysqli_real_escape_string($from);
  $to    = mysqli_real_escape_string($to);
  $subject = mysqli_real_escape_string($subject);
  $headers = mysqli_real_escape_string($headers);
  $message = mysqli_real_escape_string($message);
  $email   = mysqli_real_escape_string($email);
  $result = mysqli_query("INSERT INTO email_log (`to`,`from`,`subject`,`headers`,`message`,`source`) VALUES('$to','$from','$subject','$headers','$message','$email')");
  if (mysqli_affected_rows() == 0)
    mail($notify,'Email Logger Error',"There was an error inserting into the email logger database.\n\n".mysqli_error());
} else {
  mail($notify,'Email Logger Error',"There was an error connecting the email logger database.\n\n".mysqli_error());
}
?>

I followed these rules and they are in check:

  1. File permissions (and directory of it) are set to 0755

  2. Uploaded via cPanel. The file should be in ascii format and not binary (I don't know how to check tho)

  3. No whitespaces/newlines before/after the php tags and hashbang

I've looked at and tried the answers to these questions which are similar but have not resolved the error I got:

PHP email piping error

Email Piping - working but emails return errors

Among others from the cPanel forum and other resources.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ArabianMaiden
  • 505
  • 7
  • 24
  • 1
    "Argument 1, character 3" sounds like garbage after the `-q` option. Did you use a Windows editor to save this file? (Text upload should ideally have fixed it but not using Windows, or at least saving with Unix line-ending conventions, is probably a better solution.) – tripleee Jan 02 '19 at 00:21
  • @tripleee I'm using Windows and Sublime Text 3 for editing. I uploaded it through cPanel. What should I do to upload it in the correct format? – ArabianMaiden Jan 02 '19 at 00:24
  • My suggestion would be to save with Unix line endings locally, and not then worry too much about how to transfer the file correctly (or abandon Windows entirely if you can). I am not familiar with Sublime Text 3 but this seems to cover it: https://stackoverflow.com/questions/39680585/how-do-configure-sublime-to-always-convert-to-unix-line-endings-on-save – tripleee Jan 02 '19 at 10:09
  • @tripleee What a breakthrough! That was the issue. Sublime Text 3 saves the line endings for Windows by default it seems. I changed that and the email is actually parsing. Thank you for that. – ArabianMaiden Jan 02 '19 at 11:22

1 Answers1

3

The solution to this issue was to make sure that the line endings for the script are saved for Unix. If you're using Windows, check your text editor's default setting for saving line endings. The related question proved useful in handling this, How do configure sublime to always convert to unix line endings on save?

For Sublime Text 3 I simply changed the line ending format (Menu > View > Line Endings > Unix) and saved the file. The e-mail parser works without errors now.

Credit goes to Triplee for this excellent solution. For future readers, the general troubleshoot forums mention extraneous carriage returns but not anything about formatting the text into Unix line endings in case you're a Windows user.

ArabianMaiden
  • 505
  • 7
  • 24
  • 1
    "Extraneous carriage returns" is exactly the same issue. DOS text editors natively put carriage returns before line feeds, whereas typical Unix (and the rest of the civilized world) expects line feeds only – tripleee Jan 02 '19 at 11:42
  • Edited the answer to include "Windows users". This wouldn't have been an issue if I was using Linux in the first place, right? – ArabianMaiden Jan 02 '19 at 11:52
  • There's a saying about how you can't make things foolproof because they will invent a better fool but yeah, it's unlikely this would affect anyone who is using Linux. – tripleee Jan 02 '19 at 11:55
  • @ArabianMaiden, do you know how to solve this one. "Error in argument 3, char 2: no argument for option t" – vishal Jan 25 '22 at 05:12
  • @vishal most likely a type in the config. Post ur question or code and I can check it out – ArabianMaiden Feb 01 '22 at 16:32
  • @ArabianMaiden, my site build in php. I passed this argument "$ php -S localhost:8002 -t " in cmd and got this error " Error in argument 3, char 2: no argument for option t " – vishal Feb 02 '22 at 04:58