Hi Wietse, Thanks for your guidance so far.
I'm trying to use the postfix sendmail command line - and have this working (code is still rough). However, I'm now trying to get any output from the command. To simulate an error, I've intentionally added an invalid -N option - which in my manual testing outputs an error about invalid option. Below is my c code - I can't get the error back in my buffer. Can you have a look at let me know if there's anything obvious I'm doing. thanks Kent. ------------------------------------------------------------------------------------------------------ int sendMail ( std::string from, std::string to, std::string message ) { int ret_code = -1; // /usr/sbin/sendmail.postfix -f 'from@email.address' -N 'success, delay, failure' 'to@email.address' < tmp const char * exec_path = prefs_PostfixUnixPath().c_str(); // /usr/sbin/sendmail.postfix std::string _f; _f.assign("-f "); _f.append( from ); // -f email@address.domain char * child_args[] = {(char *)"-N 'success,delay,failure,invalid'", (char *)_f.c_str(), (char *)to.c_str(), NULL}; int pid; int pc[2]; /* Parent to child pipe */ int cp[2]; /* Child to parent pipe */ char ch; /* Make pipes */ if( pipe(pc) < 0) { log_write("Can't make pipe: pc"); return -1; } if( pipe(cp) < 0) { log_write("Can't make pipe: cp"); return -1; } // The 'SIGCHLD' signal is triggered when the child fork completes - we want to ignore this. signal(SIGCHLD,SIG_IGN); // ignore 'SIGCHLD' signal /* Create a child to run command. */ switch( pid = fork() ) { case -1: log_write("Error: Can't fork"); return -1; case 0: // === Child === close(1); // Close current stdout. dup2( cp[1], 1 ); // Make stdout go to write end of pipe. close(2); dup2( cp[1], 2 ); // Make stderr go to write end of pipe. close(0); // Close current stdin. dup( pc[0] ); // Make stdin come from read end of pipe. close( pc[1] ); // Close what we don't need. close( cp[0] ); printf("Execute: %s\n", exec_path ); execve( exec_path, child_args, NULL); printf("Error: execve failed"); // this will only occur if 'execve' had an error. exit(1); default: // === Parent === // Close what we don't need. // the 'pipe' buffer size can vary - let's write in 1Kb chunks. if 'out' == 0, buffer is full - wait and write again. int out = write( pc[1], message.c_str(), message.length() ); // write the message to postfix... (this is the whole from:, To:, Subject, Body, etc.) close(pc[1]); // close once written close(cp[1]); int status = 0; char buffer[1024]; // Space to store the response - is 1Kb enough ??? int L = 0; do { waitpid(pid, &status, 0); printf("PID Status: %d\n", status ); printf("\nOutput from child:\n"); while( read(cp[0], &ch, 1) == 1) // read the reply (if any) (how do we get the errors ???) { if( L < 1022 ) buffer[L++] = ch; } buffer[L] = 0; } while ( !WIFEXITED(status) ); printf("Result: %s\n", buffer); ret_code = 1; // need to check if successful or not and return true / false appropriately. break; } return ret_code; } > On 3/06/2017, at 1:32 AM, Wietse Venema <wie...@porcupine.org> wrote: > > Kent: >> Hi Wietse, >> >> Okay - I think I've worked out the answer to my second question if I use the >> sendmail command line, with the -N option. >> >>> /usr/sbin/sendmail.postfix -f t...@dev.kamar.kiwi.nz -N 'success, delay, >>> failure' k...@kamar.nz < tmp >> >> Reading through documentation / mailing lists, it looks like this >> has to be requested per e-mail when using the sendmail command. >> >> Is there anything I can set in the 'main.cf' file to change the >> default 'delay,failure' to be 'success,delay,failure' ? > > You can change your sendmail command line. > > You can also specify the notification requirements in SMTP, as > defined in RFC 3461. > > Wietse