Mail Extension Pastebin 2

 {

  "manifest_version": 3,
  "name": "Gmail AI Assistant",
  "version": "0.4.0",
  "description": "Intelligently sorts and prioritizes your emails.",
  "permissions": [
    "storage",
    "activeTab",
    "scripting",
    "identity"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": [
        "https://mail.google.com/*"
      ],
      "js": [
        "content.js"
      ],
      "css": [
        "styles.css"
      ]
    }
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "images/icon16.png",
      "48": "images/icon48.png",
      "128": "images/icon128.png"
    }
  },
  "icons": {
    "16": "images/icon16.png",
    "48": "images/icon48.png",
    "128": "images/icon128.png"
  },
  "oauth2": {
    "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
    "scopes": [
      "https://www.googleapis.com/auth/gmail.modify"
    ]
  }
}
```javascript
// background.js

console.log("Gmail AI Assistant background script loaded.");

/**
 * Handles messages sent from the content script to perform actions.
 */
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.action === 'createFilter') {
        getAuthToken(token => {
            createFilter(token, request.data.senderEmail);
        });
    } else if (request.action === 'markPriority') {
        getAuthToken(token => {
            applyPriorityLabel(token, request.data.threadId);
        });
    }
    return true; // Indicates that the response will be sent asynchronously.
});

/**
 * Prompts the user for authentication and retrieves an OAuth 2.0 token.
 * @param {function(string)} callback - The function to call with the retrieved token.
 */
function getAuthToken(callback) {
    chrome.identity.getAuthToken({ interactive: true }, (token) => {
        if (chrome.runtime.lastError) {
            console.error(chrome.runtime.lastError.message);
            return;
        }
        callback(token);
    });
}

/**
 * Creates a new label named "Priority" if it doesn't already exist.
 * @param {string} token - The OAuth 2.0 token.
 * @returns {Promise<string>} A promise that resolves with the ID of the "Priority" label.
 */
async function getOrCreatePriorityLabelId(token) {
    // First, list existing labels to see if "Priority" already exists.
    const listResponse = await fetch('[https://gmail.googleapis.com/gmail/v1/users/me/labels](https://gmail.googleapis.com/gmail/v1/users/me/labels)', {
        headers: { 'Authorization': `Bearer ${token}` }
    });
    const listData = await listResponse.json();
    const priorityLabel = listData.labels.find(label => label.name === 'Priority');

    if (priorityLabel) {
        return priorityLabel.id; // Return existing label ID
    }

    // If it doesn't exist, create it.
    const createResponse = await fetch('[https://gmail.googleapis.com/gmail/v1/users/me/labels](https://gmail.googleapis.com/gmail/v1/users/me/labels)', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            name: 'Priority',
            labelListVisibility: 'labelShow',
            messageListVisibility: 'show'
        })
    });
    const createData = await createResponse.json();
    console.log('Created "Priority" label:', createData);
    return createData.id;
}

/**
 * Applies the "Priority" label to a specific email thread.
 * @param {string} token - The OAuth 2.0 token.
 * @param {string} threadId - The ID of the thread to label.
 */
async function applyPriorityLabel(token, threadId) {
    const labelId = await getOrCreatePriorityLabelId(token);
    const response = await fetch(`https://gmail.googleapis.com/gmail/v1/users/me/threads/${threadId}/modify`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            addLabelIds: [labelId]
        })
    });
    const data = await response.json();
    console.log('Applied Priority label to thread:', data);
}

/**
 * Creates a Gmail filter to archive emails from a specific sender.
 * @param {string} token - The OAuth 2.0 token.
 * @param {string} senderEmail - The email address of the sender to filter.
 */
async function createFilter(token, senderEmail) {
    const filter = {
        criteria: { from: senderEmail },
        action: { addLabelIds: ['TRASH'] } // Archives and moves to trash
    };

    const response = await fetch('[https://gmail.googleapis.com/gmail/v1/users/me/settings/filters](https://gmail.googleapis.com/gmail/v1/users/me/settings/filters)', {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(filter)
    });

    const data = await response.json();
    console.log('Filter created:', data);
}
```javascript
// content.js

console.log("Gmail AI Assistant content script loaded and running.");

const PROMOTION_KEYWORDS = [
    'unsubscribe', 'view in browser', 'no longer wish', 'special offer',
    'limited time', 'percent off', 'free shipping', 'view this email'
];

function processVisibleEmails() {
    const emailRows = document.querySelectorAll('tr.zA');
    if (emailRows.length === 0) return;

    chrome.storage.sync.get(['senderCounts'], (result) => {
        let counts = result.senderCounts || {};
        let updated = false;

        emailRows.forEach(row => {
            if (row.dataset.promptInjected) return;

            const senderEl = row.querySelector('.yW span[email]');
            if (senderEl) {
                const senderEmail = senderEl.getAttribute('email');
                const senderName = senderEl.getAttribute('name');

                // --- 1. Personal Conversation Logic ---
                const threadCountEl = row.querySelector('.bA4 span');
                if (threadCountEl && parseInt(threadCountEl.innerText) > 2) {
                    const threadId = row.closest('tr').getAttribute('data-thread-id');
                    if (threadId) {
                        injectPersonalConversationPrompt(row, senderName, threadId);
                        row.dataset.promptInjected = 'true';
                        return;
                    }
                }

                // --- 2. Repetitive Sender Logic ---
                if (!counts[senderEmail]) {
                    counts[senderEmail] = 0;
                }
                counts[senderEmail] += 1;
                updated = true;

                const threshold = 4;
                if (counts[senderEmail] >= threshold) {
                    injectRepetitiveEmailPrompt(row, senderName, senderEmail, counts[senderEmail]);
                    row.dataset.promptInjected = 'true';
                    return;
                }

                // --- 3. Promotional Email Logic ---
                const snippetEl = row.querySelector('.y2');
                if (snippetEl) {
                    const snippetText = snippetEl.innerText.toLowerCase();
                    if (PROMOTION_KEYWORDS.some(keyword => snippetText.includes(keyword))) {
                        injectPromotionPrompt(row, senderName);
                        row.dataset.promptInjected = 'true';
                        return;
                    }
                }
            }
        });

        if (updated) {
            chrome.storage.sync.set({ senderCounts: counts });
        }
    });
}

/**
 * Injects a prompt for personal conversations.
 * @param {HTMLElement} targetRow The email row.
 * @param {string} senderName The sender's name.
 * @param {string} threadId The ID of the email thread.
 */
function injectPersonalConversationPrompt(targetRow, senderName, threadId) {
    const promptContainer = createPromptContainer();
    const promptContent = document.createElement('div');
    promptContent.className = 'gmail-ai-prompt personal';

    promptContent.innerHTML = `
        <div class="prompt-icon">💬</div>
        <div class="prompt-text">This looks like an important conversation with <strong>${senderName}</strong>. Mark as priority?</div>
        <div class="prompt-actions">
            <button class="prompt-button yes" data-action="mark-priority">Mark Priority</button>
            <button class="prompt-button no" data-action="dismiss">Dismiss</button>
        </div>
    `;

    promptContainer.firstChild.appendChild(promptContent);
    targetRow.parentNode.insertBefore(promptContainer, targetRow);

    promptContainer.querySelector('[data-action="dismiss"]').addEventListener('click', (e) => { e.stopPropagation(); promptContainer.remove(); });
    promptContainer.querySelector('[data-action="mark-priority"]').addEventListener('click', (e) => {
        e.stopPropagation();
        chrome.runtime.sendMessage({ action: 'markPriority', data: { threadId } });
        promptContainer.remove();
    });
}

/**
 * Injects a prompt for likely promotions.
 */
function injectPromotionPrompt(targetRow, senderName) {
    const promptContainer = createPromptContainer();
    const promptContent = document.createElement('div');
    promptContent.className = 'gmail-ai-prompt promotion';

    promptContent.innerHTML = `
        <div class="prompt-icon">🛍️</div>
        <div class="prompt-text">This looks like a promotional email from <strong>${senderName}</strong>.</div>
        <div class="prompt-actions">
            <button class="prompt-button yes" data-action="unsubscribe">Unsubscribe</button>
            <button class="prompt-button no" data-action="dismiss">Dismiss</button>
        </div>
    `;

    promptContainer.firstChild.appendChild(promptContent);
    targetRow.parentNode.insertBefore(promptContainer, targetRow);

    promptContainer.querySelector('[data-action="dismiss"]').addEventListener('click', (e) => { e.stopPropagation(); promptContainer.remove(); });
    promptContainer.querySelector('[data-action="unsubscribe"]').addEventListener('click', (e) => {
        e.stopPropagation();
        alert('Automated unsubscribe coming in a future update!');
        promptContainer.remove();
    });
}

/**
 * Injects the prompt for repetitive emails.
 */
function injectRepetitiveEmailPrompt(targetRow, senderName, senderEmail, count) {
    const promptContainer = createPromptContainer();
    const promptContent = document.createElement('div');
    promptContent.className = 'gmail-ai-prompt repetitive';

    promptContent.innerHTML = `
        <div class="prompt-icon">💡</div>
        <div class="prompt-text">You've received <strong>${count}</strong> emails from <strong>${senderName}</strong>. Would you like to create a filter?</div>
        <div class="prompt-actions">
            <button class="prompt-button yes" data-action="create-filter">Create Filter</button>
            <button class="prompt-button no" data-action="dismiss">Dismiss</button>
        </div>
    `;
   
    promptContainer.firstChild.appendChild(promptContent);
    targetRow.parentNode.insertBefore(promptContainer, targetRow);

    promptContainer.querySelector('[data-action="dismiss"]').addEventListener('click', (e) => { e.stopPropagation(); promptContainer.remove(); });
    promptContainer.querySelector('[data-action="create-filter"]').addEventListener('click', (e) => {
        e.stopPropagation();
        chrome.runtime.sendMessage({ action: 'createFilter', data: { senderEmail } });
        promptContainer.remove();
    });
}

function createPromptContainer() {
    const container = document.createElement('tr');
    container.className = 'gmail-ai-prompt-container';
    const cell = document.createElement('td');
    cell.colSpan = "100%";
    container.appendChild(cell);
    return container;
}

function observeGmail() {
    const observer = new MutationObserver((mutationsList) => {
        for(const mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                setTimeout(processVisibleEmails, 500);
                return;
            }
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });
    console.log("Mutation observer is now watching the Gmail interface.");
    setTimeout(processVisibleEmails, 1000);
}

function injectInitialUI() {
    const composeButton = document.querySelector('.T-I.T-I-KE.L3');
    if (composeButton && !document.getElementById('gmail-ai-assistant-marker')) {
        const ourUI = document.createElement('div');
        ourUI.id = 'gmail-ai-assistant-marker';
        ourUI.textContent = 'AI Assistant Active';
        ourUI.style.padding = '5px 10px';
        ourUI.style.backgroundColor = '#4285F4';
        ourUI.style.color = 'white';
        ourUI.style.marginLeft = '10px';
        ourUI.style.borderRadius = '4px';
        composeButton.parentElement.appendChild(ourUI);
    }
}

const initInterval = setInterval(() => {
    if (document.querySelector('.Cp')) {
        clearInterval(initInterval);
        injectInitialUI();
        observeGmail();
    }
}, 500);
```css
/* styles.css */

/* This style ensures the container for our prompt doesn't have unwanted borders or lines from Gmail's default table styling. */
.gmail-ai-prompt-container {
    border: none !important;
    box-shadow: none !important;
}

/* The main container for our injected prompt. */
.gmail-ai-prompt {
    border-radius: 8px;
    padding: 12px 16px;
    margin: 6px 16px 6px 72px; /* Aligns with Gmail's content, leaving space for checkboxes */
    font-family: 'Google Sans', Roboto, Arial, sans-serif;
    font-size: 14px;
    display: flex;
    align-items: center;
    gap: 16px; /* Provides spacing between the icon, text, and buttons */
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}

/* --- Repetitive Email Prompt --- */
.gmail-ai-prompt.repetitive {
    background-color: #f0f4f9; /* A light, friendly blue */
    border: 1px solid #d4e3fb;
}

/* --- Promotional Email Prompt --- */
.gmail-ai-prompt.promotion {
    background-color: #fce8e6; /* A light, cautionary red/pink */
    border: 1px solid #f9d9d6;
}

.gmail-ai-prompt.promotion .prompt-text strong {
    color: #c5221f; /* A darker red for highlighted text */
}

/* --- Personal Conversation Prompt --- */
.gmail-ai-prompt.personal {
    background-color: #e6f4ea; /* A light, positive green */
    border: 1px solid #cce8d4;
}

.gmail-ai-prompt.personal .prompt-text strong {
    color: #1e8e3e; /* A darker green for highlighted text */
}

/* Styling for the lightbulb icon */
.prompt-icon {
    font-size: 20px;
}

/* The text portion of the prompt */
.prompt-text {
    flex-grow: 1; /* Allows the text to take up the remaining space */
    color: #3c4043;
}

.prompt-text strong {
    font-weight: 500;
    color: #1a73e8; /* Default highlight color */
}

/* Container for the action buttons */
.prompt-actions {
    display: flex;
    gap: 8px;
}

/* Base styling for the prompt buttons */
.prompt-button {
    background-color: transparent;
    border: 1px solid #dadce0;
    border-radius: 4px;
    padding: 8px 16px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.2s, box-shadow 0.2s;
}

/* Specific styling for the 'Yes' or confirmation button */
.prompt-button.yes {
    background-color: #1a73e8;
    color: white;
    border-color: #1a73e8;
}

.prompt-button.yes:hover {
    background-color: #287ae6;
    box-shadow: 0 1px 2px 0 rgba(60,64,67,0.3), 0 1px 3px 1px rgba(60,64,67,0.15);
}

/* --- Promotion-specific button styling --- */
.gmail-ai-prompt.promotion .prompt-button.yes {
    background-color: #d93025;
    border-color: #d93025;
}

.gmail-ai-prompt.promotion .prompt-button.yes:hover {
    background-color: #e04a40;
}

/* --- Personal-specific button styling --- */
.gmail-ai-prompt.personal .prompt-button.yes {
    background-color: #1e8e3e;
    border-color: #1e8e3e;
}

.gmail-ai-prompt.personal .prompt-button.yes:hover {
    background-color: #25a24c;
}

/* Specific styling for the 'No' or dismiss button */
.prompt-button.no {
    color: #5f6368;
}

.prompt-button.no:hover {
    background-color: #f1f3f4;
}
```html
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Gmail AI Assistant</title>
    <style>
        body {
            font-family: 'Google Sans', Roboto, Arial, sans-serif;
            width: 250px;
            padding: 10px;
            text-align: center;
        }
        h1 {
            font-size: 16px;
            color: #202124;
        }
        p {
            font-size: 14px;
            color: #5f6368;
        }
    </style>
</head>
<body>
    <h1>Gmail AI Assistant</h1>
    <p>The assistant is active and analyzing your inbox.</p>
    <p>Future settings and controls will appear here.</p>
</body>
</html>
```
// Create dummy icon files named icon16.png, icon48.png, and icon128.png
// and place them in an 'images' folder. For now, they can be any simple image.

Comments