1

I am trying to send a mail via python's subprocess.run methode. Unfortunately, it is not working.

import subprocess

message = "Hello World"

process = subprocess.run(["mail", "-s", "Test, "xyz@xyz.com", "<<<", message], 
                     stdout=subprocess.PIPE, 
                     universal_newlines=True)

print (process.stdout)

I received the following Error:

mail: Cannot parse address <<<' (while expanding<<<'): Malformed email address

mail: Cannot parse address Hello World' (while expandingHello World'): Malformed email address

The command is working in the shell though (Linux Mint > 19.0).

James Brown
  • 36,089
  • 7
  • 43
  • 59
Bahlsen
  • 177
  • 1
  • 9
  • Might be wrong, but shell piping and redirecting doesn't work through pythons subprocess. Perhaps with `shell=True` but highly doubt it. What you might need to do is do `subprocess.run(["/usr/bin/sh", "-c", "mail -s Test xyz@xyz.com ..."])` in order for it to work. Or simply do `handle = subprocess.Popen(mail ...)` and then do `handle.write(message)` and write it as if you were piping it. All this because `subprocess.run != bash` and bash is what makes `<<<` and `|` etc work. – Torxed Jan 05 '20 at 10:11

1 Answers1

1

The <<< syntax is a feature of bash. If you want to use that you need to run your command as an argument of the bash shell:

import subprocess
message = "Hello World"

command = "mail -s Test abc@def.com <<< "+message
process = subprocess.run(
        ["bash","-c",command],
        stdout=subprocess.PIPE,
        universal_newlines=True)

print (process.stdout)

However, using shell expansion on dynamic content can be a security issue. A better way is, to use the input feature of subprocess.run ( python3 only )

import subprocess
message = "Hello World"

command = ["mail", "-s", "Test", "abc@def.com"]
process = subprocess.run(
        command,
        input=message,
        stdout=subprocess.PIPE,
        universal_newlines=True)


print (process.stdout)

See also Python - How do I pass a string into subprocess.Popen (using the stdin argument)?

Michael S
  • 738
  • 1
  • 8
  • 20
  • I have one more question, how can I check if the mail was really sent? For example, by mistake I used "...@....net" instead of "....@....com". At first, it seemed like everything went well, however, later after checking my providers mail inbox, I received a mail stating "could not find mail address. was unable to send mail". Is there any way to prevent this mistake? I already tried to print out process.stderr, but I did not receive any error / info message. Is there any log files? So far I checked /var/log/mail.log but also no error / info message was reported. – Bahlsen Jan 05 '20 at 18:03
  • In general this is not possible because this is a weakness ( or feature) of the smtp mail transport system how it works as of today. When you send mail through 'mail' command or any other mail client, you are delivering your mail to the next mailhost which was configured in your mail client or operating system. That mailhost is temporarily storing the mail and tries to reach the next node to deliver the mail to , and so on. You could scan your inbox for returned messages but that method is also not 100% accurate. – Michael S Jan 05 '20 at 18:16