rhondamuse.com

Effortlessly Clear Unread Gmail Emails Using Scala CLI

Written on

Introduction to Scala CLI and Gmail Management

Are you feeling inundated by a sea of unread emails in your inbox? Have you ever thought about just wiping them all out and achieving that elusive inbox zero? If so, this guide is for you! Not only does it cater to those overwhelmed by emails, but it also serves as a resource for anyone interested in Scala or coding in general.

You might ask, why not simply use the Gmail interface to delete those emails? As a programmer, my curiosity led me to consider automating this process with a straightforward script. Being a long-time Scala enthusiast, I wanted to put Scala CLI to the test after coming across a blog post by Alexandru Nedelcu, who showcased its use for updating NextDNS configurations. Inspired, I decided to tackle my unread email problem using Scala CLI.

Step 1: Setting Up a Google Cloud Project

To get started, we'll utilize Google Workspace APIs alongside Scala CLI. A crucial first step is to set up a Google Cloud project. If you’re unsure how to do this, refer to this guide on project creation in Google Cloud. I decided to name my project 'google-api' as shown below:

Step 2: Activating Google Workspace API

Next, you’ll need to activate the Google Workspace APIs for your project. For detailed instructions, consult this guide on the activation process. I followed the steps and successfully enabled the APIs.

Step 3: Generating Credentials for Google Workspace APIs

The subsequent step involves creating credentials for the Google Workspace APIs. These credentials are essential for obtaining an access token from Google's authorization servers, allowing your application to communicate effectively with the APIs. You’ll need to create OAuth client ID credentials and specify the application type as 'Desktop App.' Follow this guide for a detailed walkthrough. I named my credentials "Gmail Client," as illustrated below:

Step 4: Downloading the Credentials File

After generating the credentials, download the JSON file. It's advisable to store this file securely in a temporary location. For example:

/tmp/secure/google-api-credentials.json

Step 5: Installing Scala CLI

Awesome! We’ve reached our first milestone. Now, let’s dive into Scala CLI. Developed by VirtusLab, Scala CLI is a new command-line tool that simplifies Scala interactions in various ways. It particularly shines in creating single-file scripts, eliminating the complexities of project structures and build tools like SBT. You can find installation instructions in this guide.

Step 6: Writing the Script

Once Scala CLI is installed, it’s time to write a single-file Scala script. Create a new Scala file in your working directory, naming it delete_unread_emails.scala. Inside this file, add the following script:

#!/usr/bin/env -S scala-cli

//> using dep "com.google.api-client:google-api-client:2.2.0"

//> using dep "com.google.oauth-client:google-oauth-client-jetty:1.34.1"

//> using dep "com.google.apis:google-api-services-gmail:v1-rev20220404-2.0.0"

//> using dep "com.monovore::decline::2.4.1"

//> using dep "org.typelevel::cats-core::2.10.0"

import com.google.api.client.auth.oauth2.Credential

import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp

import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver

import com.google.api.client.googleapis.auth.oauth2.{GoogleAuthorizationCodeFlow, GoogleClientSecrets}

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport

import com.google.api.client.http.javanet.NetHttpTransport

import com.google.api.client.json.gson.GsonFactory

import com.google.api.client.util.store.FileDataStoreFactory

import com.google.api.services.gmail.model.{ListMessagesResponse, Message}

import com.google.api.services.gmail.{Gmail, GmailScopes}

import com.monovore.decline.*

import java.io.{File, FileInputStream, InputStreamReader}

import scala.jdk.CollectionConverters.*

import cats.implicits.*

object GMailClient {

def apply(userId: String, credentialsFilePath: String): GMailClient =

new GMailClient(

userId,

new Gmail.Builder(

GoogleNetHttpTransport.newTrustedTransport(),

GsonFactory.getDefaultInstance,

new GoogleAuthenticator(userId, credentialsFilePath).getCredential

).build()

)

}

class GMailClient(userId: String, gmail: Gmail) {

def getUnreadMails: List[Message] = {

val response = gmail

.users()

.messages()

.list(userId)

.setMaxResults(500)

.setQ("is:unread")

def getUnreadMailsHelper(

nextPageToken: String,

unreadMails: List[Message]

): List[Message] = {

if (nextPageToken == null)

unreadMails

else {

getUnreadMailsHelper(

response.setPageToken(nextPageToken).execute().getNextPageToken,

response

.setPageToken(nextPageToken)

.execute()

.getMessages

.asScala

.toList ++ unreadMails

)

}

}

getUnreadMailsHelper(

response.execute().getNextPageToken,

response.execute().getMessages.asScala.toList

)

}

def deleteMails(mails: List[Message]): Unit = {

var mailsSize = mails.size

mails.foreach { mail =>

gmail

.users()

.messages()

.delete(userId, mail.getId)

.execute()

println(s"Deleted Mail ID: ${mail.getId}, Remaining: ${mailsSize - 1}")

mailsSize -= 1

}

}

}

class GoogleAuthenticator(userId: String, credentialsFilePath: String) {

def getCredential: Credential = {

val gsonFactory = GsonFactory.getDefaultInstance

val clientSecrets = GoogleClientSecrets.load(

gsonFactory,

new InputStreamReader(new FileInputStream(credentialsFilePath))

)

val googleAuthorizationCodeFlow =

new GoogleAuthorizationCodeFlow.Builder(

GoogleNetHttpTransport.newTrustedTransport(),

gsonFactory,

clientSecrets,

List(GmailScopes.MAIL_GOOGLE_COM).asJavaCollection

)

.setDataStoreFactory(new FileDataStoreFactory(new File("/tmp/secure/tokens")))

.setAccessType("offline")

.build()

new AuthorizationCodeInstalledApp(

googleAuthorizationCodeFlow,

new LocalServerReceiver.Builder().setPort(8888).build()

).authorize(userId)

}

}

object DeleteUnreadEmails

extends CommandApp(

name = "deleteUnreadEmails",

header = "Deletes unread emails from Gmail",

main = {

val emailIdOpt =

Opts.option[String]("email-id", help = "Email ID of the user")

val credentialsFilePathOpt =

Opts.option[String](

"credentials-file-path",

help = "Path of Google API credentials file"

)

(emailIdOpt, credentialsFilePathOpt).mapN {

(emailId, credentialsFilePath) =>

{

val gmailClient = GMailClient(emailId, credentialsFilePath)

gmailClient.deleteMails(gmailClient.getUnreadMails)

}

}

}

)

Let me highlight some key features of the script that Scala CLI supports seamlessly.

First, the shebang at the top allows for direct execution of the script, provided Scala CLI is installed. Making the file executable is simple. Just open your terminal, navigate to the working directory, and run the following command:

chmod +x delete_unread_emails.scala

Second, the script utilizes several essential libraries such as Google APIs, cats, and decline. Unlike a standard Scala project, there’s no need for a separate build file (like build.sbt) to manage dependencies. Instead, we specify them directly in the file, as shown below:

//> using dep "com.google.api-client:google-api-client:2.2.0"

//> using dep "com.google.oauth-client:google-oauth-client-jetty:1.34.1"

//> using dep "com.google.apis:google-api-services-gmail:v1-rev20220404-2.0.0"

//> using dep "com.monovore::decline::2.4.1"

//> using dep "org.typelevel::cats-core::2.10.0"

Upon executing the script, Scala CLI will automatically fetch the specified dependencies from the repository.

Third, we’ve parameterized the script using the decline library. For successful execution, users must provide two parameters:

  • email-id: The email ID linked to the Gmail account from which you want to delete unread emails.
  • credentials-file-path: The local path to your credentials JSON file.

Step 7: Running the Script

To run the script, navigate to your working directory in the terminal and execute the following command:

./delete_unread_emails.scala --email-id "[email protected]" --credentials-file-path "/tmp/secure/google-api-credentials.json"

Be sure to replace "[email protected]" with your actual Gmail ID. Running this command will redirect you to your browser, prompting you to sign in to your Google account. After selecting your account, you might encounter the following screen:

Click on 'Advanced' and proceed. You will then be asked to permit access to your emails. Click 'Continue'.

Return to your terminal, and voilà! You should see console output like this confirming that your emails have been deleted:

Deleted Mail ID: abc123, Remaining: 3

Deleted Mail ID: abc124, Remaining: 2

Deleted Mail ID: abc125, Remaining: 1

Deleted Mail ID: abc126, Remaining: 0

Here's a bonus: if you execute the script again, it won’t prompt you to sign in and grant permissions anew. This is because your access token is stored locally at /tmp/secure/tokens, enabling its reuse for future access.

Now, I no longer need to rely on bash or Python; I can simply leverage my preferred language, Scala, for all my scripting tasks.

Chapter 2: Video Resources

Video 1: How to delete all unread emails in Gmail

In this video, you'll learn a step-by-step process for deleting all unread emails in your Gmail account, making your inbox management much simpler.

Video 2: How to Delete All Unread Mails in Gmail at Once

This tutorial provides a quick guide on how to efficiently delete all unread emails in Gmail at once, ensuring an organized inbox.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Exploring AI's Role in Uncovering New Laws of Physics

This article explores how AI might discover new physical laws by analyzing motion and variables.

# Essential Considerations for Your Next Programmer Job Hunt

Discover key factors to consider when seeking your next programming job to ensure career growth and satisfaction.

The Political Ramifications of the COVID-19 Pandemic Experience

An exploration of the political impacts of the COVID-19 pandemic and the resulting societal changes in trust and behavior.