<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: あかやん</title>
    <description>The latest articles on DEV Community by あかやん (@kabuakantech).</description>
    <link>https://dev.to/kabuakantech</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F855973%2F5538ee71-9b81-4f12-9f43-daeb42051988.png</url>
      <title>DEV Community: あかやん</title>
      <link>https://dev.to/kabuakantech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kabuakantech"/>
    <language>en</language>
    <item>
      <title>Kotlin用のJavadoc(dokka)でドキュメント化する要素を可視性で制御する</title>
      <dc:creator>あかやん</dc:creator>
      <pubDate>Wed, 18 May 2022 15:28:34 +0000</pubDate>
      <link>https://dev.to/kabuakantech/kotlinyong-nojavadocdokkadedokiyumentohua-suruyao-su-woke-shi-xing-dezhi-yu-suru-j4</link>
      <guid>https://dev.to/kabuakantech/kotlinyong-nojavadocdokkadedokiyumentohua-suruyao-su-woke-shi-xing-dezhi-yu-suru-j4</guid>
      <description>&lt;h1&gt;
  
  
  はじめに
&lt;/h1&gt;

&lt;p&gt;Kotlinではソースコードのドキュメント(Javadoc)化にdokkaを使用する事が多いと思います。&lt;br&gt;
dokkaは、デフォルトでprivateも含めてすべての可視性の要素がドキュメントとして出力されてしまい、ライブラリを公開した際などに不要な要素などが混じってしまう可能性があります。&lt;br&gt;
その際、ドキュメント化する要素を可視性修飾子により決定することで、publicな要素のみをドキュメントとして公開できてドキュメントの可読性が向上します。その方法について紹介します。&lt;/p&gt;
&lt;h1&gt;
  
  
  (前提) Kotlinの可視性修飾子
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/visibility-modifiers.html"&gt;https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/visibility-modifiers.html&lt;/a&gt;&lt;br&gt;
&lt;code&gt;private&lt;/code&gt;, &lt;code&gt;protected&lt;/code&gt;, &lt;code&gt;internal&lt;/code&gt;, &lt;code&gt;public&lt;/code&gt;の4つがあります。Javaでは&lt;code&gt;internal&lt;/code&gt;という可視性は存在しません。これは同じモジュール内から参照可能となる可視性で、ライブラリを作成するときに非常に重宝しました(Javaの&lt;code&gt;package protect&lt;/code&gt;とほぼ同等かと思います)&lt;/p&gt;
&lt;h1&gt;
  
  
  (前提) dokkaの記述方法
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;build.gradle.kts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.dokka"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.6.21"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.dokka"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;buildscript&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;jcenter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;classpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.jetbrains.dokka:dokka-gradle-plugin:1.6.21"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;以上を記述した上で、以下のコマンドを実行します&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gradle dokkaHtml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;すると&lt;code&gt;build/dokka/&lt;/code&gt;配下に&lt;code&gt;index.html&lt;/code&gt;などが作成されるかと思います。&lt;/p&gt;

&lt;h1&gt;
  
  
  dokkaの出力を可視性修飾子により制御する方法
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;build.gradle.kts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.jetbrains.dokka.gradle.DokkaTask&lt;/span&gt;

&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DokkaTask&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;configureEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;dokkaSourceSets&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;configureEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;documentedVisibilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jetbrains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dokka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DokkaConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Visibility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jetbrains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dokka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DokkaConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Visibility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PROTECTED&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;上記の例では&lt;code&gt;DokkaTask&lt;/code&gt;の&lt;code&gt;configureEach&lt;/code&gt;で出力する可視性として(&lt;code&gt;Visibility.PUBLIC&lt;/code&gt;, &lt;code&gt;Visibility.PROTECTED&lt;/code&gt;)を設定しました。&lt;br&gt;
あとは、先程と同じように&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gradle dokkaHtml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;でpublic及びprotectedのみの要素のドキュメントを生成することが可能です。&lt;/p&gt;

&lt;p&gt;この&lt;code&gt;DokkaTask&lt;/code&gt;の&lt;code&gt;configureEach&lt;/code&gt;内には、他にもいろいろな項目が設定可能となっています。詳しくはこちらをご覧ください。&lt;br&gt;
&lt;a href="https://kotlin.github.io/dokka/1.6.21/user_guide/gradle/usage/"&gt;https://kotlin.github.io/dokka/1.6.21/user_guide/gradle/usage/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Kotlinでfatjar(shadowjar)を作る(kts版)</title>
      <dc:creator>あかやん</dc:creator>
      <pubDate>Tue, 17 May 2022 06:33:49 +0000</pubDate>
      <link>https://dev.to/kabuakantech/kotlindefatjarshadowjarwozuo-ruktsban--5bfm</link>
      <guid>https://dev.to/kabuakantech/kotlindefatjarshadowjarwozuo-ruktsban--5bfm</guid>
      <description>&lt;p&gt;毎回fatjarを作るときにやり方ググるのが面倒なので自分の記事としてメモしておきます。&lt;br&gt;
なおGradleはkts版とします。Groovy版では少々記述を変える必要があります&lt;/p&gt;
&lt;h2&gt;
  
  
  参考
&lt;/h2&gt;

&lt;p&gt;fatjarとは依存ライブラリも含めたjarファイルです。通常のbuildをした場合に生成されるjarファイルは依存ライブラリは含まれていなく、そのjarを実行する際には依存ライブラリを指定してあげる必要があります。&lt;br&gt;
fatjarを生成しておくと、このjarファイルだけでプログラムの実行が可能となります。&lt;br&gt;
なお、ここまでfatjarと書いていますが、実際に作成に使用するのはshadowjarです。&lt;/p&gt;
&lt;h2&gt;
  
  
  手順
&lt;/h2&gt;

&lt;p&gt;新しいバージョンが常に出ているはずなので、最新のバージョンはこちらで確認しましょう&lt;br&gt;
&lt;a href="https://imperceptiblethoughts.com/shadow/getting-started/"&gt;https://imperceptiblethoughts.com/shadow/getting-started/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;build.gradle.kts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jvm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.6.20"&lt;/span&gt;  &lt;span class="c1"&gt;// ここはもともと書いてあるはず&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.johnrengelman.shadow"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"7.1.2"&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"java"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// jarファイルを実行時に実行されるメインファイルのクラスを指定する。&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;jar&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Jar&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;manifest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// mainメソッドが存在するファイルのパスに、末尾にKtを付与したものです。&lt;/span&gt;
        &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Main-Class"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"packagename.XxxxxXxxxxKt"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;こうすることで、&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gradle shadowJar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;で&lt;code&gt;build/libs/xxxxxxxxx-1.0-SNAPSHOT-all.jar&lt;/code&gt;にshadowJarが生成されます。&lt;br&gt;
このjarを以下のように実行すると&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java -jar build/libs/xxxxxxxxx-1.0-SNAPSHOT-all.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;先程指定した&lt;code&gt;packagename.XxxxxXxxxxKt&lt;/code&gt;のmainメソッドが実行されます。&lt;/p&gt;

&lt;p&gt;もしほかのmainメソッドを実行したい場合は&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java -cp build/libs/xxxxxxxxx-1.0-SNAPSHOT-all.jar packagename.YyyyyyYyyyyyKt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;のように実行することができます。この場合、&lt;code&gt;build.gradle.kts&lt;/code&gt;の&lt;code&gt;jar manifest&lt;/code&gt;の記載は不要になります。(その代わり&lt;code&gt;java -jar&lt;/code&gt;では実行できない)&lt;/p&gt;

&lt;p&gt;以上です。shadowJarを使うだけであれば、pluginに2行追加するだけで良いので非常に楽です。ただ、依存の衝突などが発生した場合は大変ですがその際はMergeStrategyを記述する必要があります。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>KotlinでGmailのAPI経由でメールを取得する</title>
      <dc:creator>あかやん</dc:creator>
      <pubDate>Mon, 16 May 2022 11:53:14 +0000</pubDate>
      <link>https://dev.to/kabuakantech/kotlindegmailnoapijing-you-demeruwoqu-de-suru-1ama</link>
      <guid>https://dev.to/kabuakantech/kotlindegmailnoapijing-you-demeruwoqu-de-suru-1ama</guid>
      <description>&lt;h1&gt;
  
  
  はじめに
&lt;/h1&gt;

&lt;p&gt;KotlinでGmailのメールを取得して解析したり、既読フラグを付けたりする必要があったので方法をまとめました。&lt;br&gt;
流れとしては、まずGoogle Cloud Platform(GCP)上でGmailへのアクセスが可能なクライアント用OAuthトークンを発行します。&lt;br&gt;
そのOAuthトークンを用いて、任意のGmailアカウントでクライアントを認証しユーザトークンを発行、そのトークンを用いてメール取得などを行います。&lt;/p&gt;
&lt;h2&gt;
  
  
  Google Cloud Platformでの作業
&lt;/h2&gt;

&lt;p&gt;GCP上で行うことは、自分のアカウントに紐付いたGmail API用のOAuthトークンを発行することです。ここで言う「自分のアカウント」はメールを取得したいアカウントでなくてもOKです。&lt;br&gt;
任意のアカウントでクライアントID用のOAuthトークンを発行し、そのトークンを用いて任意のGmailアカウント(アプリ認証済み)のメールを取得することが可能なアプリケーションを作成します。&lt;/p&gt;
&lt;h2&gt;
  
  
  クライアント用のOAuthトークン発行
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://console.cloud.google.com/"&gt;Google Cloud Platform&lt;/a&gt;で、&lt;a href="https://console.cloud.google.com/projectselector2/apis/dashboard"&gt;API Service&lt;/a&gt;のページに移動します。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dPueVscs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o22meqvw59s8n2c285ce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dPueVscs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o22meqvw59s8n2c285ce.png" alt="Image description" width="880" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FVEANiDk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/343fjyhr1ukx0oanwxaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FVEANiDk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/343fjyhr1ukx0oanwxaa.png" alt="Image description" width="880" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gmail APIを有効にします。&lt;br&gt;
&lt;a href="https://console.cloud.google.com/apis/library/gmail.googleapis.com"&gt;https://console.cloud.google.com/apis/library/gmail.googleapis.com&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c9y-DnUc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65235x1cutg2h2p5b19v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c9y-DnUc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65235x1cutg2h2p5b19v.png" alt="Image description" width="880" height="588"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;認証情報からOAuthトークンを発行します。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P8N1ZBof--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8720ilurplhypcsa8mmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P8N1ZBof--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8720ilurplhypcsa8mmx.png" alt="Image description" width="880" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3H6S37Bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/591z4fq0100zk91vrvan.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3H6S37Bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/591z4fq0100zk91vrvan.png" alt="Image description" width="880" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;発行したトークンはこちらからjsonとしてダウンロードしておきKotlinプロジェクトディレクトリにおいておきます。&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yRxrg67H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10avja83ywyycbcxrz48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yRxrg67H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10avja83ywyycbcxrz48.png" alt="Image description" width="880" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;また、作成したアプリケーションは本番に公開、もしくはテストユーザとして使用したいGmailアカウントを登録しておく必要があります。&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ldpBK6FZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kn494gr4nisrqrqhrnjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ldpBK6FZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kn494gr4nisrqrqhrnjo.png" alt="Image description" width="880" height="899"&gt;&lt;/a&gt;&lt;br&gt;
本番に公開した場合でも、credentialsが知られていなければ他人に悪用されることはありませんのでどちらでもOKだと思います。&lt;/p&gt;

&lt;p&gt;これでGoogle Cloud Platform上での作業は終了です。&lt;/p&gt;
&lt;h2&gt;
  
  
  Kotlinの実装
&lt;/h2&gt;

&lt;p&gt;build.gradle.ktsはこちら&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    implementation("com.google.api-client:google-api-client:1.34.1")
    implementation("com.google.oauth-client:google-oauth-client-jetty:1.33.3")
    implementation("com.google.apis:google-api-services-gmail:v1-rev20220404-1.32.1")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;まずはOAuth認証をする部分を実装します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
   * このアプリケーションに付与する権限の一覧。必要に応じて適切に設定してください
   * https://developers.google.com/resources/api-libraries/documentation/gmail/v1/java/latest/com/google/api/services/gmail/GmailScopes.html
   */&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;SCOPES&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;GmailScopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GMAIL_LABELS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// メールのラベルを取得する権限&lt;/span&gt;
    &lt;span class="nc"&gt;GmailScopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GMAIL_READONLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// メールを読み取る権限&lt;/span&gt;
    &lt;span class="nc"&gt;GmailScopes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GMAIL_MODIFY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// メールのラベルの修正や送信なども行える権限&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * jsonのアプリケーション情報を用いてOAuthユーザ認証を行います。
   */&lt;/span&gt;
  &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;httpTransport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NetHttpTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;jsonFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GsonFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;credentialsFilePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"credentials.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tokenDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"tokens"&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Credential&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// val jsonFactory: GsonFactory = GsonFactory.getDefaultInstance()&lt;/span&gt;
    &lt;span class="c1"&gt;// Googleが提供するHTTPクライアントを生成(これは、通常のNetHttpTransportにGoogle API用のルート証明書が埋め込まれていたりするようです。)&lt;/span&gt;
    &lt;span class="c1"&gt;// val httpTransport = GoogleNetHttpTransport.newTrustedTransport()&lt;/span&gt;

    &lt;span class="c1"&gt;// OAuth認証情報の読み込み&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;inputStream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;credentialsFilePath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inputStream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// json形式の認証情報を読み込む&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;clientSecrets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GoogleClientSecrets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GoogleClientSecrets&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;InputStreamReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputStream&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;// 認証フローの設定をする。&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GoogleAuthorizationCodeFlow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GoogleAuthorizationCodeFlow&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clientSecrets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SCOPES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setDataStoreFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FileDataStoreFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenDir&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="c1"&gt;// トークン保存先ディレクトリの指定&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAccessType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"offline"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// web applicationの場合はonline, それ以外はoffline&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// callback受け取り用URL(localhost:8888)のWebサーバを建てる&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;receiver&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalServerReceiver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// 認証用を行う(ここでWebサイトが開きユーザにアプリ認証を実行させる)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationCodeInstalledApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;getCredentials()&lt;/code&gt;を実行すると、以下のようなアプリケーション認証画面が立ち上がり、適切な権限を許可してアプリケーションにコールバック(localhost:8888)してあげます。&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CnMC7y3s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pwq62ivje5adb4jdxd5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CnMC7y3s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pwq62ivje5adb4jdxd5t.png" alt="Image description" width="880" height="1476"&gt;&lt;/a&gt;&lt;br&gt;
アプリケーションは受け取ったコールバックに含まれるユーザトークンをもとに、以後Gmailの操作を行っていきます。&lt;/p&gt;

&lt;p&gt;Gmail serviceインスタンスの作成&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;jsonFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;GsonFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GsonFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDefaultInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;// Googleが提供するHTTPクライアントを生成(これは、通常のNetHttpTransportにGoogle API用のルート証明書が埋め込まれていたりするようです。)&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;httpTransport&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GoogleNetHttpTransport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newTrustedTransport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;credential&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"credentials.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tokens"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// Gmail serviceを作成。Gmailの各種操作には以降このserviceを使用します。&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Gmail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setApplicationName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kotlin-gmail-reader"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;readMailAndRemoveUnread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// 下で実装します&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ここで作成された&lt;code&gt;service&lt;/code&gt;インスタンスを用いて以後Gmailの操作が可能となります。&lt;/p&gt;

&lt;p&gt;そして、メールを読み込んで既読フラグを付与するプログラムを作成します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;readMailAndRemoveUnread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Gmail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"me"&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;targetLabel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"UNREAD"&lt;/span&gt; &lt;span class="c1"&gt;// 今回の読み込み対象のラベルは未読メールとします。INBOXやSENT,IMPORTANTなども選べます。&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;labelList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;// ラベル一覧を出力してみます。&lt;/span&gt;
  &lt;span class="n"&gt;labelList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// UNREADラベルインスタンスを取得します&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;labelList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;targetLabel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$targetLabel label not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// 取得対象のメッセージID一覧を取得する(ここではメールヘッダや本文は取得できない)&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;messageIdList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;labelIds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pageToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;  &lt;span class="c1"&gt;// 初回はnull。続きを取得する場合に指定する。&lt;/span&gt;
    &lt;span class="n"&gt;includeSpamTrash&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;maxResults&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="c1"&gt;// メッセージ取得数&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mailMessageList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messageIdList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;messageId&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// メッセージIDをもとにメッセージを取得する&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// メール本文はBase64でエンコードされているのでデコードする&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// palyloadのbodyにdata要素がある場合&lt;/span&gt;
      &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;massageBase64&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;CharSequence&lt;/span&gt;
      &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BaseEncoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;base64Url&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;massageBase64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Charset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Base64がpartsというヘッダで複数要素に分割されている場合があるのでここで結合しながらデコードする&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;containsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;CharSequence&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BaseEncoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;base64Url&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Charset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// それ以外の場合は今回は対象外とする(本来はしっかりと処理する必要があるが)&lt;/span&gt;
        &lt;span class="s"&gt;""&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// メールのヘッダがこのままでは使いにくいのでMapに変換する&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;headersMap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;associate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowercase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Locale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDefault&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// MailMessageは最下部で定義しているdata classです。&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mailMessage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MailMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headersMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;headersMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;headersMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// メール内容を出力する&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mailMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mailMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mailMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mailMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// メールを既読にする(GoogleではUNREADラベルが付与されているものが未読のため、そのUNREADラベルを削除すると既読となる)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;labelIds&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UNREAD"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;batchRemoveUnreadLabel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BatchModifyMessagesRequest&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;removeLabelIds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;batchModify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batchRemoveUnreadLabel&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;mailMessage&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;MailMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;以上でメールの取得やメールの既読操作などができました。&lt;br&gt;
同じような操作でメールの送信なども可能になると思います。&lt;br&gt;
Javaの公式ドキュメントはこちらにありますので合わせてご参照いただければと思います。&lt;br&gt;
&lt;a href="https://developers.google.com/gmail/api/quickstart/java"&gt;https://developers.google.com/gmail/api/quickstart/java&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>令和の時代にjQueryでフォームのvalidationを行う</title>
      <dc:creator>あかやん</dc:creator>
      <pubDate>Wed, 11 May 2022 03:53:31 +0000</pubDate>
      <link>https://dev.to/kabuakantech/ling-he-noshi-dai-nijquerydehuomunovalidationwoxing-u-1563</link>
      <guid>https://dev.to/kabuakantech/ling-he-noshi-dai-nijquerydehuomunovalidationwoxing-u-1563</guid>
      <description>&lt;p&gt;やむを得ずjQueryでフォームのvalidationを行う必要があったのでメモとして行った方法を残しておきます。&lt;/p&gt;

&lt;p&gt;今の時代はReactやVue.jsなどの仮想DOMで簡単に行えるようになっているので、わざわざjQueryで行う必要はないのですが、どうしてもReactなどが使用できない環境でしたのでこちらの環境を使用しました。&lt;/p&gt;

&lt;h1&gt;
  
  
  使ったライブラリ
&lt;/h1&gt;

&lt;p&gt;今回は&lt;a href="https://jqueryvalidation.org/"&gt;jQuery Validation Plugin&lt;/a&gt;を使用しました。&lt;br&gt;
思ってた１０倍は便利なライブラリでした&lt;/p&gt;
&lt;h1&gt;
  
  
  シンプルな使用方法
&lt;/h1&gt;

&lt;p&gt;私はCDNから引っ張ってきたのでこちらを貼り付けるだけです。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;あとは、スクリプトで対象のformにvalidate関数を仕込んであげるだけです。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form id=validationForm&amp;gt;
  &amp;lt;input name="mail"&amp;gt;
  ....
&amp;lt;/form&amp;gt;

&amp;lt;script type="text/javascript"&amp;gt;
  $(function(){
    $('#validationForm').validate({
      rules: {
        name: {
          required: true
        },
        mail: {
          required: true,
          email: true,
        },
        mailConfirm: {
          email: true,
          equalTo : "#mail"
        },
        content: {
          required: true
        },
      },
      messages: {
        name: {
          required: '名前を入力してください。',
        },
        mail: {
          required: 'メールアドレスを入力してください。',
          email: '有効なメールアドレスを入力してください。'
        },
        mailConfirm: {
          required: '確認メールアドレスを入力してください。',
          email: '有効なメールアドレスを入力してください。',
          equalTo : 'メールアドレスが一致しません。'
        },
        content: {
          required: '内容を入力してください。',
        },
      },
    });
  });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rulesでは&lt;code&gt;required&lt;/code&gt;や&lt;code&gt;email&lt;/code&gt;などのプリセットのルールを仕込むことができますし、正規表現でvalidationをかけることもできます(私は使っていないので割愛します)&lt;br&gt;
&lt;code&gt;required&lt;/code&gt;はフォームが必須の場合に使用するルールです。&lt;br&gt;
&lt;code&gt;email&lt;/code&gt;は有効なメールアドレスのvalidationをしてくれます&lt;br&gt;
&lt;code&gt;equalTo&lt;/code&gt;は指定したinput(今回は#mail)と同一の内容かをチェックしてくれます。&lt;/p&gt;

&lt;p&gt;messagesではvalidationに失敗した場合に表示するメッセージを設定することができます。&lt;/p&gt;

&lt;p&gt;これで最低限の機能としての実装は終わりです。&lt;br&gt;
こちらで動かすと、validation失敗時にinputタグの直下にラベルが追加されるようになります。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X2UNf56A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40azbji29io6b8bx8h4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X2UNf56A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40azbji29io6b8bx8h4l.png" alt="Image description" width="880" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ここで、できればエラーは赤文字にしたいと思うかもしれません。そのためのオプション機能も用意してくれています。それが&lt;code&gt;errorPlacement&lt;/code&gt;と&lt;code&gt;success&lt;/code&gt;です。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="text/javascript"&amp;gt;
  $(function(){
    $('#validationForm').validate({
      rules: {
        ...
      },
      messages: {
        ..
      },
    },
    errorPlacement: function (error, element) {
      // あるinputのvalidationに失敗した際に呼ばれる。自分で表示をカスタマイズしたいときに使用する。
      // error はエラー時に表示するelement(例: &amp;lt;label&amp;gt;メールアドレスを入力してください。&amp;lt;/label&amp;gt;)が入っている
      // element にはエラーが発生したelement(例: &amp;lt;input name="mail" ...&amp;gt;)が入っている

      // 一例: エラー発生inputの上にあるdivのclass名を --error に変える
      const errorElement = element.closest("div")
      errorElement.removeClass()
      errorElement.addClass('xxxxxx--error')

      // 赤文字で表示できるように定義済みのクラス .item__error を使用したエレメントを errorElement の中に append する
      const errorMessage = errorElement.children("p")
      const customErrorMessage = $($.parseHTML('&amp;lt;span class="item__error"&amp;gt;' + error.text() + '&amp;lt;/span&amp;gt;'));
      errorMessage.append(errorMessageNodes)
    },
    success: function(error, element) {
      // あるinputのvalidationに成功したときに呼ばれる。表示済みのエラーを削除する際に使用する。
      // error はエラー時に表示していたelement(例: &amp;lt;label&amp;gt;メールアドレスを入力してください。&amp;lt;/label&amp;gt;)が入っている
      // element にはエラーが発生していたelement(例: &amp;lt;input name="mail" ...&amp;gt;)が入っている

      // divに装飾していたエラー用classを戻してあげる
      const errorElement = element.closest("div")
      errorElement.removeClass()
      errorElement.addClass('xxxxxx')

      // 赤文字で表示していたエラー内容を削除する
      const errorMessage = errorElement.children("p")
      errorMessage.children(".item__error").remove()
    });
  });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;以上でうまくvalidationすることができました。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rustのシンプルなスレッドの実装</title>
      <dc:creator>あかやん</dc:creator>
      <pubDate>Sun, 01 May 2022 13:41:46 +0000</pubDate>
      <link>https://dev.to/kabuakantech/rustnosuretudono-fan-sinpurunasuretudonoshi-zhuang-n8</link>
      <guid>https://dev.to/kabuakantech/rustnosuretudono-fan-sinpurunasuretudonoshi-zhuang-n8</guid>
      <description>&lt;h1&gt;
  
  
  一番簡単なスレッドの実装
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;thread::spawn(function)&lt;/code&gt;で実装可能。&lt;br&gt;
&lt;code&gt;function&lt;/code&gt;には任意の関数を入れることができる。Rustでクロージャを作成するときは以下&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|x, y| {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;{}&lt;/code&gt;の中には複数行を書くことが可能で、関数の戻り値の行のみ&lt;code&gt;;&lt;/code&gt;無しで実装する必要がある&lt;/p&gt;

&lt;p&gt;例&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|x, y| {
  let value = x + y;
  value
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;これを踏まえてシンプルなスレッドを実装すると以下の通り。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main() {
    let mut handles = Vec::new();
    for x in 1..10 {
        handles.push(thread::spawn(move || {
            println!("{}", x)
        }));
    }
    for handle in handles {
        handle.join();  // 10スレッドの処理が終わるまで待つ
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ここで注意すべきはクロージャの前に &lt;code&gt;move&lt;/code&gt; が書かれていること。&lt;br&gt;
Rustには所有権の概念があり、それに関連したエラーです。&lt;br&gt;
単にループを回してスレッドを作成するだけだと、&lt;code&gt;x&lt;/code&gt;の所有権がthread内に移されず、スレッドが完了する前に&lt;code&gt;x&lt;/code&gt;が寿命となる可能性があるためエラーを吐き出している。&lt;/p&gt;

&lt;p&gt;そのため、&lt;code&gt;x&lt;/code&gt;の所有権を各スレッドに移すために&lt;code&gt;move&lt;/code&gt;を使用している。&lt;/p&gt;

&lt;p&gt;このようにRustでは常に所有権を意識して実装を進めなければならない。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>hello world</title>
      <dc:creator>あかやん</dc:creator>
      <pubDate>Sun, 01 May 2022 03:03:27 +0000</pubDate>
      <link>https://dev.to/kabuakantech/hello-world-pic</link>
      <guid>https://dev.to/kabuakantech/hello-world-pic</guid>
      <description>&lt;h1&gt;
  
  
  I'm now studying Rust
&lt;/h1&gt;

</description>
    </item>
  </channel>
</rss>
