【Python】Gmail を利用してメールを送信してみる

Python,開発

おはようございます。

久しぶりの Python 記事です。

今回は Gmail を利用してメールを送信する方法を試してみました。

プロジェクトは新しく作成します。

スポンサーリンク

事前準備

Gmailを利用するために、サードパーティ製のアプリからのメール送信を許可する必要があります。

セキュリティの設定

Googleにログインし、セキュリティの設定から、「安全性の低いアプリの許可」をオンに変更します。

新規プロジェクトの作成

ディレクトリ構成は次のとおり。
AdminLTEで丁度いいのがあったので流用しました。

SampleMail
│ Main.py

├─static
│ ├─css
│ │ │ AdminLTE.css
│ │ │ AdminLTE.min.css
│ │ │ style.css
│ │ │
│ │ └─skins
│ │
│ └─js
│ adminlte.min.js
│ script.js

└─templates
Main.html

パッケージ追加

とりあえず、今まで通り Tornado をインストールします。

Default Settings

上部メニューの「File」>「Default Settings…」を選択します。

パッケージ追加

別ウィンドウで設定画面が表示されるので、
サイドメニューの「Project Interpreter」を選択、右側に表示される画面にて「Project Interpreter」リストより対象の Python環境を選択、右側にある「+」マークをクリックします。

インストール

パッケージ検索画面が表示されるので、
検索窓に「tornado」を入力して対象のパッケージを検索、絞り込まれた一覧から「tornado」を選択して、「Install Package」ボタンをクリックします。

下部に「Package ‘tornado’ installd successfully」が表示されれば完了です。

プログラム

画面

画面は AdminLTE のクイックメールを流用しました。

templates/Main.html

<!DOCTYPE html>
<html lang="ja">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<title>メールサンプル</title>
	<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
	<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
	<link rel="stylesheet" href="{{ static_url('css/AdminLTE.min.css') }}">
	<link rel="stylesheet" href="{{ static_url('css/style.css') }}">
	<link rel="stylesheet" href="{{ static_url('css/skins/skin-blue.min.css') }}">
</head>
<body>
	<section class="content container-fluid">
		<div class="row">
			<div class="col-xs-8">
				<div class="row">
					<div class="col-xs-8">
                        <!-- quick email widget -->
                        <div class="box box-info box-solid">
                            <div class="box-header with-border">
                                <i class="fa fa-envelope"></i>

                                <h3 class="box-title">メール送信</h3>
                                <!-- tools box -->
                                <div class="pull-right box-tools">
                                <button type="button" class="btn btn-info btn-sm" data-widget="remove" data-toggle="tooltip"
                                        title="Remove">
                                    <i class="fa fa-times"></i></button>
                                </div>
                                <!-- /. tools -->
                            </div>
                            <div class="box-body">
                                <div class="form-group">
                                    <input type="email" class="form-control" id="email_to" name="email_to" placeholder="送信先:">
                                </div>
                                <div class="form-group">
                                    <input type="email" class="form-control" id="email_cc" name="email_cc" placeholder="CC:">
                                </div>
                                <div class="form-group">
                                    <input type="email" class="form-control" id="email_bcc" name="emailb_cc" placeholder="BCC:">
                                </div>
                                <div class="form-group">
                                    <input type="text" class="form-control" id="subject" name="subject" placeholder="件名">
                                </div>
                                <div>
                                    <textarea id="message" class="message" placeholder="メッセージ"></textarea>
                                </div>
                            </div>
                            <div class="box-footer clearfix">
                                <button type="button" class="pull-right btn btn-default" id="sendEmail">送信
                                <i class="fa fa-arrow-circle-right"></i></button>
                            </div>
                        </div>
					</div>
				</div>
			</div>
		</div>
	</section>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
	<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.19/jquery-ui.min.js"></script>
	<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
	<script src="{{ static_url('js/adminlte.min.js') }}"></script>
	<script src="{{ static_url('js/script.js') }}"></script>
	<script>
		$(document).ready( function () {
			initialize();
		} );
	</script>
</body>
</html>

static/css/style.css

.form-control {
    ime-mode: active;
}

.message {
    width: 100%;
    height: 125px;
    font-size: 14px;
    line-height: 18px;
    border: 1px solid #dddddd;
    padding: 10px;
}

クライアントサイド

static/js/script.js

/**
 * 初期処理.
 */
function initialize() {
    // ボタンにイベントを追加
    $("#sendEmail").click(function () {
        sendMessage();
    });
}

/**
 * メッセージを送信.
 */
function sendMessage() {

   var param = {
      email_to : $("#email_to").val()
      , email_cc : $("#email_cc").val()
      , email_bcc : $("#email_bcc").val()
      , subject : $("#subject").val()
      , message : $("#message").val()
   }

   $.ajax({
      url: "http://localhost:8888/sendMail",
      type: "POST",
      data: JSON.stringify(param),
      success: function(jsonResponse) {
         jsonResponse = jsonResponse.replace( /\\/g , "" );
         var data = JSON.parse(jsonResponse);
         alert("メッセージを送信しました。");
      },
      error: function() {
      }
   });
}

サーバーサイド

Main.py

# --- coding: utf-8 ---
"""
メールサンプル
"""
import os
import logging
import json

import tornado.web
import tornado.ioloop
import tornado.websocket
from tornado.web import RequestHandler
from tornado.options import options

import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate

FROM_ADDR = "yourmail@gmail.com"
PASSWORD = "xxxxxx"

class MainHandler(RequestHandler):
    """
    初期表示処理
    """

    def initialize(self):
        logging.info("[MainHandler] initialize")

    def get(self):
        logging.info("[MainHandler] get")
        self.render("Main.html", from_addr=FROM_ADDR, password=PASSWORD)


class SendMailHandler(RequestHandler):
    """
    メール送信処理
    """

    def initialize(self):
        logging.info("SendMailHandler [initialize]")

    def post(self):
        param = json.loads(self.request.body)

        # メール情報を設定
        msg_obj = MIMEText(param["message"])
        msg_obj["Subject"] = param["subject"]
        msg_obj["From"] = FROM_ADDR
        msg_obj["To"] = param["email_to"]
        msg_obj["Cc"] = param["email_cc"]
        msg_obj["Bcc"] = param["email_bcc"]
        msg_obj["Date"] = formatdate()

        # 送信先のリスト
        to_list = param["email_to"].split(",")
        cc_list = param["email_cc"].split(",")
        bcc_list = param["email_bcc"].split(",")

        # SMTPの設定
        smtp_obj = smtplib.SMTP("smtp.gmail.com", 587)
        smtp_obj.ehlo()
        smtp_obj.starttls()
        smtp_obj.login(FROM_ADDR, PASSWORD)
        smtp_obj.sendmail(FROM_ADDR, to_list+cc_list+bcc_list, msg_obj.as_string())
        smtp_obj.close()

        data = {
            "result": "Success"
        }

        self.write(json.dumps(data, ensure_ascii=False))


application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/sendMail", SendMailHandler),
],
    template_path=os.path.join(os.getcwd(),  "templates"),
    static_path=os.path.join(os.getcwd(),  "static"),
)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    application.listen(8888)
    logging.info("server started")
    tornado.ioloop.IOLoop.instance().start()

メール情報(msg_obj)に設定する情報は、メールクライアントなどで表示されるものになります。
実際に送信される宛先やCCは、sendmailメソッドに渡しているアドレスとなります。

起動してみる

メール送信画面
送信結果

送信後、メッセージが表示されればOKです。

まとめ

今回は画面に入力した情報を元にメールを送ってみましたが、
もちろんプログラム上の処理をトリガーにしてメール送信するといったことも可能ですね。

次回は AdminLTE を利用して、HTMLメールを送信できるようにしてみたいと思います。

ではでは。

スポンサーリンク


関連するコンテンツ