TheFoss
TheFoss

Reputation: 65

Why is my stdin redirection ('<') not working with subprocess.Popen()?

I'm building a script in python, and one part of it needs to send an email with a file as the message body. Instead of sending the contents of the file, the script sends me the next character entered into the terminal e.g. if I enter c as a part of "cat", it doesn't put c into the terminal, but instead sends me an email with "c" as the body.

This is on CentOS 7.6.1810, with Python 3.5.6.

#!/usr/src/Python-3.5.6/python
import subprocess
import sys
import os

subprocess.Popen(["mail", "-s", "Test Subject", "[email protected]", "<", "/path/to/file.txt"], stdout=open('stdout', 'w'), stderr=open('errout', 'w'))

The contents of file.txt should be send as the body, but I just get the first letter of whatever the next thing I type is. "stdout" reads "EOT" after this, and nothing is printed to "errout". To be clear, I'm trying to invoke the command

mail -s "Test Subject" [email protected] < /path/to/file.txt

from inside of the script. This command works as expected outside of the Python script, but inside of it I run into the problem.

Upvotes: 2

Views: 225

Answers (1)

Michael Jaros
Michael Jaros

Reputation: 4681

subprocess.Popen() executes your new process directly by default. So your code passes some additional arguments < and /path/to/file.txt to the mail executable, which will not yield the expected result.

Redirections like < on unix systems are handled by the shell, not by each individual executable. That's why you want subprocess.Popen() to run your mail command with all the arguments mail as well as the redirection < /path/to/file.txt in a shell instead.

You can do this with the shell=True parameter:

subprocess.Popen(["mail", "-s", "Test Subject", "[email protected]", "<", "/path/to/file.txt"], stdout=open('stdout', 'w'), stderr=open('errout', 'w'), shell=True)

Note that the shell is probably not necessary – you could have Popen open the file and connect mail's stdin to that descriptor, see anishsane's comment below.

Using a shell should be avoided especially if user data is being passed to the child process, as it would need to be sanitized properly to prevent command injection attacks.

See the Python 3 docs on subprocess.Popen.

Upvotes: 3

Related Questions