上位に戻る ESP32 OAuth認証で、Gmailでメール送る 初版2025/2/25

ESP32 雨検出器を作りたく始めたのですが、色々引っかかったので、記録しておこうと思います
雨を検出した場合の通知は、作り始めた時は、LINEのNotifyを試験して通知出来たのでこれで行こうと作り始めたのですが、この
サービスが、2025年3月末で終わるとの通知がきました。代替え機能は、ビジネス向けプランに変更だって・・・・。でここからが
ドツボにはまりました トホホ
ビジネス向けプランなんか支払い登録しないといけないみたいだしいやだ で調べてると、

プロジェクト共有サービスのSlack のAPIを使ってスマホにプッシュ通知を送る記事があったので試してみました アカウント作って
ワークスペース作ってプロジェクト作って APIを登録のところで、んん判らん・・・ 英語判らんし、翻訳も意味が理解できない
工作好きのただのジジイの頭ではムリだあああ!

もうメールでいっか Push通知機能のあるメールだったらほぼ即座に通知が来るので と思ってメールでの通知を検討
スマホがandroidなのでGmailで、自分宛に送れば解決じゃねえか! ESPのライブラリ調べると、ESP Mail Clientなるライブラリが
あるじゃないですか 普通にsmtp認証で試したらダメだああ 調べると ムムムム Gmail IDとPasswordによるsmtp認証方式が
禁止になってる OAuth2.0認証しかダメみたい ESP Mail Clientの説明にはXOAuth2.0認証に対応って書いてはあるのだが
またもや判らん・・・・。凡例のアクセストークンあたりと思われるが 
昔は、メール送信、25番ポートで簡単に送りたいほうだいだったのに、今はIMAPだのSSLだのムズすぎ・・・。

で、もうしょうがない ESP32からは、HTTPクライアントで、WindowsのWebサーバにメールの送り先や内容をPOSTしてWebサーバから
Gmailのメールサーバを使って送信することに
asp.netのSmtp Clientクラスには、調べるとOAuth認証には対応していなく またまたしょうがないのでOAuth認証に対応した
フリーのSMAILというメールソフトを使うことにしました googleへのアクセストークンの取得方法などが詳しくマニュアルに記載
されており、理解できていないジジイでもできました

いやあ長かった・・・。
追伸 なんかgooleで2段階認証を有効にしてアプリパスワードを取得してSMTP Auth(ID,password)で認証している紹介サイトを発見!
ゲロゲロ・・・。OAuth認証じゃなくてもいいのかえ ガックリ

  1. ESP32側のコード
    asp.net(自宅サーバ)のwebサーバにメール宛先、題名、本文をpostする
    #include <WiFi.h>
    #include <WiFiClientSecure.h>

    // WiFi設定
    const char* ssid     = "ssiddesu";
    const char* password = "passworddesu";
    //wifi接続
    int lpcnt;
    int lpcnt2;
    //asp.net webサーバ
    const char* host = "host.nonamae.jp";
    String atesaki="atesaki1@gmail.com,atesaki2@gmail.com";
    String daimei="雨の通知";
    String naiyou="雨が降り始めました   \n2行目";

    void setup()
    {
       // シリアルモニタの通信速度
       Serial.begin(115200);
      delay(500);
      // ssidとpasswordを用いてWi-Fiに接続
      Serial.print("Connecting to ");
      Serial.println(ssid);
       while (WiFi.status() != WL_CONNECTED) {    // 接続確認
          delay(500);                            //   0.5秒毎にチェック
          lpcnt += 1 ;                           //
          if (lpcnt > 6) {                       // 6回目(3秒) で切断/再接続
            WiFi.disconnect(true,true) ;         //
            WiFi.begin(ssid, password);    //
            lpcnt = 0 ;                          //
            lpcnt2 += 1 ;                        // 再接続の回数をカウント
          }                                      //
          if (lpcnt2 > 3) {                      // 3回 接続できなければ、
            ESP.restart() ;                      // ソフトウェアリセット
          }                                      //
          Serial.print(".");                     //
      }            

        Serial.println("");
        Serial.println("WiFi connected.");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());

        send_post(); //サーバにポスト送信
    }

    // post
    void send_post() {
      // HTTPSへアクセス(SSL通信)するためのライブラリ
      WiFiClientSecure client;
      // サーバー証明書の検証を行わずに接続する場合に必要
      client.setInsecure();
      Serial.println("Try");
     
      //自宅aspサーバにSSL接続(ポート443:https)
      if (!client.connect(host, 443)) {
        Serial.println("Connection failed");
        return;
      }
      Serial.println("Connected");

      // リクエスト送信
      String query = "送付先=" + atesaki + "&題名=" + daimei + "&内容=" + naiyou;
      String request = String("") +
                   "POST /xxxx/xxxx/xxxx.aspx HTTP/1.1\r\n" + //post先を指定する
                   "Host: " + host + "\r\n" +
                   "Content-Length: " + String(query.length()) +  "\r\n" +
                   "Content-Type: application/x-www-form-urlencoded\r\n\r\n" +
                    query + "\r\n";
      client.print(request);

        // 一定時間レスポンスがなければタイムアウト.
        unsigned long timeout = millis();
        while (client.available() == 0)
        {
            if (millis() - timeout > 5000)
            {
                Serial.println(">>> Client Timeout !");
                client.stop();
                return;
            }
        }
        // レスポンスを1行ごとに表示 デバッグ用
        while(client.available())
        {
            String line = client.readStringUntil('\r');
            Serial.print(line);
        }
     Serial.println();
     Serial.println("post完了");
    }


    void loop(){
       
    }



  2. サーバ側のコード
    smailを、postを受けるaspxと同じフォルダにsmailというフォルダを作って入れます
    smailのマニュアルに沿って、gmailのoauth認証にデクトップアプリを登録して、トークンを取得します
    ※添付マニュアル2022年度版なので、googleの登録画面が異なってはいます
    マニュアル記載のデバッグ用コマンドラインで実行して状態を確認します
    ここで、正常を確認してください .net側のプログラムでは応答を受け取る仕様にしていませんので
    以下のコードかなり適当なので参考程度です しかも今時 VB で記載しています
    xxxx.aspx
    <!DOCTYPE html>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            </div>
        </form>
    </body>
    </html>

    xxxx.aspx.vb
    Imports System.IO
    Imports System.Diagnostics
    Public Class uketori
        Inherits System.Web.UI.Page

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

            Dim loop1 As Integer
            Dim coll As NameValueCollection
            coll = Request.Form
            Dim arr1 As String() = coll.AllKeys
            'デバッグ用(受け取りデータをページに記述及びtxtファイル保存
            Dim str_result As String = ""
            Dim outdata(10) As String
            For loop1 = 0 To arr1.Length - 1
                str_result = str_result + arr1(loop1) + ":" + coll.Get(arr1(loop1)) + "<br>"
                outdata(loop1) = arr1(loop1) + ":" + coll.Get(arr1(loop1))
            Next
            Label1.Text = str_result
            Dim fnamae As String = Server.MapPath("") & "\postdata.txt"
            File.WriteAllLines(fnamae, outdata)

            '処理の本体
            Dim sousinsaki As String = coll.Get(arr1(0))
            Dim daimei As String = coll.Get(arr1(1))
            Dim naiyou As String = coll.Get(arr1(2))
            'MailMessageの作成
            Dim svpass As String = Server.MapPath("smail/")
            'ダブルクオーテション追加
            daimei = """" & daimei & """"
            naiyou = """" & naiyou & """"
            'メール送信コマンド
            Process.Start(svpass & "smail", "-hsmtp.gmail.com -fYouMail@gmail.com -s" & daimei & " -T" & naiyou & " " & sousinsaki)
        End Sub

    End Class

    デバッグ用に受け取ったデータを返してるのと、postdata.txtに保存しています まあ関係ない部分が多いです





    以上間違い等ありましたら、以下ご意見箱にお願いします

   

    ご意見箱