Kotlin에서 Gmail의 API로 이메일을 보내세요.

23569 단어

はじめに



Kotlin에서 Gmail로 이메일을 보내거나 이메일을 보내거나, 이메일을 보내거나, 이메일을 보내거나, 이메일을 보내거나, 이를 통해 다른 방식으로 연락을 드렸습니다.
Google Cloud Platform(GCP)에서 Gmail을 사용하면 액세스할 수 있습니다.
そのOAuthto-クンを用 いて, 任意のGmail アカウントでクライアントを認証しユーザトークンを発行, そのトークンを用い てmeール取得などを行います.

Google Cloud Platform으로의 작업



GCP에서 실행되는 문서는 Gmail API를 사용하여 인증할 수 있는 문서입니다.
任意のアカウントでクライントID用のOAuthto-kンを発行し、そのトークンを用いて任意のGmail アカウント(アプリ認証済み)의 mer- er を 取 得 する こと が 可能 な ア プ リ ケ ー 作成します.

クライアント用のOAuthto-kン発行



Google Cloud Platform 그리고, API Serviceのページに移動します.





Gmail API는 가능합니다.
https://console.cloud.google.com/apis/library/gmail.googleapis.com


認証情報からOAuthto-kンを発行します.





発行 し た と く は こち ら か ら json と し て ダ ウ ン ロ ー ド し て おきKotlinprojekt ディレク ト リ に お い て お き ま す.


また, 作成したアプリケーションは本番に公開, もしくはtestユーザとして使用したいGmailアカウントを登録しておく必要があります.

本番に公開した場合でも、credentialsが知られていなければ他人に悪用されることはありませんのでどちらでもOKだと思います.

여기에서 Google Cloud Platform을 통해 작업을 완료할 수 있습니다.

Kotlin의 혁신



build.gradle.kts는 여기에서

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")
}


まずはOAuth認証をする部分を実装します.

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

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

    // OAuth認証情報の読み込み
    val inputStream = File(credentialsFilePath).inputStream()
    // json形式の認証情報を読み込む
    val clientSecrets: GoogleClientSecrets = GoogleClientSecrets
      .load(jsonFactory, InputStreamReader(inputStream))

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

    // callback受け取り用URL(localhost:8888)のWebサーバを建てる
    val receiver = LocalServerReceiver.Builder().setPort(8888).build()
    // 認証用を行う(ここでWebサイトが開きユーザにアプリ認証を実行させる)
    return AuthorizationCodeInstalledApp(flow, receiver).authorize("user")
  }

getCredentials()を実行すると、以下のようなアプリケーション認証画面が立ち上がり、適切な権限を許可してアプリケーションにコールバック(localhost:8888)してあげます.

Aprike-sion은 は受け取った コールバックに含まれる ユーザトークンをもとに, 以後Gmail의 操作を行っていきます.

Gmail 서비스인스턴스의 작업

fun main() {
  val jsonFactory: GsonFactory = GsonFactory.getDefaultInstance()
  // Googleが提供するHTTPクライアントを生成(これは、通常のNetHttpTransportにGoogle API用のルート証明書が埋め込まれていたりするようです。)
  val httpTransport = GoogleNetHttpTransport.newTrustedTransport()

  val credential = getCredentials(httpTransport, jsonFactory, "credentials.json", "tokens")
  // Gmail serviceを作成。Gmailの各種操作には以降このserviceを使用します。
  val service: Gmail = Gmail.Builder(httpTransport, jsonFactory, credential)
    .setApplicationName("kotlin-gmail-reader")
    .build()
  readMailAndRemoveUnread(service)  // 下で実装します
}


ここで作成された service Instansを用 いて以後Gmail의 작업이 가능합니다.

そして, meールを読み込んで既読フラグを付与する프로그램を作成します.

fun readMailAndRemoveUnread(service: Gmail) {
  val user = "me"
  val targetLabel = "UNREAD" // 今回の読み込み対象のラベルは未読メールとします。INBOXやSENT,IMPORTANTなども選べます。
  val labelList = service.users().labels().list(user).execute()
  // ラベル一覧を出力してみます。
  labelList.labels.forEach(::println)
  // UNREADラベルインスタンスを取得します
  val label = labelList.labels.find { it.name == targetLabel } ?: error("$targetLabel label not found")

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

  val mailMessageList = messageIdList.messages.map { messageId ->
    // メッセージIDをもとにメッセージを取得する
    val message = service.users().messages().get(user, messageId.id).execute()

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

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

data class MailMessage(val date: String, val from: String, val subject: String, val body: String)


以上でめールの取得やmerールの既読操作などができました.
同じような操作でめールの送信なども可能になると思います.
자바의 공립 교육은 여기에서 시작됩니다.
https://developers.google.com/gmail/api/quickstart/java

좋은 웹페이지 즐겨찾기