Skip to content

Instantly share code, notes, and snippets.

@vict0rsch
Last active February 22, 2022 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vict0rsch/365b3e2b1aee8b634579d4001aaf103c to your computer and use it in GitHub Desktop.
Save vict0rsch/365b3e2b1aee8b634579d4001aaf103c to your computer and use it in GitHub Desktop.
Protonmail bulk "mark as read" and "move to trash" workarounds
// -----------------------
// ----- Functions -----
// -----------------------
/**
*
* @param {string} testId The string id for the element to find,
* matchec against elements' `data-testid` attribute.
* @returns HTML element
*/
const getFromTestId = (testId) => {
return Array.from(document.getElementsByTagName("button")).filter(
(element) => element.getAttribute("data-testid") === testId
)[0];
};
/**
* Get the element to select all the emails on this page.
* @returns HTML element
*/
const all = () => document.getElementById("idSelectAll");
/**
* Get the element to mark all the emails on this page as "read".
* @returns HTML element
*/
const markRead = () => getFromTestId("toolbar:read");
/**
* Get the element to move all the emails on this page to the trash.
* @returns HTML element
*/
const moveToTrash = () => getFromTestId("toolbar:movetotrash");
/**
* Get the element to go to the next page.
* @returns HTML element
*/
const next = () => getFromTestId("pagination-row:go-to-next-page");
/**
* Perform 1 iteration of selectAll-markAsRead-goToNextPage.
* @param {number} clickTime The time to wait between button clicks.
* @param {string} action The action to perform on each page: "markAsRead" or "moveToTrash".
*/
const actionOnAllAndNext =
(clickTime, action = "markAsRead") =>
() => {
// select all emails
all().click();
setTimeout(() => {
// choose element depending on the action
const element = action === "markAsRead" ? markRead() : moveToTrash();
// click element
element.click();
setTimeout(() => {
// Find button to next page
const nextElement = next();
if (nextElement && !nextElement.disabled) {
// Next page is available: click it
nextElement.click();
} else {
// No next page: stop
console.info("No more pages. Stopping.");
clearInterval(interval);
}
}, clickTime);
}, clickTime);
};
/**
*
* @param {number} clickTime The time to wait between button clicks.
* @param {number} loadingTime The time to wait for a single page to load, i.e.
* the time between calls to actionOnAllAndNext()
* @param {string} action The action to perform on each page: "markAsRead" or "moveToTrash".
* @returns interval id
*/
const start = (clickTime, loadingTime, action = "markAsRead") => {
interval = setInterval(actionOnAllAndNext(clickTime, action), loadingTime);
};
// -----------------------
// ----- Execution -----
// -----------------------
// state variable to stop the interval loop
var interval = null;
// The time to wait between button clicks.
const clickTime = 200;
// The time to wait for a single page to load, i.e. the time between calls to actionOnAllAndNext()
const loadingTime = 4000;
// The action to perform: markAsRead or moveToTrash
const action = "moveToTrash";
// Start the bulk mark as read process.
start(clickTime, loadingTime, action);
// clearInterval(interval);
@vict0rsch
Copy link
Author

vict0rsch commented Feb 22, 2022

How to use

  1. Open the console (right click + Inspect, ctrl/cmd + i)
  2. Paste the code above

Execution logic

  1. clicks the button to select all emails
  2. clicks the button to mark them as read or move them to trash (see action)
  3. clicks the button to next page
  4. wait for elements to load (loadingTime)
  5. go to 1.

Stopping

  1. The script auto-stops when there's no "Next" page
  2. Stop manually by executing clearInterval(interval) in the console
  3. Refreshing the page will also stop everything

Customization

  1. loadingTime is the time the code will wait after clicking the "Next" button. Increase if your internet is slower
  2. action is the action to perform: it can be either "markAsRead" or "moveToTrash"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment