Landing your first internship in tech is a crucial step in kickstarting your career. The job market is competitive, and manually searching for internships across multiple job boards can be time-consuming and overwhelming. Why not automate this process and receive curated listings based on your preferences?
In this tutorial, we’ll build an Internship Search Agent using a Groovy script. This project will teach you how to work with APIs, parse JSON data, and automate email notifications. By the end, you’ll have a tool that fetches internship postings, filters them according to your interests, and emails them directly to you.
Understanding the Job Posting API
The Daily International Job Posting API provides real-time job listings aggregated from various sources, including company career pages, job boards, or recruitment agencies. The primary endpoint is /api/v2/jobs/search
, which allows filtering based on multiple parameters, for example:
dateCreated
: Filter jobs by date (e.g.,2025-07-17
for a specific day or2025-07
for a month).page
: Define the page number for paginated results.countryCode
: Specify the country for the job search.city
: Narrow down by city.title
: Search by job title keywords.
Furthermore, the API supports for Boolean queries, allowing us to create highly refined searches. We can use "OR" (comma-separated keywords), "AND" (encoded +
sign), and "NOT" (hyphen) operators to filter jobs based on specific criteria within various fields. The API also supports keyphrase searches using double quotes (e.g., city="New York"
), allowing us to target specific locations or requirements. By combining these operators, we can create very specific and targeted job searches.
Defining Your Internship Search Criteria
When searching for internships, start by considering the location - do you prefer local jobs, or are you open to relocating for the right opportunity? Your choice may depend on personal preferences, financial considerations, and the availability of opportunities in your desired field.
Next, define the field and tech stack that align with your skills and career goals. Are you interested in software development, data science, cybersecurity, or another area? Within your chosen field, consider the technologies you want to work with - whether it’s Java, Python, or web development.
For this tutorial, we’ll search for internships in the United States that involve software development using Groovy:
countryCode=us
(Internships in the USA)contractType=internship
(Internship positions)title=Java,Groovy,Kotlin
(Synonyms relevant to Java development)
Writing the Internship Search Agent in Groovy
Setting Up Your Groovy Environment
To easily set up your Groovy environment we'll use SDKMAN on MacOS or Linux. To do so open a terminal and run the following command:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install groovy 4.0.11
sdk use groovy 4.0.11
sdk default groovy 4.0.11
After installation, we run source "$HOME/.sdkman/bin/sdkman-init.sh"
to init SDKMAN. Once SDKMAN is ready, you can install Groovy by running sdk install groovy <version>
, replacing <version>
with your desired Groovy distribution, such as sdk install groovy 4.0.11
. You can check available versions with sdk list groovy
. To switch between installed versions, use sdk use groovy <version>
or set a default with sdk default groovy <version>
.
Writing the Groovy Script
Create a new file called InternshipSearch.groovy
and add the following code:
// InternshipSearch.groovy
@Grab(group='org.apache.httpcomponents.client5', module='httpclient5', version='5.2.1')
import org.apache.hc.client5.http.classic.methods.HttpGet
import org.apache.hc.client5.http.impl.classic.HttpClients
import org.apache.hc.core5.http.io.entity.EntityUtils
import groovy.json.JsonSlurper
// API Configuration
def API_URL = "https://daily-international-job-postings.p.rapidapi.com/api/v2/jobs/search";
def API_KEY = "YOUR_RAPIDAPI_KEY";
def EMAIL_USER = "your_email@gmail.com";
def EMAIL_PASS = "your_password";
def RECIPIENT_EMAIL = "your_email@gmail.com";
def MAX_PAGES = 1 // Limit the number of pages to fetch per query (25 per month are free)
// Define your search criteria
def queryParams = [
"countryCode=us",
"contractType=internship",
'title=java,kotlin,groovy,J2EE,JVM,JDK,JSP,"Spring Boot","Spring Framework"'
].join("&")?.replaceAll(/\+/,'%2B')?.replaceAll(/\s+/,'+')
// Function to fetch internship postings with pagination
def fetchInternships = { baseParams ->
def allInternships = []
def page = 1
def totalCount = Integer.MAX_VALUE // Initialize to a large number
println "Starting to query API using '${API_URL}?${baseParams}'"
while (allInternships.size() < totalCount && page <= MAX_PAGES) {
try {
// Create the full URL with query parameters and pagination
def url = new URL("${API_URL}?${baseParams}&page=${page}") // Access API_URL directly
// Open a connection and set headers
def connection = url.openConnection()
connection.setRequestProperty("x-rapidapi-key", API_KEY)
connection.setRequestProperty("x-rapidapi-host", new URL(API_URL).host)
// Get the response
def response = connection.inputStream.text
def jsonSlurper = new groovy.json.JsonSlurper()
def jsonResponse = jsonSlurper.parseText(response)
// Update total count and accumulate internships
totalCount = jsonResponse.totalCount
allInternships.addAll(jsonResponse.result)
println " Fetched page ${page} with ${jsonResponse?.result?.size() ?: 0} of ${totalCount} internships."
page++
} catch (Exception e) {
println "Error fetching page ${page}: ${e.message}"
break
}
}
println "Total internships fetched: ${allInternships.size()} of ${totalCount} internships"
return allInternships
}
// Function to format internships into an HTML table
def formatInternships = { internships ->
if (internships.isEmpty()) {
return "<p>No internships found.</p>"
}
def html = "<h2>Internship Opportunities</h2>\n"
html += "<table border='1'>\n"
html += " <tr><th>Date Created</th><th>Title</th><th>Company</th><th>Location</th><th>Contract Type</th><th>URL</th></tr>\n"
internships.each { internship ->
html += " <tr>"
html += " <td>${internship.dateCreated ?: 'N/A'}</td>"
html += " <td>${internship.title ?: 'N/A'}</td>"
html += " <td>${internship.company ?: 'N/A'}</td>"
html += " <td>${internship.city ?: 'N/A'}, ${internship.state ?: 'N/A'}</td>"
html += " <td>${internship.contractType ?: 'N/A'}</td>"
html += " <td><a href='${internship.jsonLD?.url ?: '#'}'>Link</a></td>"
html += " </tr>\n"
}
html += "</table>"
return html
}
// Function to send an email
def sendEmail = { to, subject, content ->
def props = new java.util.Properties()
props.put("mail.smtp.host", "smtp.gmail.com")
props.put("mail.smtp.port", "587")
props.put("mail.smtp.auth", "true")
props.put("mail.smtp.starttls.enable", "true")
// Get the session
Session session = Session.getInstance(props, new jakarta.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(EMAIL_USER, EMAIL_PASS)
}
})
// Compose the message
MimeMessage message = new MimeMessage(session)
message.setFrom(new InternetAddress(EMAIL_USER))
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to))
message.setSubject(subject)
message.setContent(content, "text/html; charset=UTF-8")
Transport.send(message)
println "Email send to: ${to}"
}
// Main script execution
try {
// Fetch internships with pagination
def internships = fetchInternships(queryParams)
// Format internships into an HTML table
def formattedInternships = formatInternships(internships)
// Send the email with the formatted internships
sendEmail(RECIPIENT_EMAIL, "New Internship Opportunities", formattedInternships)
} catch (Exception e) {
println "Error in main script execution: ${e.message}"
}
Run the script using:
groovy InternshipSearch.groovy
Automating the Internship Search
On MacOS and Linux, you can use cron
to automate the execution of groovy InternshipSearch.groovy
daily. Open a terminal and run crontab -e
to edit the cron configuration. Add the following line to schedule the script to run every day at 8:00 AM:
0 8 * * * /usr/local/bin/groovy /path/to/InternshipSearch.groovy
Replace /usr/local/bin/groovy
with the correct path to your Groovy installation (which groovy
can help find it), and /path/to/InternshipSearch.groovy
with the full path to your script. Save and exit the editor, then check if the job is active by running crontab -l
.
Conclusion
By following this tutorial, you’ve built a Groovy-based Internship Search Agent that fetches relevant postings and sends them via email. This project demonstrates how automation can streamline your job search using a Groovy script and give you an edge in securing your first tech internship!
Adapt the script to your needs by tweaking the query and refining the query parameters to match your skills and preferences, whether it's the location, contract type, or tech stack. A well-targeted query will lead you to the right opportunities.
Good luck with your internship search!