Как использовать os.spawnv для отправки электронной почты с помощью Python? - PullRequest
1 голос
/ 17 июля 2010

Сначала позвольте мне сказать, что я знаю, что лучше использовать модуль подпроцесса, но я редактирую код других людей и пытаюсь внести как можно меньше изменений, в том числе избежать импорта любых новых модулей.Поэтому я хотел бы придерживаться импортированных в настоящее время модулей (os, sys и paths), если это вообще возможно.

Код в настоящее время (в файле с именем postfix-to-mailman.py, что некоторыеиз вас могут быть знакомы с):

if local in ('postmaster', 'abuse', 'mailer-daemon'):
  os.execv("/usr/sbin/sendmail", ("/usr/sbin/sendmail", 'first@place.com'))
  sys.exit(0)

Это прекрасно работает (хотя я думаю, что sys.exit (0) никогда не будет вызываться и, следовательно, будет ненужным).

Я верю в этозаменяет текущий процесс вызовом / usr / sbin / sendmail, передавая ему аргументы / usr / sbin / sendmail (для argv [0], т.е. самого себя) и 'someaddress@someplace.com', затем передает среду текущего процесса- включая сообщение электронной почты в sys.stdin - дочернему процессу.

Что я хотел бы сделать, это, по сути, отправить еще одну копию сообщения, прежде чем делать это.Я не могу использовать execv снова, потому что тогда выполнение остановится.Поэтому я попробовал следующее:

if local in ('postmaster', 'abuse', 'mailer-daemon'):
  os.spawnv(os.P_WAIT, "/usr/sbin/sendmail", ("/usr/sbin/sendmail", 'other@place.com'))
  os.execv("/usr/sbin/sendmail", ("/usr/sbin/sendmail", 'first@place.com'))
  sys.exit(0)

Однако, хотя он отправляет сообщение на other@place.com, он никогда не отправляет его на first@place.com

Это удивило меняпотому что я думал, что использование spawn запустит дочерний процесс, а затем продолжит выполнение в текущем процессе, когда он вернется (или без ожидания, если используется P_NOWAIT).

Кстати, сначала я попытался os.P_NOWAIT, но сообщениеЯ получил по адресу other@place.com было пусто, поэтому, по крайней мере, когда я использовал P_WAIT, сообщение пришло без изменений.Но его так и не отправили на first@place.com, что является проблемой.

Я бы предпочел не использовать os.system, если бы мог избежать этого, потому что я бы не хотел выходить в среду оболочки, еслиэтого можно избежать (проблемы безопасности, возможная производительность? Я признаю, что я здесь параноик, но если я смогу избежать os.system, я бы все еще хотел).

Единственное, о чем я могу думать, эточто вызов os.spawnv каким-то образом потребляет / очищает содержимое sys.stdin, но это тоже не имеет смысла.Идеи?

Ответы [ 2 ]

1 голос
/ 17 июля 2010

Хотя это может и не иметь смысла, похоже, дело обстоит именно так

import os

os.spawnv(os.P_WAIT,"/usr/bin/wc", ("/usr/bin/wc",))
os.execv("/usr/bin/wc", ("/usr/bin/wc",))

$ cat j.py | python j.py 
       4       6     106
       0       0       0

В этом случае вы можете сделать что-то вроде этого

import os
import sys

buf = sys.stdin.read()
wc = os.popen("usr/sbin/sendmail other@place.com","w")
wc.write(buf)
wc.close()
wc = os.popen("usr/sbin/sendmail first@place.com","w")
wc.write(buf)
wc.close()
sys.exit(0)
0 голосов
/ 08 августа 2010

sys.stdin - это канал, и он не доступен для поиска, поэтому вы никогда не сможете перемотать этот файловый объект, чтобы снова прочитать его содержимое.Чтобы фактически вызвать sendmail (1) дважды, вам нужно сохранить содержимое stdin, желательно во временный файл, но если гарантированно ограничен размер данных, вы можете вместо этого сохранить их в памяти.

Но почемупройти через неприятности?Вам конкретно нужна копия электронной почты, чтобы она была отдельной электронной почтой (и если да, то почему)?Просто добавьте нужного получателя в исходный вызов sendmail (1).Дополнительный получатель не будет отображаться в заголовках писем.

if local in ('postmaster', 'abuse', 'mailer-daemon'):
  os.execv("/usr/sbin/sendmail", ("/usr/sbin/sendmail", 
                                  'first@place.com',
                                  'otheruser@example.com'))
  sys.exit(0)

Oh, и строка sys.exit (0) будет выполнена, если по какой-либо причине os.execv () завершится неудачно.Это произойдет, если / usr / sbin / sendmail не может быть выполнен, например, если исполняемый файл не существует или не является фактически исполняемым.Другими словами, это условие ошибки, о котором вы должны позаботиться.

...