使用Python发送电子邮件,从文本文件中获取收件人列表

时间:2011-05-16 15:35:06

标签: python email osx-snow-leopard

我已经能够拼凑下面的代码,我现在可以通过OSX10.6发送电子邮件。我希望添加到此脚本中的是能够直接从与python文件本身相同的目录中的文本文件“获取”收件人列表。

我还想对'sender'元素进行硬编码,因为它会保持静态。请帮助。

#!/usr/bin/env python

"""Send the contents of a directory as a MIME message."""

import os
import sys
import smtplib
# For guessing MIME type based on file name extension
import mimetypes

from optparse import OptionParser

from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

COMMASPACE = ', '

def main():
parser = OptionParser(usage="""\
Send the contents of a directory as a MIME message.

Usage: %prog [options]

Unless the -o option is given, the email is sent by forwarding to your local
SMTP server, which then does the normal delivery process. Your local machine
must be running an SMTP server.
""")
parser.add_option('-d','--directory',
type='string', action='store')
parser.add_option('-o', '--output',
type='string', action='store', metavar='FILE',
help="""Print the composed message to FILE instead of
sending the message to the SMTP server.""")
parser.add_option('-s', '--sender',
type='string', action='store', metavar='SENDER',
help='The value of the From: header (required)')
parser.add_option('-r', '--recipients',
type='string', action='store', metavar='RECIPIENT',
default="recipient.txt", dest='recipients',
help='A file containing email addresses of recipients. One recipient per line')
opts, args = parser.parse_args()
if not opts.sender or not opts.recipients:
    parser.print_help()
    sys.exit(1)
directory = opts.directory
if not directory:
    directory = '.'
# Create the enclosing (outer) message
outer = MIMEMultipart()
outer['Subject'] = 'Malware submission'

# Variable to hold the recipients string
rec = ""
# Open recipients file
f = open(opts.recipients)
# Loop through each line of the file
for line in f:
    # Remove whitespace from line and add COMMASPACE
    rec += line.rstrip() + COMMASPACE
f.close()

outer['To'] = rec[:-2]; #Remove last COMMASPACE
outer['From'] = opts.sender
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'

for filename in os.listdir(directory):
    path = os.path.join(directory, filename)
    if not os.path.isfile(path):
        continue
    # Guess the content type based on the file's extension. Encoding
    # will be ignored, although we should check for simple things like
    # gzip'd or compressed files.
    ctype, encoding = mimetypes.guess_type(path)
    if ctype is None or encoding is not None:
    # No guess could be made, or the file is encoded (compressed), so
    # use a generic bag-of-bits type.
        ctype = 'application/octet-stream'
        maintype, subtype = ctype.split('/', 1)
    if maintype == 'text':
        fp = open(path)
    # Note: we should handle calculating the charset
        msg = MIMEText(fp.read(), _subtype=subtype)
        fp.close()
    elif maintype == 'image':
        fp = open(path, 'rb')
        msg = MIMEImage(fp.read(), _subtype=subtype)
        fp.close()
    elif maintype == 'audio':
        fp = open(path, 'rb')
        msg = MIMEAudio(fp.read(), _subtype=subtype)
        fp.close()
    else:
        fp = open(path, 'rb')
        msg = MIMEBase(maintype, subtype)
        msg.set_payload(fp.read())
        fp.close()
    # Encode the payload using Base64
    encoders.encode_base64(msg)
# Set the filename parameter
msg.add_header('Content-Disposition', 'attachment', filename=filename)
outer.attach(msg)
# Now send or store the message
composed = outer.as_string()
if opts.output:
    fp = open(opts.output, 'w')
    fp.write(composed)
    fp.close()
else:
    s = smtplib.SMTP('localhost')
    s.sendmail(opts.sender, opts.recipients, composed)
    s.quit()

if __name__ == '__main__':
main()

非常感谢。

3 个答案:

答案 0 :(得分:1)

您可能想要替换这段代码:

# Variable to hold the recipients string
rec = ""
# Open recipients file
f = open(opts.recipients)
# Loop through each line of the file
for line in f:
    # Remove whitespace from line and add COMMASPACE
    rec += line.rstrip() + COMMASPACE
f.close()

这一行:

rec = ', '.join([line.strip() for line in file(opts.recipients) if line.strip()])

答案 1 :(得分:0)

要获取收件人,您可以尝试:

# add a new parameter 'recipientfile'
parser.add_option('-f', '--recipientfile',
              type='string', action='store', metavar='RECIPIENT_FILE',
              default=None, dest='recipient_file',
              help='A To: header value (a file containing this)')

opts, args = parser.parse_args()
if not opts.sender or (not opts.recipients or not opts.recipient_file):
    parser.print_help()
    sys.exit(1)
directory = opts.directory
if not directory:
    directory = '.'
try:                      # load the text file containing recipient1, recipient2, ....
    rec_file = open(opts.recipient_file)
    recipients = rec_file.read()
    rec_file.close()
except OSError:
    print "/!\ Bad file %s"%opts.recipient_file
    recipients = COMMASPACE.join(opts.recipients)
# Create the enclosing (outer) message
outer = MIMEMultipart()
outer['Subject'] = 'Malware submission'
outer['To'] = recipients
outer['From'] = opts.sender
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'

答案 2 :(得分:0)

好的,所以我(或更确切地说是一位同事)解决了这个问题。代码如下,非常感谢Paul Littlefair的解决方案。

#!/usr/bin/env python

"""Send the contents of a directory as a MIME message."""

import os
import sys
import smtplib
# For guessing MIME type based on file name extension
import mimetypes

from optparse import OptionParser

from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

COMMASPACE = ', '


def main():
parser = OptionParser(usage="""\
Send the contents of a directory as a MIME message.

Usage: %prog [options]

Unless the -o option is given, the email is sent by forwarding to your local
SMTP server, which then does the normal delivery process. Your local machine
must be running an SMTP server.
""")
parser.add_option('-d','--directory',
type='string', action='store')
parser.add_option('-o', '--output',
type='string', action='store', metavar='FILE',
help="""Print the composed message to FILE instead of
sending the message to the SMTP server.""")
parser.add_option('-s', '--sender',
type='string', action='store', metavar='SENDER',
help='The value of the From: header (required)')
parser.add_option('-r', '--recipient',
type='string', action='append', metavar='RECIPIENT',
default=[], dest='recipients'),
parser.add_option('-f', '--recipientfile',
type='string', action='store', metavar='RECIPIENT_FILE',
dest='recipient_file', default="",
help='A To: header value (a file containing this)')

opts, args = parser.parse_args()
if not opts.sender or not (opts.recipient_file or opts.recipients):
    parser.print_help()
    sys.exit(1)
directory = opts.directory
if not directory:
    directory = '.'
# Create the enclosing (outer) message

try:
    rec_file = open(opts.recipient_file)
    recipients = rec_file.read()
    rec_file.close()
except IOError:
    print "/!\ Bad file. Falling back to recipent option"
    recipients = COMMASPACE.join(opts.recipients)

outer = MIMEMultipart()
outer['Subject'] = 'Malware submission'
outer['To'] = recipients
outer['From'] = opts.sender
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'

for filename in os.listdir(directory):
    path = os.path.join(directory, filename)
    if not os.path.isfile(path):
        continue
    # Guess the content type based on the file's extension. Encoding
    # will be ignored, although we should check for simple things like
    # gzip'd or compressed files.
    ctype, encoding = mimetypes.guess_type(path)
    if ctype is None or encoding is not None:
    # No guess could be made, or the file is encoded (compressed), so
    # use a generic bag-of-bits type.
        ctype = 'application/octet-stream'
        maintype, subtype = ctype.split('/', 1)
    if maintype == 'text':
        fp = open(path)
    # Note: we should handle calculating the charset
        msg = MIMEText(fp.read(), _subtype=subtype)
        fp.close()
    elif maintype == 'image':
        fp = open(path, 'rb')
        msg = MIMEImage(fp.read(), _subtype=subtype)
        fp.close()
    elif maintype == 'audio':
        fp = open(path, 'rb')
        msg = MIMEAudio(fp.read(), _subtype=subtype)
        fp.close()
    else:
        fp = open(path, 'rb')
        msg = MIMEBase(maintype, subtype)
        msg.set_payload(fp.read())
        fp.close()
    # Encode the payload using Base64
    encoders.encode_base64(msg)
# Set the filename parameter
msg.add_header('Content-Disposition', 'attachment', filename=filename)
outer.attach(msg)
# Now send or store the message
composed = outer.as_string()
if opts.output:
    fp = open(opts.output, 'w')
    fp.write(composed)
    fp.close()
else:
    s = smtplib.SMTP('localhost')
    s.sendmail(opts.sender, recipients, composed)
    s.quit()

if __name__ == '__main__':
main()

输入格式为-d [dir] -s [fromaddress] -f [recipientsourcefile]