API Python Script Pt.1

This post will be broken up into two parts. First, in this post I am going to break down a script I created where I will be reaching out to a public weather API and then scheduling this task to be sent out every day at a specific time. It is important to use the automation tools within python, because automation is one of the biggest benefits of using this language. Now I will begin to break down the script and how I set it up to become automated.

import schedule 
import time
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
import os
import requests

The first thing I have done is import the necessary modules for this script. Each one will be used and explained later, so I will not go into detail about each line right now.

email_username = os.environ.get('EMAIL_USERNAME')
email_password = os.environ.get('EMAIL_PASSWORD')

In these two lines, I am using the os.environ.get() funcion from the os module to retrieve the environment variables that I named “EMAIL_USERNAME” and “EMAIL_PASSWORD” respectively.

smtp = smtplib.SMTP('smtp.gmail.com', 587)

Here we are starting the SMTP connection to the Gmail SMTP server over port 587 so that the traffic is encrypted going over that port. Using smtplib.SMTP is a class from the smtplib module which allows us to send email messages over an SMTP server.

smtp.ehlo()

This method is used to start the interaction with the SMTP server to try and establish communication. EHLO, which stands for extended hello, reaches out to the SMTP server suggesting that this script wants to start a SMTP connection.

smtp.starttls()

This line starts the process of using TLS, an encrypted connection to communicate with the SMTP server. TLS goes through the process of a three way handshake so that way we can safely send the email over the internet.

smtp.login(email_username, email_password)

Now in this line I am authenticating the script with the SMTP server. I am doing this by providing the username and password that I defined earlier with the environmental variables. If the username and password are correct, then the SMTP server will grant access to this script allowing it to send emails.

def get_weather(api_key, location):

This line begins out first function which is created to get the weather information from the API. I am defining the “get_weather” function with parameters of “api_key” and “location”. These values will be placed in the function later when the function is called with those parameters defined.

url = f'http://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}&units=imperial'

This line within the function is the exact URL of the public API I created. It is written using an f-string

response = requests.get(url)

Here I am using the “get” method of the “requests” library. The purpose of this is to send an HTTP request from the argument “url” which is defined as a string of the actual URL

data = response.json()

This line is also using the “requests” library. This takes the variable “response” from the last line and uses JSON to convert the content into a python dictionary which is stored under the new variable “data”

return data

The variable “data” is now just returned and the “get_weather” function is finished.

def message(subject = 'Weather Report', text = '', weather_data = None):

Now the next function defined is “message”. This function has parameters of “subject”, “text”, and “weather_data”. “Subject” has a string value that will be the actual subject of the sent email. “Text” has an empty string as its value, but this will represent the body of the email. “Weather_data = None” is set this way incase for some reason there is no data passed to that variable, then the function will automatically take the value of “none”.

msg = MIMEMultipart()

Next, I will create a multipart message and define that as “msg”.

msg['Subject'] = subject

This line sets the email subject. Meaning once this function is called, whatever is passed in the “subject” parameter, will get placed as the subject of the email because of this line.

msg.attach(MIMEText(text))

When executing this line, I am attaching the contents of the “text” parameter to “msg” using the methods of the MIMEMultipart class and MIMEText class.

if weather_data:

Now, I will start an if statement which will attach the weather information.

weather_text = (
			f"Weather in {weather_data['name']}:\n"
            		f"{weather_data['weather'][0]['description'].capitalize()}.\n"
            		f"Temperature: {weather_data['main']['temp']}°F\n"
            		f"Feels Like: {weather_data['main']['feels_like']}°F\n"
            		f"Min Temperature: {weather_data['main']['temp_min']}°F\n"
            		f"Max Temperature: {weather_data['main']['temp_max']}°F\n"
            		f"Humidity: {weather_data['main']['humidity']}%\n"
            		f"Wind Speed: {weather_data['wind']['speed']} mph\n"
            	)

This is a series of f-strings that will attach various information to the email which are all listed at the beginning of each string. The defined variables in the email will be: Temperature, what the temp feels like, the minimum temperature for the day, the maximum temperature for the day, the humidity, and the wind speed. All of this will come out in Fahrenheit as well.

msg.attach(MIMEText(weather_text))

Now we will attach this information to the message if it is present.

return msg

This line returns all of the information that was attached to “msg”.

to = 'xyz@email.com'

Here we are defining the email address we will be sending this to. I put an example email address in there, so when in use an real address must be placed here.

def send_weather_email():

Next, we are creating our last function defined as “send_weather”. This function will be the last step in sending the current weather to an email.

api_key = '5464561af6ce15490f209040beca9b5d'

We will define the variable “api_key” and make it equal to the key that I created for the API we are using.

location = 'xyz,US'

Next, we will define the variable “location” with the town that we want followed by a comma and the country that town is located in.

weather_data = get_weather(api_key, location)

In this line we are calling the weather data variable and passing it the parameters which were just defined in the last two lines. This will allow the earlier “if” statement to be executed and input the proper data.

msg = message(text = 'Here is the current weather', weather_data = weather_data)

Here we are creating the message by calling the message function with specific arguments to create the email. Inside, the “text” argument will be filled in with a string and saying that “weather data” is equal to whatever info got returned from the “weather data” if statement.

smtp.sendmail(from_addr = 'xyz@gmail.com', to_addrs = to, msg = msg.as_string())

Now, we send the email by defining what email to send it from, calling the “to” address (who we are sending it to), and attaching the message as a string.

schedule.every().day.at('07:00').do(send_weather_email)

Here is the part that is a foreshadow to what part 2 will be about. In this line we are starting the process of using automation. We are scheduling this email to be sent every at 7 am.

while True:
	try:
		schedule.run_pending()
		time.sleep(1)
	except:
		print("script interrupted.")
		break
	except: Exception as e:
		print(f'Schedule error: {str(e)}')

In this block of code we are going to use a “while loop” to go through a “try-except” block to make sure our script is emailed correctly and if not then we will be shown what the issue was with sending it.

smtp.quit

Lastly, we will send a request to the SMTP server to quit the connection, it will acknowledge and terminate on their end, and then our end will officially terminate the connection. It is always good to end your SMTP connections when finished using them.

This is the end of the script I have created and the explanation of how I created and used a public weather API to be able to send an email with the weather everyday from a specific location.

Leave a Reply

Your email address will not be published. Required fields are marked *