Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] Integrated personal email gateway (GSoC'17) #7342

Merged
merged 65 commits into from
Aug 22, 2017
Merged
Changes from 1 commit
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5e8a23a
Merge pull request #2 from RocketChat/develop
pkgodara Jun 8, 2017
a39ca5e
Phase-I
pkgodara Jun 13, 2017
c5e9905
Phase-I
pkgodara Jun 13, 2017
eaac7fb
Updated email footer
pkgodara Jun 14, 2017
61aa422
IMAP implementation. Received emails & reply message
pkgodara Jun 22, 2017
d428eb0
improved email footer
pkgodara Jun 22, 2017
c818311
extract email info
pkgodara Jun 22, 2017
df8b8da
Email sending refactored.Reply-To along with Message-ID for backup
pkgodara Jun 23, 2017
8883de3
remove unwanted deps
pkgodara Jun 23, 2017
da8e0a4
Constraint IMAP info & show error
pkgodara Jun 23, 2017
585623b
fix eslint
pkgodara Jun 25, 2017
75ebf82
resolve conflict in package.json
pkgodara Jun 25, 2017
5b7c0f6
fix eslint
pkgodara Jun 25, 2017
06ba639
resolve conflict in package.json
pkgodara Jun 25, 2017
3ea675c
resolve conflict
pkgodara Jun 25, 2017
2b64c84
Merge branch 'develop' into gsoc17
pkgodara Jun 26, 2017
cc32ba4
supporting comments
pkgodara Jun 26, 2017
b4e80b7
imap info Bug fix
pkgodara Jul 2, 2017
1ab89bc
imap => direct_reply, settings
pkgodara Jul 2, 2017
b60b1f1
meteor fiber error
pkgodara Jul 2, 2017
3219105
codecy fix
pkgodara Jul 2, 2017
41aaae5
send Message
pkgodara Jul 5, 2017
8bbe667
Merge branch 'develop' into gsoc17
pkgodara Jul 5, 2017
923103e
fix eslint
pkgodara Jul 5, 2017
4128ae6
fix eslint
pkgodara Jul 5, 2017
9e7d70f
fix eslint
pkgodara Jul 5, 2017
e4bbcb7
reduce new-lines
pkgodara Jul 5, 2017
feb8287
Object oriented IMAP & Control IMAP
pkgodara Jul 8, 2017
6260033
remove extra logs
pkgodara Jul 8, 2017
0bbda5e
fix eslint
pkgodara Jul 8, 2017
beff246
Added email message info
pkgodara Jul 10, 2017
e72ba62
i18n for toastr messages
pkgodara Jul 11, 2017
d73629d
fix select values
pkgodara Jul 11, 2017
00d4810
fix settings, unnecessary lint
pkgodara Jul 13, 2017
6d08dbc
fix unnecessary lint
pkgodara Jul 13, 2017
953d1e2
intercepter start on save settings
pkgodara Jul 13, 2017
252279e
fix start
pkgodara Jul 13, 2017
b400c39
fix class definition, config, onload
pkgodara Jul 13, 2017
3048a02
fix email sending, import, callbacks
pkgodara Jul 13, 2017
03a7d1c
callbacks to arrow functions
pkgodara Jul 13, 2017
9a7dfd3
using class variables
pkgodara Jul 13, 2017
72dc724
direct callback
pkgodara Jul 13, 2017
fb58ea8
Icon to identify messages sent by emails
pkgodara Jul 14, 2017
7bc6631
Icon to identify messages sent by emails
pkgodara Jul 14, 2017
1d7f266
use common property name
pkgodara Jul 14, 2017
88e0978
POP3 implementation
pkgodara Jul 23, 2017
3350e43
fix eslint
pkgodara Jul 23, 2017
3e20101
Merge branch 'develop' into gsoc17
pkgodara Jul 23, 2017
aed2ab8
fix eslint
pkgodara Jul 23, 2017
d2296d6
fix imap to pop swap issue
pkgodara Jul 23, 2017
98a820d
allow email subject editing
pkgodara Jul 24, 2017
8ef220c
using import, export replacing globals
pkgodara Jul 30, 2017
01262cc
Merge branch 'develop' into gsoc17
pkgodara Jul 30, 2017
c93aecf
toplevel import, export
pkgodara Jul 30, 2017
aae9e98
remove older i18n translations
pkgodara Aug 2, 2017
3517ae0
Merge branch 'develop' into gsoc17
pkgodara Aug 2, 2017
747d503
Merge branch 'develop' into gsoc17
pkgodara Aug 11, 2017
3bd791a
message ts sync & email subject editing
pkgodara Aug 12, 2017
70c5c27
fix POP intercepter
pkgodara Aug 12, 2017
d1573c5
fix mention all subject editing
pkgodara Aug 12, 2017
c3a9a5e
IMAP delete emails option
pkgodara Aug 16, 2017
af1b739
settings for custom Separator
pkgodara Aug 16, 2017
9909728
replace tag if exists in email provided
pkgodara Aug 17, 2017
7724061
Merge branch 'develop' into gsoc17
pkgodara Aug 22, 2017
3646237
Merge branch 'develop' into gsoc17
rodrigok Aug 22, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
POP3 implementation
  • Loading branch information
pkgodara committed Jul 23, 2017
commit 88e0978eaa8d814e6e829ba1dfbbb6b3ff896472
5,857 changes: 4,291 additions & 1,566 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -99,11 +99,13 @@
"highlight.js": "^9.12.0",
"imap": "^0.8.19",
"jquery": "^3.2.1",
"mailparser-node4": "^2.0.2-2",
"mime-db": "^1.28.0",
"mime-type": "^3.0.5",
"moment": "^2.18.1",
"moment-timezone": "^0.5.13",
"photoswipe": "^4.1.2",
"poplib": "^0.1.7",
"prom-client": "^9.1.1",
"semver": "^5.3.0",
"toastr": "^2.1.2"
1 change: 1 addition & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
@@ -424,6 +424,7 @@
"Direct_Reply_Debug": "Debug Direct Reply",
"Direct_Reply_Debug_Description": "[Beware] Enabling Debug mode would display your 'Plain Text Password' in Admin console.",
"Direct_Reply_Enable": "Enable Direct Reply",
"Direct_Reply_Frequency": "Email Check Frequency",
"Direct_Reply_Protocol": "Direct Reply Protocol",
"Direct_Reply_Host": "Direct Reply Host",
"Direct_Reply_Port": "Direct_Reply_Port",
132 changes: 132 additions & 0 deletions packages/rocketchat-lib/server/lib/interceptDirectReplyEmails.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import IMAP from 'imap';
import POP3 from 'poplib';
import {simpleParser as simpleParser} from 'mailparser-node4';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you using this syntax, you are not changing the variable name 😄


class IMAPIntercepter {
constructor() {
@@ -97,6 +99,10 @@ class IMAPIntercepter {
email.body = bodyBuffer;
} else {
email.headers = IMAP.parseHeader(headerBuffer);

email.headers.to = email.headers.to[0];
email.headers.date = email.headers.date[0];
email.headers.from = email.headers.from[0];
}
});
});
@@ -114,4 +120,130 @@ class IMAPIntercepter {
}
}

class POP3Intercepter {
constructor() {
this.pop3 = new POP3(RocketChat.settings.get('Direct_Reply_Port'), RocketChat.settings.get('Direct_Reply_Host'), {
enabletls: !RocketChat.settings.get('Direct_Reply_IgnoreTLS'),
debug: RocketChat.settings.get('Direct_Reply_Debug') ? console.log : false
});

this.totalMsgCount = 0;
this.currentMsgCount = 0;

this.pop3.on('connect', Meteor.bindEnvironment(() => {
this.pop3.login(RocketChat.settings.get('Direct_Reply_Username'), RocketChat.settings.get('Direct_Reply_Password'));
}));

this.pop3.on('login', Meteor.bindEnvironment((status, rawData) => {
if (status) {
// run on start
this.pop3.list();
} else {
console.log('Unable to Log-in ....');
}
}));

// on getting list of all emails
this.pop3.on('list', Meteor.bindEnvironment((status, msgcount, msgnumber, data, rawdata) => {
if (status) {
if (msgcount > 0) {
this.totalMsgCount = msgcount;
this.currentMsgCount = 1;
// Retrieve email
this.pop3.retr(this.currentMsgCount);
} else {
this.pop3.quit();
}
} else {
console.log('Cannot Get Emails ....');
}
}));

// on retrieved email
this.pop3.on('retr', Meteor.bindEnvironment((status, msgnumber, data, rawdata) => {
if (status) {
// parse raw email data to JSON object
simpleParser(data, Meteor.bindEnvironment((err, mail) => {
this.initialProcess(mail);
}));

this.currentMsgCount += 1;

// delete email
this.pop3.dele(msgnumber);
} else {
console.log('Cannot Retrieve Message ....');
}
}));

// on email deleted
this.pop3.on('dele', Meteor.bindEnvironment((status, msgnumber, data, rawdata) => {
if (status) {
// get next email
if (this.currentMsgCount <= this.totalMsgCount) {
this.pop3.retr(this.currentMsgCount);
} else {
// parsed all messages.. so quitting
this.pop3.quit();
}
} else {
console.log('Cannot Delete Message ....');
}
}));

// invalid server state
this.pop3.on('invalid-state', function(cmd) {
console.log(`Invalid state. You tried calling ${ cmd }`);
});

// locked => command already running, not finished yet
this.pop3.on('locked', function(cmd) {
console.log(`Current command has not finished yet. You tried calling ${ cmd }`);
});
}

initialProcess(mail) {
const email = {
headers: {
from: mail.from.text,
to: mail.to.text,
date: mail.date,
'message-id': mail.messageId
},
body: mail.text
};

RocketChat.processDirectEmail(email);
}
}

class POP3Helper {
constructor() {
this.running = false;
}

start() {
// run every x-minutes
if (RocketChat.settings.get('Direct_Reply_Frequency')) {
this.running = Meteor.setInterval(() => {
// get new emails and process
RocketChat.POP3 = new RocketChat.POP3Intercepter();
}, RocketChat.settings.get('Direct_Reply_Frequency')*60*1000);
}
}

isActive() {
return this.running;
}

stop(callback = new Function) {
if (this.isActive()) {
Meteor.clearInterval(this.running);
}
callback();
}
}

RocketChat.IMAPIntercepter = IMAPIntercepter;
RocketChat.POP3Intercepter = POP3Intercepter;
RocketChat.POP3Helper = new POP3Helper();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets start using export and import instead of global variables? Let me know if you need help with that

6 changes: 0 additions & 6 deletions packages/rocketchat-lib/server/lib/processDirectEmail.js
Original file line number Diff line number Diff line change
@@ -91,22 +91,16 @@ RocketChat.processDirectEmail = function(email) {
// Extract/parse reply from email body
email.body = reply.parse_reply(email.body);

email.headers.to = email.headers.to[0];

// if 'To' email format is "Name <username@domain>"
if (email.headers.to.indexOf('<') >= 0 && email.headers.to.indexOf('>') >= 0) {
email.headers.to = email.headers.to.split('<')[1].split('>')[0];
}

email.headers.from = email.headers.from[0];

// if 'From' email format is "Name <username@domain>"
if (email.headers.from.indexOf('<') >= 0 && email.headers.from.indexOf('>') >= 0) {
email.headers.from = email.headers.from.split('<')[1].split('>')[0];
}

email.headers.date = email.headers.date[0];

// 'To' email format "username+messageId@domain"
if (email.headers.to.indexOf('+') >= 0) {
// Valid 'To' format
9 changes: 9 additions & 0 deletions packages/rocketchat-lib/server/startup/settings.js
Original file line number Diff line number Diff line change
@@ -524,6 +524,15 @@ RocketChat.settings.addGroup('Email', function() {
env: true,
i18nLabel: 'IgnoreTLS'
});
this.add('Direct_Reply_Frequency', 5, {
type: 'int',
env: true,
i18nLabel: 'Direct_Reply_Frequency',
enableQuery: {
_id: 'Direct_Reply_Protocol',
value: 'POP'
}
});
this.add('Direct_Reply_Username', '', {
type: 'string',
env: true,
Original file line number Diff line number Diff line change
@@ -3,25 +3,60 @@ const startEmailIntercepter = _.debounce(Meteor.bindEnvironment(function() {

if (RocketChat.settings.get('Direct_Reply_Enable') && RocketChat.settings.get('Direct_Reply_Protocol') && RocketChat.settings.get('Direct_Reply_Host') && RocketChat.settings.get('Direct_Reply_Port') && RocketChat.settings.get('Direct_Reply_Username') && RocketChat.settings.get('Direct_Reply_Password')) {
if (RocketChat.settings.get('Direct_Reply_Protocol') === 'IMAP') {
// stop already running instance
// stop already running IMAP instance
if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
console.log('Disconnecting already running instance...');
console.log('Disconnecting already running IMAP instance...');
RocketChat.IMAP.stop(Meteor.bindEnvironment(function() {
console.log('Starting new instance......');
console.log('Starting new IMAP instance......');
RocketChat.IMAP = new RocketChat.IMAPIntercepter();
RocketChat.IMAP.start();
return true;
}));
} else if (!RocketChat.IMAP || !RocketChat.IMAP.isActive()) {
console.log('Starting new instance......');
} else if (RocketChat.POP3 && RocketChat.POP3.isActive()) {
console.log('Disconnecting already running POP instance...');
RocketChat.POP3Helper.stop(Meteor.bindEnvironment(function() {
console.log('Starting new IMAP instance......');
RocketChat.IMAP = new RocketChat.IMAPIntercepter();
RocketChat.IMAP.start();
return true;
}));
} else {
console.log('Starting new IMAP instance......');
RocketChat.IMAP = new RocketChat.IMAPIntercepter();
RocketChat.IMAP.start();
return true;
}
} else if (RocketChat.settings.get('Direct_Reply_Protocol') === 'POP') {
// stop already running POP instance
if (RocketChat.POP3 && RocketChat.POP3.isActive()) {
console.log('Disconnecting already running POP instance...');
RocketChat.POP3Helper.stop(Meteor.bindEnvironment(function() {
console.log('Starting new POP instance......');
RocketChat.POP3 = new RocketChat.POP3Intercepter();
RocketChat.POP3Helper.start();
return true;
}));
} else if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
console.log('Disconnecting already running IMAP instance...');
RocketChat.IMAP.stop(Meteor.bindEnvironment(function() {
console.log('Starting new POP instance......');
RocketChat.POP3 = new RocketChat.POP3Intercepter();
RocketChat.POP3Helper.start();
return true;
}));
} else {
console.log('Starting new POP instance......');
RocketChat.POP3 = new RocketChat.POP3Intercepter();
RocketChat.POP3Helper.start();
return true;
}
}
} else if (RocketChat.IMAP && RocketChat.IMAP.isActive()) {
// stop IMAP instance
RocketChat.IMAP.stop();
} else if (RocketChat.POP3 && RocketChat.POP3.isActive()) {
// stop POP3 instance
RocketChat.POP3Helper.stop();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On else you can stop the service if it exists, then you don't need the stop button

}), 1000);