2019年12月1日日曜日

CGI + Python で画像を添付したメールを送る

CGI で画像を添付して Python でメールを送るサンプルを置いておきます。

なんだかんだモックを作るときに CGI はとても便利です。 ただメール送信も CGI も自発的には使わなくなってきてサンプルを見つけるのが面倒になってきているので、残しておきます。 昔だったらこういうのは Ruby で書いてたけど、最近は Python のほうが楽かも。

# -*- coding: utf-8 -*-
import cgi, ssl, textwrap, base64, smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate


ACCOUNT = 'foo@bar.com'
PASSWORD = 'hogefuga'

def create_message(name, img, to):
    message = textwrap.dedent('''\
        {name}さん、こんにちは。
        ''').format(name=name).strip()
    msg = MIMEMultipart()
    msg['Subject'] = "タイトル"
    msg['From'] = ACCOUNT
    msg['To'] = to
    msg['Date'] = formatdate()
    body = MIMEText(message)
    msg.attach(body)
    attachment = MIMEBase('image', 'png')

    # https://www.lisz-works.com/entry/python-base64-incorrect-padding
    # base64 不足文字を補完
    img += '=' * (len(img) % 4)

    attachment.set_payload(base64.b64decode(img))
    encoders.encode_base64(attachment)
    attachment.add_header(
        "Content-Disposition", "attachment", filename='capture.png')
    msg.attach(attachment)
    return msg

def send_email(msg, to):
    smtp = smtplib.SMTP('smtp.gmail.com', 587)
    smtp.ehlo()
    smtp.starttls()
    smtp.login(ACCOUNT, PASSWORD)
    smtp.mail(ACCOUNT)
    smtp.rcpt(to)
    smtp.data(msg.as_string())
    smtp.quit()

def check_parameters(form):
    if 'name' not in form:
        return False
    if 'to' not in form:
        return False
    if 'img' not in form:
        return False
    return True



# name = '山田 太郎'
# to = 'hello@world.com'
# img = ''  # base64に変換したものを適当に
# msg = create_message(name, img, to)
# send_email(msg, to)

form = cgi.FieldStorage()
if check_parameters(form):
    name = form.getvalue('name')
    img = form.getvalue('img')
    to = form.getvalue('email')

    msg = create_message(name, img, to)
    send_email(msg, to)
    print("Content-Type: text/html\n")
    print("OK!")
else:
    print("Status: 400 Bad Request\n")


クエリパラメータで、 name = [氏名] & to = [送信先] & img = [画像データ] を CGI 経由で POST で受け取り、Gmail でメール送信する例です。 画像データは、<input type="file"> や canvas.toBlob() を FormData.append() すると良いでしょう。 画像は昔なら base64 化して送ってましたが、今は canvas.toBlob() が良いです。

ちなみに Gmail でこのスクリプトを動かすには、Google アカウントの セキュリティ設定 から、アプリパスワードの設定が必要です。

0 件のコメント: