0

I want to generate Accounts using usernames and random generated passwords. However. I cannot send Mails with multiple line. A minimal code showing my problem is:

import subprocess
import string

username = Test
randomPassword = abcabc
fromAddr='test@example.com'
toAddr='receive@example.com'
subject='Test Mail'
body='Your Username is ' + username + '\n'+'Your Password is' + randomPassword
cmd='echo '+body+' | mail -s '+subject+' -r '+fromAddr+' '+toAddr
send=subprocess.call(cmd,shell=True)

The error is:

mail: cannot send message: process exited with a non-zero status

/var/log/mail.err shows the follwoing

[SERVERNAME] sSMTP[9002]: RCPT TO:<[SUBJECT]@[SERVERNAME]> (Domain does not exist: [SERVERNME])

A suggestion I found was to use

cmd='echo -e ' +body+ [...] 

However this didn't solved the issue.

Any suggestions?

ChrizZ
  • 47
  • 1
  • 7
  • Why aren't you using a Python library for sending mail? – Barmar Jul 15 '19 at 22:14
  • There is a set up mail server which we want to use, so we can just change settings in the the ssmtp config and everything runs without any issues. I would prefer using Linux mail command. However if that isn't possible with that method I could aswell use a python library – ChrizZ Jul 15 '19 at 22:19

2 Answers2

3

You need to put the body and subject in quotes. It's easier if you use an f-string

cmd  = f"echo '{body}' | mail -s '{subject}' -r '{fromAddr}' '{toAddr}'"

Note that you need to ensure that there are no quote characters in any of the parameters -- make sure you don't allow single quote in the password.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I cannot edit it. But after {toAddr} there is a ' missing. So the correct command would be: cmd = f"echo '{body}' | mail -s '{subject}' -r '{fromAddr}' '{toAddr}'" But this solution works like a charm. Thank you. Will mark as correct answer as soon as StackOverflow lets me – ChrizZ Jul 15 '19 at 22:24
  • @ChrizZ You should look at triplee's answer, it's better than this. – Barmar Jul 16 '19 at 02:56
  • You could fix the quoting issue with `shlex` but it gets complex enough that it might still introduce vulnerabilities; and there are other reasons to want to avoid `shell=True` too - see [Actual meaning of `shell=True` in `subprocess`](https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess) – tripleee Jul 16 '19 at 03:17
2

You really want to avoid the various quoting issues with Barmar's answer. If your Python is new enough, you want

send = subprocess.call(
    ['mail', '-s', subject, '-r', fromAddr, toAddr],
    input=body, text=True)

Prior to Python 3.7, you'll want to replace text=True with the older, more unclear alias universal_newlines=True. The input argument was probably introduced in Python 3.3. For idas for how to do something similar in older versions than that, and a more detailed discussion, see Running Bash commands in Python

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • `mail` is a very thin wrapper around `sendmail` (though it has a fair bit of code unrelated to sending a message from the command line) so this is basically equivalent to prepending `f'From: {fromAddr}\nTo: {toAddr}\nSubject: {subject}\n\n'` to the `body` string and piping to `sendmail`. – tripleee Jul 16 '19 at 03:13