如何使用os.spawnv使用Python发送电子邮件副本?

时间:2010-07-17 01:02:18

标签: python process postfix-mta mailman

首先让我说我知道最好使用子进程模块,但我正在编辑其他人的代码,我正在尝试尽可能少地进行更改,其中包括避免导入任何新模块。所以我想尽可能坚持当前导入的模块(os,sys和path)。

代码目前(在你们中的一些人可能熟悉的名为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] ie本身)和'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,如果我可以避免它,因为如果可以避免,我宁愿不去shell环境(安全问题,可能的性能?我承认我在这里偏执,但如果我能避免使用os.system,我仍然愿意。)

我唯一能想到的是对os.spawnv的调用以某种方式消耗/清空sys.stdin的内容,但这也没有意义。想法?

2 个答案:

答案 0 :(得分:1)

虽然这可能没有意义,但事实确实如此

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)

答案 1 :(得分:0)

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)

哦,如果os.execv()由于某种原因失败,将执行sys.exit(0)行。如果无法执行/ usr / sbin / sendmail,则会发生这种情况,例如如果可执行文件不存在或实际上不可执行。换句话说,这是一个你应该照顾的错误条件。