Automate Birthday Wishing on Facebook Using Python + Flask + Selenium

Pragnakalp Techlabs
9 min readOct 19, 2021

People are more reliant on social media in today’s world. Facebook is one of the most used social media platforms. One of the features of Facebook is that from our friends list we can get to know the birthdays, and we can wish people on their special day. To automate this process, we can use python and selenium.

What is selenium?

Selenium is one of the free automated testing frameworks used to automate web browsers. We can use selenium with multiple languages like Java, Python, Ruby, C#, etc. Selenium Software is more than just a single tool; it’s a collection of tools, each of which caters to a certain organization’s Selenium QA testing requirements. Selenium Integrated Development Environment(IDE), Selenium Remote Control (RC), WebDriver, Selenium grid are tools of selenium.

To automate the browser here, we will use the selenium WebDriver tool. Selenium WebDriver is a web framework that permits you to execute cross-browser tests. This tool is used for automating web-based application testing to verify that it performs expectedly.

Installation and getting started

When starting a new project in python, the ideal approach is to create a new environment and work in it. This is helpful because it separates other projects and their dependencies in distinct places, which allows for easy deployment if needed, and clear package-managing.

python -m venv env_name

After running this in cmd, the folder will be created with the name of your environment name. After creating the environment activate it and now we will install our required dependencies for our project.

pip install selenium

We have to install a web driver which Selenium will utilize and will use it as browser. We can use any browser, but here we will use Chrome-Driver for Google Chrome/Chromium in this blog. You can download the web driver here.

For creating a web application, we have used Flask. For installing Flask in your virtual environment, use the below command.

pip install -U Flask

We have to install some other packages for this project . Create a requirements.txt file, copy required packages from this link and run the below command. This will install all the packages which are needed in this project.

pip install -r requirements.txt

1. Creating .env file

To store the email ID and passwords, we will create a .env file and get the login credentials from the .env file.

Make sure that the format of the .env is the same as below. Here the first two env variables i.e. EMAIL & PASSWORD are used for Facebook Login, and the last two i.e. SENDER_EMAIL & SENDER_PASSWORD are used for Email authentication, which is used in exceptionMail.py file.

2. Creating a python file for sending mail.

If any exception occurs, or if a birthday is successfully wished, or if there is no birthday today, we will send a mail to the user. To do so, use the code below.

import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import time
import os

# Defined sender email credentials in the .env file and accessing using os methods
sender_email = os.getenv("SENDER_EMAIL")
password = os.getenv("SENDER_PASSWORD")

def sendMail(receiver_email, bodyMessage):
message = MIMEMultipart("alternative")
message["Subject"] = "RE: Your automatic birthday wisher"
message["From"] = sender_email
message["To"] = receiver_email

# # Turn these into plain/html MIMEText objects
part1 = MIMEText(bodyMessage, "plain")

# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part first
message.attach(part1)

# Create secure connection with server and send email
context = ssl.create_default_context()
try:
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
time.sleep(10)
server.sendmail(
sender_email, receiver_email, message.as_string()
)
time.sleep(5)

return "Mail sent"
except Exception as e:
print(e)
return "Mail could not sent Exception is : {}".format(e)

3. Get the required terms using Inspect elements

By using the “inspect element”, we can detect that the email text box element contains the id ‘email’. The password’s id is similar, with its id being ‘pass’. We can utilize the ‘find_element_by_id’ function to get those elements in the HTML. After obtaining the text box elements, we can call the ‘send_keys(string)’ method on those boxes with a specified string.

4. Creating a Function for Login and wishing happy birthday.

Create a python file named facebookBirthday.py and copy below code in that file.

First, we will import the necessary Modules and Libraries for the python file.

import time
from exceptionMail import sendMail
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
import os

Then, we will fetch the username and password from the .env file.

# Defined login credentials in the .env file and accessing using os methods
usr = os.getenv("EMAIL")
pwd = os.getenv("PASSWORD")

Now we will create a function named facebookScript(). Which will open Facebook, logged you into it. Then it will search for birthday in the events tab. If there is any birthday then it will send him/her a message or mail will be sent to you.

First, we will have to open the login page of Facebook. After successfully login, We have to redirect to the Birthday page to get the birthday list using driver.get(“ https://www.facebook.com/events/birthdays/ “)

We can search the User card using find_elements_by_class_name(‘Class-name’) and store it in birthdaylist.

To find today’s birthday, we can take the Textbox as a reference. We can go through birthdaylist. If Textbox is present in any User card we will wish Happy birthday and store the user details into the ‘birthdayCandidate’.

To find Textbox we have used find_element_by_class_name(‘_1mf._1mj’) here.

We have put this code into the try-except block, so if Textbox isn’t present, we can display that there is no birthday for today!

For that, You can follow the code given below.

# message to store the result and birthdayCandidate to store wished user details
message= ''
birthdayCandidate = {}
response = ''
def facebookScript():
# You need to specify option arguments if you want to host this script
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("start-maximized") #open Browser in maximized mode
chrome_options.add_argument('--no-sandbox') #bypass OS security model
chrome_options.add_argument("disable-infobars") #disabling infobars
chrome_options.add_argument("--disable-extensions") #disables extensions
chrome_options.add_argument('--disable-dev-shm-usage') #overcome limited resource problems
chrome_options.add_argument("--disable-gpu") #applicable to windows os only
driver = webdriver.Chrome(options=chrome_options)
driver.maximize_window()
driver.get('https://www.facebook.com/')
print ("Opened facebook")
time.sleep(1)
try:
username_box = driver.find_element_by_id('email')
username_box.send_keys(usr)
print ("Email Id entered")
time.sleep(1)
password_box = driver.find_element_by_id('pass')
password_box.send_keys(pwd)
print ("Password entered")
login_box = driver.find_element_by_name('login')
login_box.click()
print ("Logged in")
time.sleep(5)
driver.get("https://www.facebook.com/events/birthdays/")
time.sleep(5)
# To find all the today's birthday list containers(Usercards)
birthdayslist= driver.find_elements_by_class_name("j83agx80.pybr56ya.rz4wbd8a.sj5x9vvc.a8nywdso")
try:
# Checks the Textbox of first Usercard
birthdayslist[0].find_element_by_class_name('_1mf._1mj')
candidate = 0
for b in birthdayslist:
print('Today birthday for loop')
name = b.find_element_by_tag_name("h2")
linkTag = b.find_element_by_tag_name("a")
link = linkTag.get_attribute("href")
imageTag = b.find_element_by_tag_name("image")
image = imageTag.get_attribute("xlink:href")
age = b.find_element_by_class_name(
'd2edcug0.hpfvmrgz.qv66sw1b.c1et5uql.lr9zc1uh.a8c37x1j.keod5gw0.nxhoafnm.aigsh9s9.d9wwppkn.fe6kdd0r.mau55g9w.c8b282yb.mdeji52x.sq6gx45u.a3bd9o3v.knj5qynh.m9osqain')
birthdayCandidate[candidate] = {
'name': name.text, 'link': link, 'image': image, 'age': age.text}
candidate = candidate + 1
textbox = b.find_element_by_class_name('_1mf._1mj')
wish = "Happy Birthday"
textbox.send_keys(wish)
textbox.send_keys(Keys.ENTER)
message = "Birthday wished successfully."
except Exception as e:
exp = 'There is no more birthday today.'
response = sendMail(receiver_email=usr, bodyMessage=exp)
time.sleep(5)
exp = exp + "\n\n" + response
message = exp
print(exp)
except NoSuchElementException:
exp = 'There is no such element, please contact the developer to fix this issue.'
response = sendMail(receiver_email=usr, bodyMessage=exp)
time.sleep(5)
exp = exp + "\n\n" + response
message = exp
print(exp)
except Exception as e:
print(e)
exp = 'There is no such element, please contact the developer to fix this issue.\n\n Exception is: {}'.format(e)
response = sendMail(receiver_email=usr, bodyMessage=exp)
time.sleep(5)
exp = exp + "\n\n" + response
message = exp
print(exp)
time.sleep(3)
# Closing the session
driver.close()
return message, birthdayCandidate

You can find the whole script here.

Now we will use this facebookScript() function in our flask project.

What is Flask?

Flask is a python web framework, for developing web applications.

Here, we will use Flask for running our script and Displaying user information or any other error that occurs while running the script.

The File Structure

We will create a flask app named flask_app.py. In this file, we will import the required modules and some functions of facebookBirthday.py, add the following code in flask_app.py

# A very simple Flask Hello World app for you to get started with...
from flask import Flask, render_template, redirect, session, url_for
import time
from facebookBirthday import facebookScript
import os

app = Flask(__name__)
app.secret_key = os.urandom(24)
birthdayData = {}

@app.route('/')
def hello_world():
return render_template('home.html')

@app.route('/running-script')
def running_script():
data = facebookScript()
session['messages'] = data[0]
global birthdayData
birthdayData = data[1]
return redirect(url_for('.success', messages = data[0]))

@app.route('/success')
def success():
global birthdayData
messages = session['messages']
return render_template('/success.html', messages = messages, birthday = birthdayData)
if __name__ == '__main__':
app.run(debug=True)

Now we will create two HTML files in the templates folder.

The first home.html, add the following code in it. It’s the start-up page when we run the flask app.

<!DOCTYPE html>
<html lang="en">
<head>
<link
rel="stylesheet"
type="text/css"
href="{{ url_for('static',filename='styles/home.css') }}"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins&display=swap"
rel="stylesheet"
/>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Facebook-script</title>
</head>
<body>
<div class="signupStyle">
<div id="content" style="display: none">
<center><h2>Executing the Script..............</h2></center>
</div>
<a
href="/running-script"
class="btnn"
onclick="return loader()"
id="button"
>Execute the Script</a
>
</div>
<script>
function loader() {
document.getElementById("button").style.display = "none";
document.getElementById("content").style.display = "block";
}
</script>
</body>
</html>

The second is success.html. This HTML template will display the status of the facebookScript() and print User information if there is a birthday today from your followers. Add the following code to it.

<!DOCTYPE html>
<html lang="en">
<head>
<link
rel="stylesheet"
type="text/css"
href="{{ url_for('static',filename='styles/home.css') }}"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins&display=swap"
rel="stylesheet"
/>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Success</title>
</head>
<body>
<div class="outerDiv">
<div class="BasicLayout">
<p><h1>Script Executed, {{ messages }}</h1></p>

<div id="birthCard" class="flexDir">
{% for b in birthday %}
<div class="profileCards">
<div>
<img class = "profileImage" alt="" src="{{birthday[b]['image']}}" />
</div>
<div>
<a style="text-decoration: none;" href="{{birthday[b]['link']}}" target="_blank"><div class = "profileName">{{ birthday[b]['name'] }}</div></a>
<div>{{ birthday[b]['date'] }}</div>
</div>
</div>
{% endfor %}
</div>

</div>
</div>
</body>
</html>

For a CSS file create a folder like this. -> static/styles.In styles, folder create CSS file name home.css and add following code in it.

body {
background: white;
font-family: "Poppins", sans-serif;
}

.btnn {
text-decoration: none;
outline: none;
padding: 10px 20px;
background: rgb(190, 255, 194);
color: rgb(2, 2, 2);
border: none;
border-radius: 3px;
cursor: pointer;
transition: all 0.5s;
margin: 10px auto;
width: max-content;
text-align: center;
}
.btnn:hover {
background-color: rgb(85, 255, 96);
}

.signupStyle {
display: flex;
justify-content: center;
align-content: center;
margin-top: 300px;
flex-direction: column;
}

/* For layout purpose */
.BasicLayout {
width: 1100px;
height: auto;
max-width: 75%;
padding: 30px 50px;
float: left;
margin: 0 auto;
margin-bottom: 2em;
display: flex;
flex-direction: column;
}

.outerDiv {
display: flex;
}

.profileCards {
margin-top: 25px;
display: flex;
width: 310px;
border-radius: 5px;
margin-right: 5px;
justify-content: space-around;
padding: 15px;
align-items: center;
background-color: rgb(223, 255, 225);
}

.profileImage {
width: 110px;
height: 110px;
border-radius: 50%;
}

.profileName {
font-size: 1.6em;
font-weight: 500;
color: rgb(55, 255, 68);
}

.flexDir{
display: flex;
gap: 10px;
}

To run the flask app

python flask_app.py

After running this script, copy the URL from the command prompt and open it into the browser. Click on the “Execute the script” button. The script will wish if there are any birthdays and display the information of user whom birthday is wished.

That’s it!

You can also put this script to run daily using cron job and you will be wishing Birthday wishes to your Facebook friends daily!

--

--

Pragnakalp Techlabs

Chatbots Development, Python Programming, Natural Language Processing (NLP), Machine Learning Solutions. https://www.pragnakalp.com