通过 Postfix 发送给多个收件人的电子邮件仅由列表中的第一个地址接收



我正在使用此问题底部的Python代码将目录的内容发送到定义文件中保存的收件人列表。在此文件中,各个地址由 ;并在单个字符串中列出。提交所需的命令时,所有内容都已发送,没有任何记录的问题,但事实证明,电子邮件仅发送到列表中第一个指定的电子邮件地址。

经过一些挖掘,Postfix 的 main.cf 文件似乎具有收件人限制,默认值为 1,这可能会限制收件人卷。我尝试将整行进行哈希处理,并将限制增加到 200,但两者都没有任何影响。

# dovecot 1.1.1
dovecot_destination_recipient_limit = 200

当您从单个收件人的角度来看电子邮件时,一切似乎都很好,所以我不得不认为是后缀/Dovecot发送邮件部分导致了问题?请参阅将邮件输出到文件而不是发送到 smtp 的示例

Content-Type: multipart/mixed; boundary="===============7543504478351047681=="
MIME-Version: 1.0
Subject: Malware submission
To: xxxxx@gmail.com;xxxxx@hotmail.com
From: me@yu.com
You will not see this in a MIME-aware mail reader.
--===============7543504478351047681==
Content-Type: application/zip
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="sample.zip"
UEsDBAoAAAAAAHGfsT4AAAAAAAAAAAAAAAAGABwAdmlydXMvVVQJAAOVxdJNKJnSTXV4CwABBPUB
AAAEFAAAAFBLAQIeAwoAAAAAAHGfsT4AAAAAAAAAAAAAAAAGABgAAAAAAAAAEADtQQAAAAB2aXJ1
cy9VVAUAA5XF0k11eAsAAQT1AQAABBQAAABQSwUGAAAAAAEAAQBMAAAAQAAAAAAA
--===============7543504478351047681==--

后缀邮件日志包含以下内容

May 17 21:10:41 MacBook-Pro-2 postfix/qmgr[3816]: 3FB902C186A: from=<chris.parker@email.co.uk>, size=1004, nrcpt=1 (queue active)
May 17 21:10:42 MacBook-Pro-2 postfix/smtp[3855]: 3FB902C186A: to=<xxxxo@gmail.com>, relay=gmail-smtp-in.l.google.com[209.85.143.27]:25, delay=1.3, delays=0.01/0.01/0.57/0.75, dsn=2.0.0, status=sent (250 2.0.0 OK 1305662986 k6si1621545wej.25)
May 17 21:10:42 MacBook-Pro-2 postfix/qmgr[3816]: 3FB902C186A: removed

请帮忙...

    #!/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 -r 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:
    #print "Sender : " + opts.sender + ", Recipients : " + recipients #DEBUG :- Check send and recipients are correct
    s = smtplib.SMTP('localhost')
    s.sendmail(opts.sender, recipients, composed)
    s.quit()
if __name__ == '__main__':
main()

用于生成电子邮件的 Python 代码

定义邮件时,应使用逗号分隔的收件人列表设置To列表:

recipients = 'foo, bar'
outer['To'] = recipients

但是,当您调用sendmail()时,您需要将收件人作为列表传递:

rcpts = [r.strip() for r in recipients.split(',') if r]
s.sendmail(sender, rcpts, composed)

最新更新