Pythonからファイル添付したメール送信

ワンライナーで立てたDebugingServerにpythonからファイル添付したメール投げてみる
pythonワンライナーでテスト用smtpサーバーをたてる - brainstorm

import smtplib
import sys
from email import encoders, utils
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import mimetypes


def attachment(filename):
    fd = open(filename, 'rb')
    mimetype, mimeencoding = mimetypes.guess_type(filename)
    if mimeencoding or (mimetype is None):
        mimetype = 'application/octet-stream'
    maintype, subtype = mimetype.split('/')
    if maintype == 'text':
        retval = MIMEText(fd.read(), _subtype=subtype)
    else:
        retval = MIMEBase(maintype, subtype)
        retval.set_payload(fd.read())
        encoders.encode_base64(retval)
    retval.add_header('Content-Disposition', 'attachment', filename=filename)
    fd.close()
    return retval


def create_message(fromaddr, toaddr, subject, message, files):
    msg = MIMEMultipart()
    msg['To'] = toaddr
    msg['From'] = fromaddr
    msg['Subject'] = subject
    msg['Date'] = utils.formatdate(localtime=True)
    msg['Message-ID'] = utils.make_msgid()

    body = MIMEText(message, _subtype='plain')
    msg.attach(body)

    for filename in files:
        msg.attach(attachment(filename))
    return msg.as_string()


def send(fromaddr, toaddr, message):
    s = smtplib.SMTP(host="127.0.0.1", port=20025)
    s.sendmail(fromaddr, [toaddr], message)
    s.close()


if __name__ == '__main__':
    fromaddr = 'foo@example.com'
    toaddr = 'bar@example.com'
    message = create_message(fromaddr, toaddr, 'test subject', 'test body', sys.argv[1:])
    send(fromaddr, toaddr, message)


実行

$ echo "test body" > test.txt
$ gzip < test.txt > test.txt.gz
$ send_mail.py test.txt test.txt.gz

実行結果

Content-Type: multipart/mixed; boundary="===============9100462119618884477=="
MIME-Version: 1.0
To: bar@example.com
From: foo@example.com
Subject: test subject
Date: Sun, 24 Feb 2013 13:43:20 +0900
Message-ID: <20130224044320.84076.27377@xxxxxxxxxxxxxx>
X-Peer: 127.0.0.1

--===============9100462119618884477==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

test body
--===============9100462119618884477==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="test.txt"

test body

--===============9100462119618884477==
Content-Type: application/octet-stream
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.txt.gz"

H4sIAFaaKVEAAytJLS5RSMpPqeQCACdlyeYKAAAA
--===============9100462119618884477==--