mirror of
https://github.com/codeninjasllc/discourse.git
synced 2025-02-25 07:54:11 -05:00
FEATURE: new incoming email details modal
This commit is contained in:
parent
510f9c5bed
commit
91bb38626c
13 changed files with 285 additions and 10 deletions
|
@ -0,0 +1,17 @@
|
||||||
|
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||||
|
import IncomingEmail from 'admin/models/incoming-email';
|
||||||
|
import computed from 'ember-addons/ember-computed-decorators';
|
||||||
|
import { longDate } from 'discourse/lib/formatter';
|
||||||
|
|
||||||
|
export default Ember.Controller.extend(ModalFunctionality, {
|
||||||
|
|
||||||
|
@computed("model.date")
|
||||||
|
date(d) {
|
||||||
|
return longDate(d);
|
||||||
|
},
|
||||||
|
|
||||||
|
load(id) {
|
||||||
|
return IncomingEmail.find(id).then(result => this.set("model", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
|
@ -14,6 +14,10 @@ IncomingEmail.reopenClass({
|
||||||
return this._super(attrs);
|
return this._super(attrs);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
find(id) {
|
||||||
|
return Discourse.ajax(`/admin/email/incoming/${id}.json`);
|
||||||
|
},
|
||||||
|
|
||||||
findAll(filter, offset) {
|
findAll(filter, offset) {
|
||||||
filter = filter || {};
|
filter = filter || {};
|
||||||
offset = offset || 0;
|
offset = offset || 0;
|
||||||
|
|
|
@ -5,9 +5,9 @@ export default AdminEmailIncomings.extend({
|
||||||
status: "rejected",
|
status: "rejected",
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
showRawEmail(incomingEmailId) {
|
showIncomingEmail(id) {
|
||||||
showModal('raw-email');
|
showModal('modals/admin-incoming-email');
|
||||||
this.controllerFor('raw_email').loadIncomingRawEmail(incomingEmailId);
|
this.controllerFor("modals/admin-incoming-email").load(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>{{email.subject}}</td>
|
<td>{{email.subject}}</td>
|
||||||
<td class="error">
|
<td class="error">
|
||||||
<a {{action "showRawEmail" email.id}}>{{email.error}}</a>
|
<a {{action "showIncomingEmail" email.id}}>{{email.error}}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.error"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<p>{{model.error}}</p>
|
||||||
|
{{#if model.error_description}}
|
||||||
|
<p class="error-description">{{model.error_description}}</p>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{{#if model.return_path}}
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.return_path"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{model.return_path}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.message_id"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{model.message_id}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if model.references}}
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.references"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<ul>
|
||||||
|
{{#each reference in model.references}}
|
||||||
|
<li>{{reference}}</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if model.in_reply_to}}
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.in_reply_to"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{model.in_reply_to}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.date"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{date}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.from"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{model.from}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.to"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<ul>
|
||||||
|
{{#each to in model.to}}
|
||||||
|
<li>{{to}}</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if model.cc}}
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.cc"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{model.cc}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.subject"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{model.subject}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>{{i18n "admin.email.incoming_emails.modal.body"}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{textarea value=model.body}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/modal/admin_incoming_email',
|
||||||
|
classNames: ['incoming-emails'],
|
||||||
|
title: I18n.t('admin.email.incoming_emails.modal.title')
|
||||||
|
});
|
|
@ -1798,6 +1798,40 @@ table#user-badges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.incoming-emails {
|
||||||
|
.control-group {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
.controls {
|
||||||
|
margin-left: 110px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 5px 10px;
|
||||||
|
}
|
||||||
|
.error-description {
|
||||||
|
color: #919191;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
float: left;
|
||||||
|
width: 100px;
|
||||||
|
text-align: right;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 95%;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mobile specific styles
|
// Mobile specific styles
|
||||||
// Mobile view text-inputs need some padding
|
// Mobile view text-inputs need some padding
|
||||||
.mobile-view .admin-contents {
|
.mobile-view .admin-contents {
|
||||||
|
|
|
@ -57,6 +57,13 @@ class Admin::EmailController < Admin::AdminController
|
||||||
render json: { raw_email: incoming_email.raw }
|
render json: { raw_email: incoming_email.raw }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def incoming
|
||||||
|
params.require(:id)
|
||||||
|
incoming_email = IncomingEmail.find(params[:id].to_i)
|
||||||
|
serializer = IncomingEmailDetailsSerializer.new(incoming_email, root: false)
|
||||||
|
render_json_dump(serializer)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def filter_email_logs(email_logs, params)
|
def filter_email_logs(email_logs, params)
|
||||||
|
|
82
app/serializers/incoming_email_details_serializer.rb
Normal file
82
app/serializers/incoming_email_details_serializer.rb
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
class IncomingEmailDetailsSerializer < ApplicationSerializer
|
||||||
|
|
||||||
|
attributes :error,
|
||||||
|
:error_description,
|
||||||
|
:return_path,
|
||||||
|
:date,
|
||||||
|
:from,
|
||||||
|
:to,
|
||||||
|
:cc,
|
||||||
|
:message_id,
|
||||||
|
:references,
|
||||||
|
:in_reply_to,
|
||||||
|
:subject,
|
||||||
|
:body
|
||||||
|
|
||||||
|
def initialize(incoming_email, opts)
|
||||||
|
super
|
||||||
|
@error_string = incoming_email.error
|
||||||
|
@mail = Mail.new(incoming_email.raw)
|
||||||
|
end
|
||||||
|
|
||||||
|
EMAIL_RECEIVER_ERROR_PREFIX = "Email::Receiver::".freeze
|
||||||
|
|
||||||
|
def error
|
||||||
|
@error_string
|
||||||
|
end
|
||||||
|
|
||||||
|
def error_description
|
||||||
|
error_name = @error_string.sub(EMAIL_RECEIVER_ERROR_PREFIX, "").underscore
|
||||||
|
I18n.t("emails.incoming.errors.#{error_name}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_error_description?
|
||||||
|
@error_string[EMAIL_RECEIVER_ERROR_PREFIX]
|
||||||
|
end
|
||||||
|
|
||||||
|
def return_path
|
||||||
|
@mail.return_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def date
|
||||||
|
@mail.date
|
||||||
|
end
|
||||||
|
|
||||||
|
def from
|
||||||
|
@mail.from.first.downcase
|
||||||
|
end
|
||||||
|
|
||||||
|
def to
|
||||||
|
@mail.to.map(&:downcase)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cc
|
||||||
|
@mail.cc.map(&:downcase) if @mail.cc.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def message_id
|
||||||
|
@mail.message_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def references
|
||||||
|
references = Email::Receiver.extract_references(@mail.references)
|
||||||
|
references.delete(@mail.in_reply_to) if references
|
||||||
|
references
|
||||||
|
end
|
||||||
|
|
||||||
|
def in_reply_to
|
||||||
|
@mail.in_reply_to
|
||||||
|
end
|
||||||
|
|
||||||
|
def subject
|
||||||
|
@mail.subject.presence || "(no subject)"
|
||||||
|
end
|
||||||
|
|
||||||
|
def body
|
||||||
|
body = @mail.text_part.decoded rescue nil
|
||||||
|
body ||= @mail.html_part.decoded rescue nil
|
||||||
|
body ||= @mail.body.decoded rescue nil
|
||||||
|
body.strip.truncate_words(100, escape: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -2262,6 +2262,19 @@ en:
|
||||||
subject: "Subject"
|
subject: "Subject"
|
||||||
error: "Error"
|
error: "Error"
|
||||||
none: "No incoming emails found."
|
none: "No incoming emails found."
|
||||||
|
modal:
|
||||||
|
title: "Incoming Email Details"
|
||||||
|
error: "Error"
|
||||||
|
return_path: "Return-Path"
|
||||||
|
message_id: "Message-Id"
|
||||||
|
in_reply_to: "In-Reply-To"
|
||||||
|
references: "References"
|
||||||
|
date: "Date"
|
||||||
|
from: "From"
|
||||||
|
to: "To"
|
||||||
|
cc: "Cc"
|
||||||
|
subject: "Subject"
|
||||||
|
body: "Body"
|
||||||
filters:
|
filters:
|
||||||
from_placeholder: "from@example.com"
|
from_placeholder: "from@example.com"
|
||||||
to_placeholder: "to@example.com"
|
to_placeholder: "to@example.com"
|
||||||
|
|
|
@ -50,6 +50,18 @@ en:
|
||||||
emails:
|
emails:
|
||||||
incoming:
|
incoming:
|
||||||
default_subject: "Incoming email from %{email}"
|
default_subject: "Incoming email from %{email}"
|
||||||
|
errors:
|
||||||
|
empty_email_error: "Happens when the raw mail we received was blank."
|
||||||
|
no_message_id_error: "Happens when the mail has no 'Message-Id' header."
|
||||||
|
auto_generated_email_error: "Happens when the 'precedence' header is set to: list, junk, bulk or auto_reply, or when any other header contains: auto-submitted, auto-replied or auto-generated."
|
||||||
|
no_body_detected_error: "Happens when we couldn't extract a body and there was no attachments."
|
||||||
|
inactive_user_error: "Happens when the sender is not active."
|
||||||
|
bad_destination_address: "Happens when none of the email addresses in To/Cc/Bcc fields matched a configured incoming email address."
|
||||||
|
strangers_not_allowed_error: "Happens when a user tried to create a new topic in a category they're not a member of."
|
||||||
|
insufficient_trust_level_error: "Happens when a use tried to create a new topic in a category they don't have the required trust level for."
|
||||||
|
reply_user_not_matching_error: "Happens when a reply came in from a different email address the notification was sent to."
|
||||||
|
topic_not_found_error: "Happens when a reply came in but the related topic has been deleted."
|
||||||
|
topic_closed_error: "Happens when a reply came in but the related topic has been closed."
|
||||||
|
|
||||||
errors: &errors
|
errors: &errors
|
||||||
format: ! '%{attribute} %{message}'
|
format: ! '%{attribute} %{message}'
|
||||||
|
|
|
@ -125,6 +125,7 @@ Discourse::Application.routes.draw do
|
||||||
get "received"
|
get "received"
|
||||||
get "rejected"
|
get "rejected"
|
||||||
get "/incoming/:id/raw" => "email#raw_email"
|
get "/incoming/:id/raw" => "email#raw_email"
|
||||||
|
get "/incoming/:id" => "email#incoming"
|
||||||
get "preview-digest" => "email#preview_digest"
|
get "preview-digest" => "email#preview_digest"
|
||||||
post "handle_mail"
|
post "handle_mail"
|
||||||
end
|
end
|
||||||
|
|
|
@ -215,7 +215,7 @@ module Email
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_related_post
|
def find_related_post
|
||||||
message_ids = [@mail.in_reply_to, extract_references]
|
message_ids = [@mail.in_reply_to, Email::Receiver.extract_references(@mail.references)]
|
||||||
message_ids.flatten!
|
message_ids.flatten!
|
||||||
message_ids.select!(&:present?)
|
message_ids.select!(&:present?)
|
||||||
message_ids.uniq!
|
message_ids.uniq!
|
||||||
|
@ -226,11 +226,11 @@ module Email
|
||||||
.first
|
.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_references
|
def self.extract_references(references)
|
||||||
if Array === @mail.references
|
if Array === references
|
||||||
@mail.references
|
references
|
||||||
elsif @mail.references.present?
|
elsif references.present?
|
||||||
@mail.references.split(/[\s,]/).map { |r| r.sub(/^</, "").sub(/>$/, "") }
|
references.split(/[\s,]/).map { |r| r.sub(/^</, "").sub(/>$/, "") }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue