Raspberry Pi で メール送信(Gmailアカウント)

Gmailアカウントを使用してメールを送信しようと思ったのですが、ログイン処理の個所で次のようなエラーが発生していました。ログインできません。

Username and Password not accepted.

 

しばらく原因がわからなかったのですが、Gmailのセキュリティ設定を緩くすることで対応できることを確認しました。

今回はその方法ですが、セキュリティが甘くなる、ということを知ったうえで設定してください。

(先に、GmailGoogle)のアカウントは作成しておいてください)

 

 

1. Gmailにログイン、設定画面まで進む

  まずは、送信元となるGoogleアカウントでGmailへログインします。

f:id:kobatom5278:20210220105119j:plain

  管理画面まで進みます。右上の自分のアイコン(私の場合は「T」)をクリック、「Google アカウントを管理」をクリックします

f:id:kobatom5278:20210220105122j:plain

 

  管理画面が開いたら、「セキュリティ」をクリックします。

f:id:kobatom5278:20210220105135j:plain

 

  下へスクロールして、「安全性の低いアプリのアクセス」を探します。そして、「アクセスを有効にする(非推奨)」をクリック。

f:id:kobatom5278:20210220105149j:plain

 

  「安全性の低いアプリの許可」の右のトグルスイッチをクリックします。

f:id:kobatom5278:20210220105157j:plain

 

  「ON」の状態になったらOKです。

f:id:kobatom5278:20210220105205j:plain

 

  無意味ですが、元の画面に戻って設定を確認しましょう。

f:id:kobatom5278:20210220105212j:plain

 

  「オン」になっていることを確認します。非推奨なので、ビックリマークアイコンが出ているのかと思います。

f:id:kobatom5278:20210220105218j:plain

 

  注意点として、「セキュリティ」の中にある、「2段階認証プロセス」が「オン」になっていると、この設定項目が出ないようです。ですので、「2段階認証プロセス」も「オフ」になっている必要もあるようです。

f:id:kobatom5278:20210220105225j:plain

 

2. Pythonプログラミング

  前回の、添付ファイルを送付するプログラムの、GmailSMTPサーバーを変更したものです。

# -*- coding: utf-8 -*-
# 日本語コメントをエラーとしないように、UTF-8で保存

# 使用するライブラリのインポート
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate
from email.mime.base import MIMEBase

# 定数の定義
SELF_MAIL_ADDRESS = '*****@gmail.com'           # 自分のGmailのメールアドレス
SELF_MAIL_PASSWORD = '*****'                    # 自分のGmailのログインパスワード
SELF_SMTP_SERVER = 'smtp.gmail.com'             # GmailのメールアドレスのSMTPサーバー名
SELF_SMTP_PORT = 587                            # SMTPサーバーのポート番号

def create_mail(mail_subject, mail_body, mail_from, mail_to, attach_filename = None):
    """
    送信メールを生成、返却
    """

    # 添付ファイル名の指定有無により切り分け
    if attach_filename == None:
        # 添付ファイルを指定していない場合
        mail_message = MIMEText(mail_body)
    else:
        # 添付ファイルを指定した場合
        mail_message = MIMEMultipart()

        # 本文(添付ファイルより先に指定する必要がある)
        mail_message.attach(MIMEText(mail_body, "plain"))

        # 添付ファイルを読み込んで添付
        try:
            # 添付ファイル名が指定されている場合、ファイルを読み込む
            with open(attach_filename, 'rb') as attach_File:
                att = MIMEBase('application', 'octet-stream')
                att.set_payload(attach_File.read())
        except Exception as e:
            # 指定された添付ファイルが読み込めなかった場合は、ログを吐いて終了
            print(f'Error:{e}')
            exit(0)        

        # 添付ファイルをbase64エンコードして添付
        encoders.encode_base64(att)
        att.add_header('Content-Disposition', f'attachment; filename={attach_filename}')
        mail_message.attach(att)

    # 送信メールを編集
    mail_message['Subject'] = mail_subject              # 件名
    mail_message['From'] = mail_from                    # 送信元メールアドレス
    mail_message['To'] = mail_to                        # 送信先メールアドレス
    mail_message['Date'] = formatdate(localtime=True)   # 送信時間。OSのタイムゾーン依存
           
    # デバッグ用に送信メールの内容を出力
    print(mail_message)

    return mail_message

def send_mail(mail_message):
    """
    メールを送信する
    """

    try:
        smtp = smtplib.SMTP(SELF_SMTP_SERVER, SELF_SMTP_PORT)
        smtp.ehlo()
        smtp.starttls()
        smtp.ehlo()
        smtp.login(SELF_MAIL_ADDRESS, SELF_MAIL_PASSWORD)
    
        smtp.sendmail(SELF_MAIL_ADDRESS, mail_to, mail_message.as_string())
    except Exception as e:
        print(f'Error:{e}')
    finally:
        smtp.quit()


# 継承した場合など、実行されないようにする(現状、意味は特にない)
if __name__ == '__main__':
    # メールの内容
    # 送信先メールアドレス
    mail_to = '*****@*****'
    # メールの件名
    mail_subject = '件名テスト'
    # メールの本文
    mail_body = '本文テスト'
    # 添付ファイル名
    mail_att = 'penguin.jpg'

    # 送信メールを作成する(添付ファイル付き)
    mail_message = create_mail(mail_subject, mail_body, SELF_MAIL_ADDRESS, mail_to, mail_att)
    #  送信メールを作成する(添付ファイルなし)
    # mail_message = create_mail(mail_subject, mail_body, SELF_MAIL_ADDRESS, mail_to)

    # メールを送信する
    send_mail(mail_message)