ssmtp_wrapper.php

  1. #!/usr/local/bin/php
  2. <?php
  3.  
  4. // Set up the default config values.
  5. $defaults = array(
  6. 'message_path' => '/var/log/sendmail_php.log',
  7. 'error_path' => '/var/log/sendmail_php.error',
  8. 'parse' => FALSE,
  9. 'ignore_dots' => FALSE,
  10. );
  11.  
  12. // Allow the config file to overwrite the defaults.
  13. if (file_exists($config_path = '/usr/local/etc/sendmail.conf.php')) {
  14. require_once($config_path);
  15. $options = array_merge($defaults, $config);
  16. } else {
  17. $options = $defaults;
  18. }
  19.  
  20. define('MESSAGE_PATH', $options['message_path']);
  21. define('ERROR_PATH', $options['error_path']);
  22.  
  23. // Helper function for logging
  24. function log_message($message, $message_type = 'message') {
  25. static $message_log_file;
  26. if ($message_log_file === NULL)
  27. $message_log_file = fopen(MESSAGE_PATH, 'a');
  28.  
  29. static $error_log_file;
  30. if ($error_log_file === NULL)
  31. $error_log_file = fopen(ERROR_PATH, 'a');
  32.  
  33. if ($message_type == 'message')
  34. fwrite($message_log_file, date('[d/m/Y H:i:s] ').$message."\n");
  35. else
  36. fwrite($error_log_file, date('[d/m/Y H:i:s] ').$message."\n");
  37. }
  38.  
  39. // Initialise these to false so we know if they got set.
  40. $from = $to = FALSE;
  41.  
  42. // Scan the command-line arguments.
  43. foreach ($_SERVER['argv'] as $index => $argv) {
  44. if ((bool) $argv AND $argv[0] == '-') {
  45. switch ($argv[1]) {
  46. case 'f':
  47. $from = substr($argv, 2);
  48. break;
  49. case 't':
  50. $options['parse'] = TRUE;
  51. break;
  52. case 'i':
  53. $options['ignore_dots'] = TRUE;
  54. break;
  55. case 'o':
  56. if ($argv[2] == 'i')
  57. $options['ignore_dots'] = TRUE;
  58. break;
  59. }
  60. } else {
  61. $to = $argv; // Always assign $to so it's the last non-hyphenated param.
  62. }
  63. log_message("Index: $index, Arg: $argv");
  64. }
  65.  
  66. // Check that valid options were passed.
  67. if (! (bool) $to AND ! (bool) $options['parse']) {
  68. log_message($msg = 'Error: Please specify a to address on the command line, or use -t', 'error');
  69. echo $msg, "\n";
  70. exit(255);
  71. }
  72.  
  73. // More valid checks.
  74. if (! (bool) $options['ignore_dots']) {
  75. log_message($msg = 'This wrapper only supports operation in -i mode (ignore single dots on a line).', 'error');
  76. echo $msg, "\n";
  77. exit(255);
  78. }
  79.  
  80. // Read in the message from stdin.
  81. $stdin = '';
  82. while ((bool) ($buffer = fread(STDIN, 1024)))
  83. $stdin .= $buffer;
  84.  
  85. // Log the contents of stdin.
  86. log_message("STDIN: $stdin");
  87.  
  88. // Should we try to parse the "to" and "from" parts of our message?
  89. if ($options['parse'] === TRUE) {
  90. $lines = explode("\n", $stdin);
  91.  
  92. foreach ($lines as $line) {
  93. if (substr($line, 0, 4) == 'To: ') {
  94. $temp_to = substr($line, 4);
  95. if ((bool) $temp_to)
  96. $to = $temp_to;
  97. } elseif (substr($line, 0, 6) == 'From: ') {
  98. $temp_from = substr($line, 6);
  99. if ((bool) $temp_from)
  100. $from = $temp_from;
  101. }
  102. }
  103.  
  104. log_message("Parsed \$to: $to, \$from: $from");
  105. }
  106.  
  107. // Ensure we don't have bad chars.
  108. $to = escapeshellarg($to);
  109. $from = escapeshellarg($from);
  110.  
  111. // Now try to pass it to sSMTP.
  112. $descriptor_spec = array(
  113. 0 => array('pipe', 'r'), // Child process will read; We shall write!
  114. 1 => array('pipe', 'w'), // Backwards, eh? Check the PHP docs.
  115. 2 => array('file', ERROR_PATH, 'a'),
  116. );
  117.  
  118. $command = '/usr/sbin/sendmail -i -f'.$from.' '.$to;
  119. log_message("\$command: $command");
  120.  
  121. $sendmail = proc_open($command, $descriptor_spec, $pipes);
  122.  
  123. if (is_resource($sendmail)) {
  124. $sendmail_stdin = $pipes[0];
  125. $sendmail_stdout = $pipes[1];
  126.  
  127. fwrite($sendmail_stdin, $stdin);
  128. fclose($sendmail_stdin);
  129.  
  130. $result = stream_get_contents($sendmail_stdout);
  131. fclose($sendmail_stdout);
  132.  
  133. $return_value = proc_close($sendmail);
  134. } else {
  135. log_message('Unable to execute!', 'error');
  136. $return_value = 255;
  137. }
  138.  
  139. exit($return_value);
  140.