0

I'm running the mailx command from inside a Python program. The program is running on a server in AWS, and I'm using their Simple Email Service to send emails.

Up until now, I've been hardcoding the SES username and password for the SMTP server directly into the Python script. I'm now switching to grabbing the username and password with an API call to AWS to increase security.

How can I rework the Python program to call the mailx command using the username and password stored in the variables SESUsername and SESPassword? The mailx command uses the smtp-auth-user and smtp-auth-password arguments.

Here are the two Python lines:

command = "mailx -v -s \"Subject\" -S ssl-verify=ignore  -S smtp-auth=login -S smtp=smtps://email-smtp.us-west-2.amazonaws.com:465 -S from=\"A Person<email@domain.com>\"  -S replyto=\"Another Person<email2@domain2.com>\" -S smtp-auth-user=XXXXX -S smtp-auth-password=XXXXX -S nss-config-dir=\"/etc/pki/nssdb/\" person3@domain3.com"

subprocess.Popen(command,shell=True)
tripleee
  • 175,061
  • 34
  • 275
  • 318
slantalpha
  • 515
  • 1
  • 6
  • 18

2 Answers2

0

You're building a command string, and you have string arguments in variables, so put the stuff together. I'd use format:

command = "...{}...{}...".format(SESUsername, SESPassword)

subprocess.Popen(command,shell=True)

This will work as long as the username and password don't contain special characters that throw off the command parsing in Popen. However, Popen does accept a sequence of strings, which makes much more sense in your case. It will greatly improve the readability of your code:

command = ['mailx', '-v', '-s', "Subject",...
           '-S', '-smtp-auth-user='+SESUsername,
           '-S', 'smtp-auth-password='+SESPassword,
           ...]

subprocess.Popen(command,shell=True)
Roland Weber
  • 3,395
  • 12
  • 26
0

You have two mistakes: you want to avoid subprocess.Popen and you want to avoid shell=True. If you have a new enough Python, use subprocess.run():

result = subprocess.run(
    ['mailx', '-v', '-s', 'Subject',
     '-S', 'ssl-verify=ignore', '-S', 'smtp-auth=login',
     '-S', 'smtp=smtps://email-smtp.us-west-2.amazonaws.com:465',
      '-S', 'from=A Person', '-S', 'replyto=Another Person',
       '-S', 'smtp-auth-user={}'.format(user),
       '-S', 'smtp-auth-password={}'.format(pass),
       '-S', 'nss-config-dir=/etc/pki/nssdb/',
       'person3@domain3.com'],
      check=True)

(Notice also how dropping the shell does away with a lot of the pesky shell quoting.)

If your Python is too old to have subpsocess.run, try subprocess.check_call. The low-level Popen is not wrong per se, but it requires quite a lot of plumbing which of course the higher-level functions take care of for you, and which seems to be missing from your code.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • See also https://stackoverflow.com/questions/4256107/running-bash-commands-in-python/51950538#51950538 – tripleee Jun 22 '19 at 06:39