FEATURE: new incoming email details modal

This commit is contained in:
Régis Hanol 2016-02-10 22:00:27 +01:00
parent 510f9c5bed
commit 91bb38626c
13 changed files with 285 additions and 10 deletions

View file

@ -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));
}
});

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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}}

View file

@ -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>

View file

@ -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')
});

View file

@ -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 {

View file

@ -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)

View 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

View file

@ -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"

View file

@ -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}'

View file

@ -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

View file

@ -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