gmailapi - JWalshe86/career GitHub Wiki

Integrate gmail api #42

Google Gmail API Anthony Brunson

Go to career project

xdg-open https://console.cloud.google.com/home/dashboard?project=career-429216
  • Search gmail api in the search bar
  • Click enable
  • Go back to gmail api and click on tutorials & documentation
  • Click on quickstarts and python
  • Install the Google client library for python:
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

Error: image

touch quickstart.py

Insert:

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]


def main():
  """ Shows basic usage of the Gmail API.
  Lists the user's Gmail labels.
  """
  creds = None
  # The file token.json stores the user's access and refresh tokens, and is
  # created automatically when the authorization flow completes for the first
  # time.
  if os.path.exists("token.json"):
    creds = Credentials.from_authorized_user_file("token.json", SCOPES)
  # If there are no (valid) credentials available, let the user log in.
  if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
      creds.refresh(Request())
    else:
      flow = InstalledAppFlow.from_client_secrets_file(
          "credentials.json", SCOPES
      )
      creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open("token.json", "w") as token:
      token.write(creds.to_json())

  try:
    # Call the Gmail API
    service = build("gmail", "v1", credentials=creds)
    results = service.users().labels().list(userId="me").execute()
    labels = results.get("labels", [])

    if not labels:
      print("No labels found.")
      return
    print("Labels:")
    for label in labels:
      print(label["name"])

  except HttpError as error:
    # TODO(developer) - Handle errors from gmail API.
    print(f"An error occurred: {error}")


if __name__ == "__main__":
  main()

image

838028a

To filter unread Gmail messages by excluding specific senders and categories, you update the query string in the Gmail API request. Construct the query with is:unread -category:social -category:promotions and append exclusions for specific senders using -from:{sender}. Extract email metadata like sender and subject from the headers. This approach helps you filter out unwanted emails and retrieve relevant unread messages efficiently.

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import os.path

# Define the scope and initialize other necessary variables
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]

def get_unread_emails():
    """Fetch unread emails excluding specific senders and categories."""
    creds = None
    if os.path.exists("token.json"):
        creds = Credentials.from_authorized_user_file("token.json", SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
            creds = flow.run_local_server(port=0)
        with open("token.json", "w") as token:
            token.write(creds.to_json())

    try:
        service = build("gmail", "v1", credentials=creds)

        # List of senders to exclude
        excluded_senders = [
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]"
        ]
        
        # Construct the query string
        query = "is:unread -category:social -category:promotions"
        for sender in excluded_senders:
            query += f" -from:{sender}"
        
        results = service.users().messages().list(userId="me", q=query).execute()
        messages = results.get('messages', [])

        if not messages:
            print("No unread messages found.")
            return []

        unread_emails = []
        for message in messages:
            msg = service.users().messages().get(userId="me", id=message['id']).execute()
            email_data = {
                'id': message['id'],
                'snippet': msg['snippet'],
                'sender': next(header['value'] for header in msg['payload']['headers'] if header['name'] == 'From'),
                'subject': next(header['value'] for header in msg['payload']['headers'] if header['name'] == 'Subject')
            }
            unread_emails.append(email_data)

        return unread_emails

    except HttpError as error:
        print(f"An error occurred: {error}")
        return []

if __name__ == "__main__":
    unread_emails = get_unread_emails()
    for email in unread_emails:
        print(f"Email ID: {email['id']}, From: {email['sender']}, Subject: {email['subject']}, Snippet: {email['snippet']}")

c652d311 If content of email has 'unfortunately' text turn red

unfortunately

def get_unread_emails():
    """Fetch unread emails excluding specific senders and categories."""
    creds = None
    if os.path.exists("token.json"):
        creds = Credentials.from_authorized_user_file("token.json", SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
            creds = flow.run_local_server(port=0)
        with open("token.json", "w") as token:
            token.write(creds.to_json())

    try:
        service = build("gmail", "v1", credentials=creds)

        # List of senders to exclude
        excluded_senders = [
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]",
            "[email protected]"
        ]
        
        query = "is:unread -category:social -category:promotions"
        for sender in excluded_senders:
            query += f" -from:{sender}"
        
        results = service.users().messages().list(userId="me", q=query).execute()
        messages = results.get('messages', [])

        unread_emails = []
        for message in messages:
            msg = service.users().messages().get(userId="me", id=message['id']).execute()
            snippet = msg['snippet']
            email_data = {
                'id': message['id'],
                'snippet': snippet,
                'sender': next(header['value'] for header in msg['payload']['headers'] if header['name'] == 'From'),
                'subject': next(header['value'] for header in msg['payload']['headers'] if header['name'] == 'Subject'),
                'highlight': 'highlight' if 'unfortunately' in snippet.lower() else ''
            }
            unread_emails.append(email_data)

        return unread_emails

    except HttpError as error:
        print(f"An error occurred: {error}")
        return []

Highlight Logic: For each email, the snippet (text preview) is checked for the word "unfortunately". If found, a highlight flag is set to 'highlight'

{% extends 'base.html' %}

{% block content %}

    <div class='container'>
        <!-- Display unread email subjects and senders -->
        <div class="row mb-2">
            <div class="col">
                <h2>Unread Emails</h2>
                <ul>
                    {% for email in email_subjects %}
                        <li class="{{ email.highlight }}">
                            <strong>From:</strong> {{ email.sender }}<br>
                            <strong>Subject:</strong> {{ email.subject }}<br>
                            <strong>Snippet:</strong> {{ email.snippet }}
                        </li>
                    {% empty %}
                        <li>No unread emails</li>
                    {% endfor %}
                </ul>
            </div>
        </div>
    </div>

    <style>
        .highlight {
            color: red;
        }
    </style>

{% endblock %}

Explanation Conditional Class Application: Each email list item (

  • ) receives the highlight class if the email snippet contains "unfortunately". CSS Styling: The .highlight class is defined in the <style> block to turn text color red. Summary Python: Adds a highlight flag to email data if the snippet contains specific keywords. HTML: Applies the highlight CSS class conditionally based on the flag, styling emails containing the keyword "unfortunately" with red text.

    Navbar display unread email count

    Base.html

    <!doctype html>
    {% load static %}
    <html lang="en" itemscope itemtype="http://schema.org/WebPage">
    <head>
        <meta charset="UTF-8">
        <title>Job Searches</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" type="text/css" href="{% static 'css/main.css'%}">
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
        <link rel="stylesheet" href="{% static 'css/style.css' %}">
    </head>
    <body data-bs-spy="scroll" data-bs-target=".navbar">
    
        <!-- NAVBAR -->
        <nav class="navbar2 navbar-expand-lg navbar-dark static-top">
            <div class="container">
                <button class="navbar-toggler text-white" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
                    aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarNav">
                    <ul class="navbar-nav text-lg-center">
                        <li class="nav-item">
                            <a class="nav-link text-white" href="http://127.0.0.1:8000/">Home</a>
                        </li>
                    </ul>
                    <!-- Unread Emails Count -->
                    <ul class="navbar-nav ms-auto">
                        <li class="nav-item">
                            <a class="nav-link text-white" href="{% url 'jobs_dashboard_with_emails' %}">
                                <i class="bi bi-envelope"></i> 
                                Unread Messages: <span class="badge bg-danger">{{ unread_email_count }}</span>
                            </a>
                        </li>
                    </ul>
                    <!-- Add more nav items as needed -->
                </div>
            </div>
        </nav>
        <!-- NAVBAR END -->
    
        <!-- Your page content -->
        {% block content %} {% endblock %}
    
        <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
        <script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
        <script src='{% static 'js/main.js' %}'></script>
        {% block postloadjs %} {% endblock %}
    </body>
    </html>
    

    jobs_dashboard_with_emails view

    def jobs_dashboard_with_emails(request):
        key = settings.GOOGLE_API_KEY
        eligible_locations = Jobsearch.objects.filter(place_id__isnull=False)
        locations = []
    
        for a in eligible_locations:
            data = {
                'lat': float(a.lat),
                'lng': float(a.lng),
                'name': a.name
            }
            locations.append(data)
    
        email_subjects = get_unread_emails()
        unread_email_count = len(email_subjects)  # Calculate the number of unread emails
    
        return render(request, "jobs/jobs_dashboard.html", context={
            'key': key,
            'locations': locations,
            'email_subjects': email_subjects,
            'unread_email_count': unread_email_count,  # Pass the unread email count to the template
        })
    

    HTML Template Changes: Added a new ul element in the navbar to display the unread messages count. The count is displayed using a badge element next to an envelope icon for visual indication.

    View Changes: Updated the view to calculate the number of unread emails and passed this count to the template. This count is used in the template to show how many unread messages are present.

  • ⚠️ **GitHub.com Fallback** ⚠️