Search code examples
pythonsubprocessmailx

Mailx won't send through python


I'm rewriting a shell script to python and a part of it includes sending notifications via mailx. I can't seem to get the subprocess right.

result = subprocess.run(["/bin/mailx", "-r", "[email protected]", "-s", "Test", "[email protected]"], check=True)

When I run this on the server the command returns a blank row, "won't complete" and I thought it might be because mailx is waiting for the email body because when I try sending through bash without a body I get sort of the same problem, so I got these tips:

1. result = subprocess.run(["echo", "Testing", "|", /bin/mailx", "-r", "[email protected]", "-s", "Test", "[email protected]"], check=True) and
2. result = subprocess.run(["/bin/mailx", "-r", "[email protected]", "-s", "Test", "[email protected]", b"Testingtesting"], check=True)

When testing 1, it just echoes out everything after echo. When testing 2, I get the blank row again.


Solution

  • Using subprocess.Popen you can do it as below :

    import subprocess
    cmd = """
            echo 'Message Body' | mailx -s 'Message Title' -r [email protected] [email protected] 
          """
    
    result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    output, errors = result.communicate()
    

    Regarding shell=True from documentation

    shell=False disables all shell based features, but does not suffer from this vulnerability; see the Note in the Popen constructor documentation for helpful hints in getting shell=False to work. The use of shell=True is strongly discouraged in cases where the command string is constructed from external input

    In your case, if you are not taking user input to pass it to subprocess.Popen you are safe.