Skip to content

Commit

Permalink
Accept Gmail Fowarding emails.
Browse files Browse the repository at this point in the history
  • Loading branch information
AndresMorelos committed Jul 7, 2021
1 parent 6639aef commit d35abd2
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 89 deletions.
3 changes: 3 additions & 0 deletions AutomationServices/EmailFowardingAccept/DISCLAIMER
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
THIS SCRAPER IS A RESEARCH BASED PROJECT, WE DON'T ENCOURAGE THE MISUSE OF THIS TOOL FOR BAD INTENTIONS.

THE DEVELOPERS ARE NOT RESPONSIBLE FOR ANY MISUSE OF THIS TOOL.
35 changes: 35 additions & 0 deletions AutomationServices/EmailFowardingAccept/scraper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { acceptInvitation } = require('./utils/acceptInvitation')



const start = async (event, context) => {
try {
const [{ destination, url }] = event.Records.map(sqsMessage => {
try {
return JSON.parse(sqsMessage.body);
} catch (e) {
console.error(e);
}
})

console.info('Starting Function')

console.info('Accepting Invitation', url)

const result = await acceptInvitation(url)

if (result === 'accepted') {
console.info(`Invitation Acepted for ${destination}`)
} else {
console.error(result)
}

} catch (error) {
console.error(error)
}

}

module.exports = {
start
}
40 changes: 40 additions & 0 deletions AutomationServices/EmailFowardingAccept/utils/acceptInvitation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const chromium = require('chrome-aws-lambda');
const puppeteer = require("puppeteer-core")

const acceptInvitation = async (url) => {

return new Promise(async (resolve, reject) => {
try {
const browser = await chromium.puppeteer.launch({
executablePath: await chromium.executablePath,
args: [...chromium.args, '--enable-features=NetworkService'],
defaultViewport: chromium.defaultViewport,
headless: chromium.headless,
});

const page = await browser.newPage();

await page.goto(url, {
waitUntil: ["networkidle0", "load", "domcontentloaded"]
});

await page.waitForTimeout(3000);

await page.click('input[type=submit]')

await page.waitForTimeout(1000);

await browser.close()

resolve('accepted')
} catch (error) {
reject(error)
}
});


}

module.exports = {
acceptInvitation
}
134 changes: 78 additions & 56 deletions AutomationServices/EmailsForwardingReader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,73 +10,27 @@ module.exports.process = async (event, context, callback) => {
try {
const mailEvent = event.Records[0].ses
const { messageId, timestamp, commonHeaders } = mailEvent.mail
let { subject, to, from } = commonHeaders
let { subject, to } = commonHeaders

const source = getEmail(to);

// Removing forward subject label
if (subject.includes('Fwd: ')) {
subject = subject.replace('Fwd: ', '')
}

// Search for bank by subject
const banks = await getBanks({})

const bank = banks.filter(bank => subject.includes(bank.subject));

if (Array.isArray(bank) && bank.length == 1) {
// Get bank information
const { filters, ignore_phrase, name: bankName } = bank[0]

// Retrieve email information
const data = await S3.getObject({
Bucket: process.env.BUCKETNAME,
Key: messageId
}).promise();

if (!([undefined, null].includes(data.Body))) {
const emailData = data.Body.toString('utf-8')
const result = await utils.readRawEmail(emailData)

for (let index = 0; index < filters.length; index++) {
const filter = filters[index];

const res = utils.search(result.html, filter.phrase, filter.parser, ignore_phrase, bankName)

if (!res) continue

const user = await getUser({ emails: source })

const prePaymentObj = {
bank: bankName,
source: res.TRANSACTION_SOURCE,
destination: res.TRANSACTION_DESTINATION,
amount: res.TRANSACTION_VALUE,
cardType: res.TRANSACTION_CARD_TYPE ? res.TRANSACTION_CARD_TYPE : 'Manual',
account: res.TRANSACTION_ACCOUNT,
category: res.TRANSACTION_TYPE,
text: res.description,
type: filter.type,
createdBy: 'AUTO_EMAIL_SERVICE',
createdAt: moment(timestamp).format(),
user: user._id,
description: res.DESCRIPTION,
isAccepted: res.TRANSACTION_TYPE === 'withdrawal' ? true : false
}
const payment = await createPayment(prePaymentObj)
break;
}
const emailData = await getEmailData(messageId)

if (emailData !== 'No Body') {
if (subject.includes('Gmail Forwarding Confirmation') > 0) {
await utils.processForwardingConfirmationGmail(emailData.html);
} else {
console.log(`No Body`)
const source = getEmail(to);
await processBankEmails(subject, source, emailData, timestamp);
}

// Deleting processed Email.
await S3.deleteObject({
Bucket: process.env.BUCKETNAME,
Key: messageId
})
}

await deleteEmailData(messageId);

} catch (error) {
console.log(error)
}
Expand All @@ -95,3 +49,71 @@ const getEmail = (from) => {
}
return source
}

const processBankEmails = async (subject, source, emailData, timestamp) => {
// Search for bank by subject
const banks = await getBanks({})

const bank = banks.filter(_bank => subject.includes(_bank.subject));

if (Array.isArray(bank) && bank.length == 1) {
// Get bank information
const { filters, ignore_phrase, name: bankName } = bank[0]


for (const filter of filters) {

const res = utils.search(emailData.html, filter.phrase, filter.parser, ignore_phrase, bankName)

if (!res) continue

const user = await getUser({ emails: source })

const prePaymentObj = {
bank: bankName,
source: res.TRANSACTION_SOURCE,
destination: res.TRANSACTION_DESTINATION,
amount: res.TRANSACTION_VALUE,
cardType: res.TRANSACTION_CARD_TYPE ? res.TRANSACTION_CARD_TYPE : 'Manual',
account: res.TRANSACTION_ACCOUNT,
category: res.TRANSACTION_TYPE,
text: res.description,
type: filter.type,
createdBy: 'AUTO_EMAIL_SERVICE',
createdAt: moment(timestamp).format(),
user: user._id,
description: res.DESCRIPTION,
isAccepted: res.TRANSACTION_TYPE === 'withdrawal' ? true : false
}
await createPayment(prePaymentObj)
break;
}



}
}

const getEmailData = async (messageId) => {
// Retrieve email information
const data = await S3.getObject({
Bucket: process.env.BUCKETNAME,
Key: messageId
}).promise();

if (!([undefined, null].includes(data.Body))) {

const emailData = data.Body.toString('utf-8')
return await utils.readRawEmail(emailData)
}

return 'No Body';
}

const deleteEmailData = async (messageId) => {
// Deleting processed Email.
await S3.deleteObject({
Bucket: process.env.BUCKETNAME,
Key: messageId
}).promise()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

module.exports.forwardingConfirmation = (text) => {
const EMAIL_DESTINATION = text.substring(0, text.indexOf(' has requested to')).trim()
const URL_CONFIRMATION = text.substring((text.indexOf('confirm the request:') + 20), text.indexOf('If you')).trim()

return {
EMAIL_DESTINATION,
URL_CONFIRMATION,
}
}
28 changes: 27 additions & 1 deletion AutomationServices/EmailsForwardingReader/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const AWS = require('aws-sdk')
const mailparser = require('mailparser').simpleParser
const _ = require('lodash')
const cheerio = require('cheerio');
Expand All @@ -10,6 +11,7 @@ const { transfersParser } = require('../parsers/bancolombia/transfers.parser')
const { transferReceptionParser } = require('../parsers/bancolombia/transferReception.parser')
const { debitWithdrawalParser } = require('../parsers/bancolombia/debitWithdrawal.parser')
const { creditCardWithdrawalParser } = require('../parsers/bancolombia/creditCardWithdrawal.parser')
const { forwardingConfirmation } = require('../parsers/gmail/FowardingConfirmation')


function isBase64(str) {
Expand All @@ -24,7 +26,7 @@ module.exports.readRawEmail = async (body) => {
textAsHtml = '<p>' + htmlToText(body).replace(/\r?\n|\r|\t/g, " ") + '</p>'
} else {
const result = await mailparser(body);
textAsHtml = result.textAsHtml ? result.textAsHtml : '<p>' + htmlToText(result.html).replace(/\r?\n|\r|\t/g, " ") + '</p>'
textAsHtml = result.textAsHtml ? result.textAsHtml : '<p>' + htmlToText(result.html).replace(/\r?\n|\r|\t/g, " ") + '</p>'
}


Expand Down Expand Up @@ -105,4 +107,28 @@ module.exports.search = (html, filter, parser, skipped_phrase = 'Bancolombia le
}
}
return undefined
}
module.exports.processForwardingConfirmationGmail = async (html) => {
const $ = cheerio.load(html)
const res = $('p')
const value = res.text().trim().replace(/=/g, '')
const result = await forwardingConfirmation(value);


const SQS = new AWS.SQS({
region: 'us-east-1',
})

try {
await SQS.sendMessage({
QueueUrl: process.env.EMAIL_FORWARDING_CONFIRMATION_SQS,
MessageBody: JSON.stringify({
destination: result.EMAIL_DESTINATION,
url: result.URL_CONFIRMATION
})
}).promise()
} catch (error) {
console.log('access denied error', JSON.stringify(error))
}

}
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,37 @@ export default {
"MONGO_SECRET": "password",
"MONGO_SET": "replicas_only",
"MONGO_USER": "FlavioAandres",
"SRV_CONFIG": false // Note the SRV CONFIG flag off
"SRV_CONFIG": false, // Note the SRV CONFIG flag off
"EMAIL_USERNAME": "[email protected]", //Only needed if you will not use the emails process with SES
"EMAIL_PASSWORD": "PASSWORD", //Only needed if you will not use the emails process with SES
"SECRET_KEY": "GENERATE_ME!",
"BODY_REQUEST": "",
"EMAIL_RECIPIENTS": ["[email protected]"],
"USER_POOL_ARN": "arn:aws:cognito-idp:us-east-1:ID:userpool/us-east-1_ID",
"TWILIO_ACCESS_TOKEN": "TOKEN",
"TWILIO_SECTRET_KEY" : "SECRET_TOKEN",
"TELEGRAM_BOT_KEY": "TELEGRAM_KEY"
}
```

```js
{
"MONGO_HOST": "mongodb+srv://USER:[email protected]/DATABASE?authSource=admin&replicaSet=REPLICASET&w=majority&readPreference=primary&appname=Personal%20Finances&retryWrites=true&ssl=true",
"MONGO_PORT": 27017,
"MONGO_SECRET": "",
"MONGO_SET": "",
"MONGO_USER": "",
"MONGO_DATABASE": "",
"SRV_CONFIG": true, //Note SRV CONFIG flag on
"EMAIL_USERNAME": "[email protected]", //Only needed if you will not use the emails process with SES
"EMAIL_PASSWORD": "PASSWORD", //Only needed if you will not use the emails process with SES
"SECRET_KEY": "GENERATE_ME!",
"BODY_REQUEST": "",
"USER_POOL_ARN": "arn:aws:cognito-idp:us-east-1:ID:userpool/us-east-1_ID",
"EMAIL_RECIPIENTS": ["[email protected]"],
"TWILIO_ACCESS_TOKEN": "TOKEN",
"TWILIO_SECTRET_KEY" : "SECRET_TOKEN",
"TELEGRAM_BOT_KEY": "TELEGRAM_KEY"
}
```

Expand Down
Loading

0 comments on commit d35abd2

Please sign in to comment.