Files
job-board-notifications/job-notifier/andela-appscript/Code.gs

174 lines
5.5 KiB
JavaScript

// Code.gs — Google Apps Script Web App
// Deploy as: Web app, Execute as "Me", Who has access: "Anyone"
// ============================================
// CONFIGURATION — change these two, then create a NEW deployment version
// ============================================
var SECRET_KEY = '5f5bd4c1751f7582f870954da60cafe2'; // e.g. output of: openssl rand -hex 16
var ALLOWED_EMAIL = 'justiceawudi@outlook.com'; // must match "Login Email" in extension Settings
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
if (!data.key || data.key !== SECRET_KEY) {
Logger.log('Unauthorized request - invalid key');
return ContentService.createTextOutput(
JSON.stringify({ error: 'Unauthorized' }),
).setMimeType(ContentService.MimeType.JSON);
}
if (data.email !== ALLOWED_EMAIL) {
Logger.log('Unauthorized request - invalid email: ' + data.email);
return ContentService.createTextOutput(
JSON.stringify({ error: 'Unauthorized email' }),
).setMimeType(ContentService.MimeType.JSON);
}
if (data.action === 'pollForLoginLink') {
var result = pollForMagicLink(data.requestId);
return ContentService.createTextOutput(
JSON.stringify(result),
).setMimeType(ContentService.MimeType.JSON);
}
return ContentService.createTextOutput(
JSON.stringify({ error: 'Unknown action' }),
).setMimeType(ContentService.MimeType.JSON);
} catch (err) {
Logger.log('Error in doPost: ' + err.message);
return ContentService.createTextOutput(
JSON.stringify({ error: err.message }),
).setMimeType(ContentService.MimeType.JSON);
}
}
// ============================================
// Poll for magic login link.
//
// No "to:" filter — the email is sent to your Outlook address and
// lands in Gmail via a forwarding rule, so its To/Delivered-To headers
// may still reference Outlook rather than Gmail. from + subject +
// newer_than + is:unread is specific enough since this only ever
// searches your own mailbox.
// ============================================
function pollForMagicLink(requestId) {
var maxAttempts = 4;
var pollInterval = 15000;
Logger.log('[' + requestId + '] Starting poll for login link...');
for (var attempt = 1; attempt <= maxAttempts; attempt++) {
Logger.log('[' + requestId + '] Attempt ' + attempt + '/' + maxAttempts);
var searchQuery =
'from:talent.andela.com subject:"Andela Login Link" newer_than:5m is:unread';
var threads = GmailApp.search(searchQuery, 0, 5);
Logger.log(
'[' + requestId + '] Found ' + threads.length + ' matching threads',
);
if (threads.length > 0) {
var allMessages = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) allMessages.push(messages[j]);
}
allMessages.sort(function (a, b) {
return b.getDate().getTime() - a.getDate().getTime();
});
var latestMessage = allMessages[0];
var body = latestMessage.getBody();
Logger.log(
'[' + requestId + '] Processing email from: ' + latestMessage.getDate(),
);
var accessAccountPattern =
/<a\s+[^>]*href=["']([^"']+)["'][^>]*>\s*Access account\s*<\/a>/i;
var match = body.match(accessAccountPattern);
if (match && match[1]) {
var link = match[1]
.replace(/&amp;/g, '&')
.replace(/&#x3D;/g, '=')
.replace(/&#61;/g, '=')
.replace(/&#x26;/g, '&');
Logger.log('[' + requestId + '] Found Access account link: ' + link);
latestMessage.markRead();
return {
success: true,
loginLink: link,
emailDate: latestMessage.getDate().toISOString(),
attempt: attempt,
};
}
Logger.log(
'[' + requestId + '] Email found but no Access account link detected',
);
}
if (attempt < maxAttempts) {
Logger.log('[' + requestId + '] Waiting ' + pollInterval / 1000 + 's...');
Utilities.sleep(pollInterval);
}
}
Logger.log(
'[' +
requestId +
'] No login link found after ' +
maxAttempts +
' attempts',
);
return {
success: false,
error: 'No login link found within timeout',
attempts: maxAttempts,
};
}
// ============================================
// Debug helpers — run manually from the Apps Script editor's function
// dropdown, then check the Executions log
// ============================================
function debugLoginEmails() {
var searchQuery =
'from:talent.andela.com subject:"Andela Login Link" newer_than:7d';
var threads = GmailApp.search(searchQuery, 0, 5);
Logger.log('Found ' + threads.length + ' emails');
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var msg = messages[j];
Logger.log('---');
Logger.log('Subject: ' + msg.getSubject());
Logger.log('From: ' + msg.getFrom());
Logger.log('To: ' + msg.getTo());
Logger.log('Date: ' + msg.getDate());
var body = msg.getBody();
var pattern =
/<a\s+[^>]*href=["']([^"']+)["'][^>]*>\s*Access account\s*<\/a>/i;
var match = body.match(pattern);
if (match) {
Logger.log('Link found: ' + match[1].substring(0, 100));
} else {
Logger.log('Access account link not found');
}
}
}
}
function testExtraction() {
var result = pollForMagicLink('test-' + Date.now());
Logger.log(JSON.stringify(result, null, 2));
}