mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 09:36:19 -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);
|
||||
},
|
||||
|
||||
find(id) {
|
||||
return Discourse.ajax(`/admin/email/incoming/${id}.json`);
|
||||
},
|
||||
|
||||
findAll(filter, offset) {
|
||||
filter = filter || {};
|
||||
offset = offset || 0;
|
||||
|
|
|
@ -5,9 +5,9 @@ export default AdminEmailIncomings.extend({
|
|||
status: "rejected",
|
||||
|
||||
actions: {
|
||||
showRawEmail(incomingEmailId) {
|
||||
showModal('raw-email');
|
||||
this.controllerFor('raw_email').loadIncomingRawEmail(incomingEmailId);
|
||||
showIncomingEmail(id) {
|
||||
showModal('modals/admin-incoming-email');
|
||||
this.controllerFor("modals/admin-incoming-email").load(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
</td>
|
||||
<td>{{email.subject}}</td>
|
||||
<td class="error">
|
||||
<a {{action "showRawEmail" email.id}}>{{email.error}}</a>
|
||||
<a {{action "showIncomingEmail" email.id}}>{{email.error}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{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 view text-inputs need some padding
|
||||
.mobile-view .admin-contents {
|
||||
|
|
|
@ -57,6 +57,13 @@ class Admin::EmailController < Admin::AdminController
|
|||
render json: { raw_email: incoming_email.raw }
|
||||
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
|
||||
|
||||
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"
|
||||
error: "Error"
|
||||
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:
|
||||
from_placeholder: "from@example.com"
|
||||
to_placeholder: "to@example.com"
|
||||
|
|
|
@ -50,6 +50,18 @@ en:
|
|||
emails:
|
||||
incoming:
|
||||
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
|
||||
format: ! '%{attribute} %{message}'
|
||||
|
|
|
@ -125,6 +125,7 @@ Discourse::Application.routes.draw do
|
|||
get "received"
|
||||
get "rejected"
|
||||
get "/incoming/:id/raw" => "email#raw_email"
|
||||
get "/incoming/:id" => "email#incoming"
|
||||
get "preview-digest" => "email#preview_digest"
|
||||
post "handle_mail"
|
||||
end
|
||||
|
|
|
@ -215,7 +215,7 @@ module Email
|
|||
end
|
||||
|
||||
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.select!(&:present?)
|
||||
message_ids.uniq!
|
||||
|
@ -226,11 +226,11 @@ module Email
|
|||
.first
|
||||
end
|
||||
|
||||
def extract_references
|
||||
if Array === @mail.references
|
||||
@mail.references
|
||||
elsif @mail.references.present?
|
||||
@mail.references.split(/[\s,]/).map { |r| r.sub(/^</, "").sub(/>$/, "") }
|
||||
def self.extract_references(references)
|
||||
if Array === references
|
||||
references
|
||||
elsif references.present?
|
||||
references.split(/[\s,]/).map { |r| r.sub(/^</, "").sub(/>$/, "") }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue