-
Notifications
You must be signed in to change notification settings - Fork 13.1k
[NEW] Email Inboxes for Omnichannel #20101
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
Merged
Merged
Changes from all commits
Commits
Show all changes
94 commits
Select commit
Hold shift + click to select a range
1ce6de9
start email as channel, create new item on admin sidebar and email ch…
rafaelblink f8f0a27
new collection "rocketchat_email_channels" and permissions.
rafaelblink 3535a45
Implement findOne and findAll email channels
rafaelblink d8ecf38
implement POST for email channel api and list page with data.
rafaelblink f944ade
missing tooltip of send email test and translation
rafaelblink 5e1e21e
refactor on AutoCompleteDepartment to accept none label.
rafaelblink cdc0017
fix margin left from sidebar left tag.
rafaelblink 6533a25
implements createdBy and refactor required fields from POST Api.
rafaelblink d6c4a6c
Create new email channel and showing createdBy on grid
rafaelblink 2795611
email channel edit form with API implementation.
rafaelblink c1bda33
removing unused stuff
rafaelblink 062177f
Renaming file and refactoring variable names.
rafaelblink 26fc7e1
removing required fields from API.
rafaelblink cf04646
Auxiliary file only user raw models, change to the api use model.
rafaelblink 69649ec
missing translations pt-br and some new values in english
rafaelblink 39ff423
error translations and hasUnsavedChanges check on edit.
rafaelblink 48077ec
t('All') as fallback when label is not defined on Department Auto Com…
rafaelblink 8eba0d0
Implements remove button and api method.
rafaelblink 003800d
renaming Email Channel to Email Inbox.
rafaelblink 4d85896
Refactor POST API
rafaelblink 4f030e6
Email Inbox to Email Inboxes
rafaelblink 68b3a01
Fix LGTM, async methods with no "await".
rafaelblink d0ad4b0
unecessary promise await inside async method
rafaelblink f1b0174
refactor api method and variable names
rafaelblink 17a5f65
translations changes and autocomplete refactor.
rafaelblink 1b29a11
email validation with icon on field
rafaelblink 309f923
check existent email and when is edit, check different from the same.
rafaelblink 45efeb1
Merge branch 'develop' into omnichannel/email-as-channel
rodrigok c581a89
refactor email checker and some validations on server side.
rafaelblink 7109ad6
Merge remote-tracking branch 'origin/omnichannel/email-as-channel' in…
rafaelblink 195c3f4
remove unused icon import
rafaelblink dc40781
split post from get url API
rafaelblink a7827a3
Merge branch 'develop' into omnichannel/email-as-channel
renatobecker 6da4c1d
Merge branch 'develop' into omnichannel/email-as-channel
rafaelblink 349d6c5
Merge remote-tracking branch 'origin/develop' into omnichannel/email-…
rodrigok cf1ccb8
Merge branch 'omnichannel/email-as-channel' of https://github.com/Roc…
rodrigok 5eecfa8
Merge remote-tracking branch 'origin/develop' into omnichannel/email-…
rodrigok 78d9c7d
Merge remote-tracking branch 'origin/develop' into omnichannel/email-…
rodrigok 070a302
Add insertOne in BaseRaw (from Sampaio’s commit)
rodrigok 53402ac
Convert EmailInboxRaw to TS
rodrigok 68856b2
Extract IMAPInterceptor into a module
rodrigok 12db03c
Initial implementation of email fetching (missing update config while…
rodrigok bb6faa1
Pass emails to omni routing creating messages and grouping correctly
rodrigok e87175b
Move things around
rodrigok 567c016
Intercept message quotes and reply as email
rodrigok 218d444
Usei UI Kit to render the email with more info
rodrigok 10c0dcf
Update inboxes config listening to database
rodrigok f81e645
Fix types
rodrigok b41f5e6
Handle sender info
rodrigok 53cbdf3
Handle departments
rodrigok b555e72
Implement button to test email config
rodrigok 22e3514
Receive attachments from email and link to the message
rodrigok 4c03f6b
attachment actionButton with reply quoted event.
rafaelblink 9bd525d
Add msgId as optional field.
renatobecker 7ca0b53
Show Email Inbox and Subject on visitor page and hide Transcript button.
rafaelblink c01475a
Merge branch 'develop' into omnichannel/email-as-channel
rafaelblink bfe6ce1
Allow to send attachments back via email
rodrigok 8e401ac
Merge remote-tracking branch 'origin/develop' into omnichannel/email-…
rodrigok cb119de
Merge branch 'develop' into omnichannel/email-as-channel
renatobecker 57546b0
Fix LGTM(unnecessary parameter)
renatobecker 2ba95f9
Fix condition missing when replying emails.
renatobecker c77cd07
Improve code organization
rodrigok 1762e07
unarchive closed chats.
renatobecker 9cf2204
Merge branch 'develop' into omnichannel/email-as-channel
renatobecker 26463ba
Unarchive closed email channels.
renatobecker 0405048
Merge branch 'omnichannel/email-as-channel' of https://github.com/Roc…
renatobecker d8fc7d4
Improve UI of sent emails and attachments
rodrigok ad193a3
Remove unnecessary code.
renatobecker cc47eed
Merge branch 'omnichannel/email-as-channel' of https://github.com/Roc…
rodrigok 439b033
Merge branch 'omnichannel/email-as-channel' of https://github.com/Roc…
renatobecker addc9cc
Fix import.
renatobecker 2dbe320
Check if message came from email before replying.
renatobecker 26df865
Remove unnecessary file.
renatobecker 710acc5
Add translations.
renatobecker 2d4262e
Fix issue not allowing quote after taking the room
rodrigok 5c89436
Merge branch 'develop' into omnichannel/email-as-channel
renatobecker b589041
Rename "SSL TLS" to "Secure"
rafaelblink 357b437
Merge remote-tracking branch 'origin/omnichannel/email-as-channel' in…
rafaelblink cf6cd3f
Handle email reply errors.
renatobecker 19c2c31
show "active" instead "created by" on Email Inbox List.
rafaelblink 0328e02
Merge branch 'omnichannel/email-as-channel' of https://github.com/Roc…
renatobecker bae54d2
Remove all try catch unnecessary on Email Inboxes API endpoints and s…
rafaelblink de5fdce
Merge branch 'omnichannel/email-as-channel' of https://github.com/Roc…
renatobecker 1e25718
Change port to number type and some code enhancements
rafaelblink 2a1a6a2
Merge remote-tracking branch 'origin/omnichannel/email-as-channel' in…
rafaelblink 3206527
Handle promisse error when service is offline.
renatobecker 1b2348e
Fix wrong typecast.
renatobecker 925f3ba
Fix error when starting a new chat with attachments.
renatobecker 1a00a3b
Merge branch 'develop' into omnichannel/email-as-channel
renatobecker cfd257c
Merge branch 'develop' into omnichannel/email-as-channel
rafaelblink 4b330d6
Default ports (IMAP and SMTP) for new email inbox.
rafaelblink cdc0c39
Remove duplicated translation PT-BR
rafaelblink 5cb4be2
TAPi18n not working properly on server side.
rafaelblink a8f8a72
Message header translations missing
rafaelblink File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import { EmailInbox } from '../../../models/server/raw'; | ||
| import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; | ||
| import { Users } from '../../../models'; | ||
|
|
||
| export async function findEmailInboxes({ userId, query = {}, pagination: { offset, count, sort } }) { | ||
| if (!await hasPermissionAsync(userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| const cursor = EmailInbox.find(query, { | ||
| sort: sort || { name: 1 }, | ||
| skip: offset, | ||
| limit: count, | ||
| }); | ||
|
|
||
| const total = await cursor.count(); | ||
|
|
||
| const emailInboxes = await cursor.toArray(); | ||
|
|
||
| return { | ||
| emailInboxes, | ||
| count: emailInboxes.length, | ||
| offset, | ||
| total, | ||
| }; | ||
| } | ||
|
|
||
| export async function findOneEmailInbox({ userId, _id }) { | ||
| if (!await hasPermissionAsync(userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| return EmailInbox.findOneById(_id); | ||
| } | ||
|
|
||
| export async function insertOneOrUpdateEmailInbox(userId, emailInboxParams) { | ||
| const { _id, active, name, email, description, senderInfo, department, smtp, imap } = emailInboxParams; | ||
|
|
||
| if (!_id) { | ||
| emailInboxParams._createdAt = new Date(); | ||
| emailInboxParams._updatedAt = new Date(); | ||
| emailInboxParams._createdBy = Users.findOne(userId, { fields: { username: 1 } }); | ||
| return EmailInbox.insertOne(emailInboxParams); | ||
| } | ||
|
|
||
| const emailInbox = await findOneEmailInbox({ userId, id: _id }); | ||
|
|
||
| if (!emailInbox) { | ||
| throw new Error('error-invalid-email-inbox'); | ||
| } | ||
|
|
||
| const updateEmailInbox = { | ||
| $set: { | ||
| active, | ||
| name, | ||
| email, | ||
| description, | ||
| senderInfo, | ||
| smtp, | ||
| imap, | ||
| _updatedAt: new Date(), | ||
| }, | ||
| }; | ||
|
|
||
| if (department === 'All') { | ||
| updateEmailInbox.$unset = { | ||
| department: 1, | ||
| }; | ||
| } else { | ||
| updateEmailInbox.$set.department = department; | ||
| } | ||
|
|
||
| return EmailInbox.updateOne({ _id }, updateEmailInbox); | ||
| } | ||
|
|
||
| export async function findOneEmailInboxByEmail({ userId, email }) { | ||
| if (!await hasPermissionAsync(userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| return EmailInbox.findOne({ email }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| import { check, Match } from 'meteor/check'; | ||
|
|
||
| import { API } from '../api'; | ||
| import { findEmailInboxes, findOneEmailInbox, insertOneOrUpdateEmailInbox } from '../lib/emailInbox'; | ||
| import { hasPermission } from '../../../authorization/server/functions/hasPermission'; | ||
| import { EmailInbox } from '../../../models'; | ||
| import Users from '../../../models/server/models/Users'; | ||
| import { sendTestEmailToInbox } from '../../../../server/features/EmailInbox/EmailInbox_Outgoing'; | ||
|
|
||
| API.v1.addRoute('email-inbox.list', { authRequired: true }, { | ||
| get() { | ||
| const { offset, count } = this.getPaginationItems(); | ||
| const { sort, query } = this.parseJsonQuery(); | ||
| const emailInboxes = Promise.await(findEmailInboxes({ userId: this.userId, query, pagination: { offset, count, sort } })); | ||
|
|
||
| return API.v1.success(emailInboxes); | ||
| }, | ||
| }); | ||
|
|
||
| API.v1.addRoute('email-inbox', { authRequired: true }, { | ||
| post() { | ||
| if (!hasPermission(this.userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| check(this.bodyParams, { | ||
| _id: Match.Maybe(String), | ||
| name: String, | ||
| email: String, | ||
| active: Boolean, | ||
| description: Match.Maybe(String), | ||
| senderInfo: Match.Maybe(String), | ||
| department: Match.Maybe(String), | ||
| smtp: Match.ObjectIncluding({ | ||
| password: String, | ||
| port: Number, | ||
| secure: Boolean, | ||
| server: String, | ||
| username: String, | ||
| }), | ||
| imap: Match.ObjectIncluding({ | ||
| password: String, | ||
| port: Number, | ||
| secure: Boolean, | ||
| server: String, | ||
| username: String, | ||
| }), | ||
| }); | ||
|
|
||
| const emailInboxParams = this.bodyParams; | ||
|
|
||
| const { _id } = emailInboxParams; | ||
|
|
||
| Promise.await(insertOneOrUpdateEmailInbox(this.userId, emailInboxParams)); | ||
|
|
||
| return API.v1.success({ _id }); | ||
| }, | ||
| }); | ||
|
|
||
| API.v1.addRoute('email-inbox/:_id', { authRequired: true }, { | ||
| get() { | ||
| check(this.urlParams, { | ||
| _id: String, | ||
| }); | ||
|
|
||
| const { _id } = this.urlParams; | ||
| if (!_id) { throw new Error('error-invalid-param'); } | ||
| const emailInboxes = Promise.await(findOneEmailInbox({ userId: this.userId, _id })); | ||
rafaelblink marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return API.v1.success(emailInboxes); | ||
| }, | ||
| delete() { | ||
| if (!hasPermission(this.userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| check(this.urlParams, { | ||
| _id: String, | ||
| }); | ||
|
|
||
| const { _id } = this.urlParams; | ||
| if (!_id) { throw new Error('error-invalid-param'); } | ||
|
|
||
| const emailInboxes = EmailInbox.findOneById(_id); | ||
|
|
||
| if (!emailInboxes) { | ||
| return API.v1.notFound(); | ||
| } | ||
| EmailInbox.removeById(_id); | ||
| return API.v1.success({ _id }); | ||
| }, | ||
| }); | ||
|
|
||
| API.v1.addRoute('email-inbox.search', { authRequired: true }, { | ||
| get() { | ||
| if (!hasPermission(this.userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| check(this.queryParams, { | ||
| email: String, | ||
| }); | ||
|
|
||
| const { email } = this.queryParams; | ||
| const emailInbox = Promise.await(EmailInbox.findOne({ email })); | ||
|
|
||
| return API.v1.success({ emailInbox }); | ||
| }, | ||
| }); | ||
|
|
||
| API.v1.addRoute('email-inbox.send-test/:_id', { authRequired: true }, { | ||
| post() { | ||
| if (!hasPermission(this.userId, 'manage-email-inbox')) { | ||
| throw new Error('error-not-allowed'); | ||
| } | ||
| check(this.urlParams, { | ||
| _id: String, | ||
| }); | ||
|
|
||
| const { _id } = this.urlParams; | ||
| if (!_id) { throw new Error('error-invalid-param'); } | ||
| const emailInbox = Promise.await(findOneEmailInbox({ userId: this.userId, _id })); | ||
|
|
||
| if (!emailInbox) { | ||
| return API.v1.notFound(); | ||
| } | ||
|
|
||
| const user = Users.findOneById(this.userId); | ||
|
|
||
| Promise.await(sendTestEmailToInbox(emailInbox, user)); | ||
|
|
||
| return API.v1.success({ _id }); | ||
| }, | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.