مراية لـ
https://github.com/postalserver/postal.git
تم المزامنة 2026-04-21 06:08:09 +00:00
initial commit from appmail
هذا الالتزام موجود في:
15
app/views/address_endpoints/_form.html.haml
Normal file
15
app/views/address_endpoints/_form.html.haml
Normal file
@@ -0,0 +1,15 @@
|
||||
= form_for [organization, @server, @address_endpoint], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :address, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :address, :autofocus => true, :class => 'input input--text'
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit @address_endpoint.new_record? ? "Create address endpoint" : "Save address endpoint", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
- if f.object.persisted?
|
||||
= link_to "Delete address endpoint", [organization, @server, @address_endpoint], :remote => true, :class => 'button button--danger', :method => :delete, :data => {:confirm => "Are you sure you wish to delete this HTTP endpoint?\n\r#{pluralize @address_endpoint.routes.size, 'route'} that uses this endpoint will also be deleted."}
|
||||
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
= hidden_field_tag 'return_notice', params[:return_notice]
|
||||
11
app/views/address_endpoints/edit.html.haml
Normal file
11
app/views/address_endpoints/edit.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "Address Endpoints"
|
||||
- page_title << "Edit"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :address_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
35
app/views/address_endpoints/index.html.haml
Normal file
35
app/views/address_endpoints/index.html.haml
Normal file
@@ -0,0 +1,35 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "Address Endpoints"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :address_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @address_endpoints.empty?
|
||||
.noData.noData--koala.noData--clean
|
||||
%h2.noData__title There aren't any address endpoints yet.
|
||||
%p.noData__text
|
||||
Address endpoints are e-mail addresses hosted on other platforms that you'd
|
||||
like to deliver e-mails to. Once you've created these, you can send messages
|
||||
to them by creating #{link_to 'routes', [organization, @server, :routes], :class => 'u-link'}.
|
||||
%p.noData__button
|
||||
= link_to "Add your first address endpoint", [:new, organization, @server, :address_endpoint], :class => 'button button--positive'
|
||||
|
||||
- else
|
||||
|
||||
%ul.endpointList.u-margin
|
||||
- for endpoint in @address_endpoints
|
||||
%li.endpointList__item
|
||||
= link_to [:edit, organization, @server, endpoint], :class => 'endpointList__link' do
|
||||
.endpointList__main
|
||||
%p.endpointList__name= endpoint.address
|
||||
%ul.endpointList__details
|
||||
%li.endpointList__detailItem
|
||||
- if endpoint.last_used_at
|
||||
Last used #{distance_of_time_in_words_to_now endpoint.last_used_at} ago
|
||||
- else
|
||||
Not used yet
|
||||
|
||||
%p.u-center= link_to "Add another address endpoint", [:new, organization, @server, :address_endpoint], :class => 'button button--positive'
|
||||
11
app/views/address_endpoints/new.html.haml
Normal file
11
app/views/address_endpoints/new.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "Address Endpoints"
|
||||
- page_title << "New"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :address_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
24
app/views/admin/organizations/index.html.haml
Normal file
24
app/views/admin/organizations/index.html.haml
Normal file
@@ -0,0 +1,24 @@
|
||||
- page_title << "Admin"
|
||||
- page_title << "Organizations"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious Admin →
|
||||
Organizations
|
||||
.pageContent
|
||||
%table.dataTable
|
||||
%thead
|
||||
%tr
|
||||
%td{:width => "30%"} Name
|
||||
%td{:width => "25%"} Owner
|
||||
%td{:width => "5%"} Servers
|
||||
%td{:width => "10%"} Status
|
||||
%td{:width => "15%"} Created
|
||||
%tbody
|
||||
- for organization in @organizations
|
||||
%tr
|
||||
%td= link_to organization.name, organization_root_path(organization), :class => "u-link"
|
||||
%td= organization.owner&.name || "No Owner"
|
||||
%td= organization.servers.count
|
||||
%td= organization.status
|
||||
%td= organization.created_at.to_s(:long)
|
||||
= paginate @organizations
|
||||
21
app/views/admin/stats/stats.html.haml
Normal file
21
app/views/admin/stats/stats.html.haml
Normal file
@@ -0,0 +1,21 @@
|
||||
- page_title << "Admin"
|
||||
- page_title << "Stats"
|
||||
|
||||
.pageContent
|
||||
.adminStats
|
||||
%dl.adminStats__stat
|
||||
%dt Total Messages
|
||||
%dd= number_with_delimiter @stats.total_messages
|
||||
|
||||
%dl.adminStats__stat
|
||||
%dt Total Outgoing
|
||||
%dd= number_with_delimiter @stats.total_outgoing
|
||||
|
||||
|
||||
%dl.adminStats__stat
|
||||
%dt Total Incoming
|
||||
%dd= number_with_delimiter @stats.total_incoming
|
||||
|
||||
%dl.adminStats__stat
|
||||
%dt Current Queue Size
|
||||
%dd= number_with_delimiter @queue_size
|
||||
12
app/views/app_mailer/new_user.text.erb
Normal file
12
app/views/app_mailer/new_user.text.erb
Normal file
@@ -0,0 +1,12 @@
|
||||
Hello <%= @user.first_name %>,
|
||||
|
||||
To verify your e-mail address you will be prompted to enter a code when you login to your Postal account. The code you need to enter is:
|
||||
|
||||
<%= @user.email_verification_token %>
|
||||
|
||||
Once you've done that, you'll be able to access your account.
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
12
app/views/app_mailer/password_reset.text.erb
Normal file
12
app/views/app_mailer/password_reset.text.erb
Normal file
@@ -0,0 +1,12 @@
|
||||
Hello there,
|
||||
|
||||
You (or someone pretending to be you) have requested a new password for your Postal account. To choose a new password, please click the link below and you'll be able to create a new password and login to Postal.
|
||||
|
||||
<%= Postal.host_with_protocol %>/login/reset/<%= @user.password_reset_token %><%= @return_to ? "?return_to=#{ERB::Util.url_encode(@return_to)}" : '' %>
|
||||
|
||||
If you didn't request this, you can ignore this e-mail.
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
17
app/views/app_mailer/server_send_limit_approaching.text.erb
Normal file
17
app/views/app_mailer/server_send_limit_approaching.text.erb
Normal file
@@ -0,0 +1,17 @@
|
||||
We're writing to let you know that your <%= @server.name %> mail server is approaching its send limit. All mail servers have a limit of how much e-mail they are permitted to send in a rolling 60 minute window. At present you have sent <%= @server.send_volume %> messages and have a limit of <%= @server.send_limit %>.
|
||||
|
||||
Orgaization: <%= @server.organization.name %>
|
||||
Server: <%= @server.name %>
|
||||
Send Limit: <%= @server.send_limit %>
|
||||
Current Volume: <%= @server.send_volume %>
|
||||
|
||||
When you reach your limit, any mail you send will be held in our system until it is manually unheld by you through our web interface or using our API.
|
||||
|
||||
You can view more information about this server at:
|
||||
|
||||
<%= Postal.host_with_protocol %>/org/<%= @server.organization.permalink %>/servers/<%= @server.permalink %>
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
17
app/views/app_mailer/server_send_limit_exceeded.text.erb
Normal file
17
app/views/app_mailer/server_send_limit_exceeded.text.erb
Normal file
@@ -0,0 +1,17 @@
|
||||
We're writing to let you know that your <%= @server.name %> mail server has exceeded its send limit. All mail servers have a limit of how much e-mail they are permitted to send in a rolling 60 minute window. At present you have sent <%= @server.send_volume %> messages and have a limit of <%= @server.send_limit %>.
|
||||
|
||||
Orgaization: <%= @server.organization.name %>
|
||||
Server: <%= @server.name %>
|
||||
Send Limit: <%= @server.send_limit %>
|
||||
Current Volume: <%= @server.send_volume %>
|
||||
|
||||
All messages that you send until your volume drops will now be held in our system. You will need to manually release any of these messages that you wish to send. You can do this through our web interface or using our API.
|
||||
|
||||
You can view more information about this server at:
|
||||
|
||||
<%= Postal.host_with_protocol %>/org/<%= @server.organization.permalink %>/servers/<%= @server.permalink %>
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
12
app/views/app_mailer/server_suspended.text.erb
Normal file
12
app/views/app_mailer/server_suspended.text.erb
Normal file
@@ -0,0 +1,12 @@
|
||||
Hello,
|
||||
|
||||
We're writing to inform you that, unfortunately, we have had to suspend one of your mail servers on Postal.
|
||||
|
||||
Organization: <%= @server.organization.name %>
|
||||
Server: <%= @server.name %>
|
||||
Reason: <%= @server.actual_suspension_reason %>
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
10
app/views/app_mailer/user_invite.text.erb
Normal file
10
app/views/app_mailer/user_invite.text.erb
Normal file
@@ -0,0 +1,10 @@
|
||||
You've been invited to access the <%= @organization.name %> organization on Postal.
|
||||
|
||||
To accept this invitation, please click the link below to create an account or login to an existing one.
|
||||
|
||||
<%= Postal.host_with_protocol %>/join/<%= @user_invite.uuid %>
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
14
app/views/app_mailer/verify_domain.text.erb
Normal file
14
app/views/app_mailer/verify_domain.text.erb
Normal file
@@ -0,0 +1,14 @@
|
||||
Hello there,
|
||||
|
||||
<%= @user.name %> (<%= @domain.owner.is_a?(Organization) ? @domain.owner.name : @domain.owner.organization.name %>) would like to start sending e-mail from <%= @domain.name %> using Postal. We're writing to you to request your authorization to allow this domain to be used to send e-mail through their mail server.
|
||||
|
||||
If you agree, please provide the code below to <%= @user.first_name %> who will be able to enter it into our web interface to continue.
|
||||
|
||||
<%= @domain.verification_token %>
|
||||
|
||||
If you don't agree, just ignore this e-mail.
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
14
app/views/app_mailer/verify_email_address.text.erb
Normal file
14
app/views/app_mailer/verify_email_address.text.erb
Normal file
@@ -0,0 +1,14 @@
|
||||
Hi <%= @user.first_name %>,
|
||||
|
||||
You've just changed the e-mail address on your Postal account. So that we can verify that you own the new address you've entered, we need you to enter the code below into the box shown in your web browser.
|
||||
|
||||
<%= @user.email_verification_token %>
|
||||
|
||||
If you don't have a box on your screen, just login to your Postal account to continue.
|
||||
|
||||
<%= Postal.host_with_protocol %>/login
|
||||
|
||||
Thanks,
|
||||
|
||||
<%= Postal.smtp_from_name %>
|
||||
<%= Postal.smtp_from_address %>
|
||||
39
app/views/credentials/_form.html.haml
Normal file
39
app/views/credentials/_form.html.haml
Normal file
@@ -0,0 +1,39 @@
|
||||
= form_for [organization, @server, @credential], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :type, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :type, Credential::TYPES, {}, :disabled => @credential.persisted?, :class => 'input input--select', :autofocus => @credential.new_record?
|
||||
%p.fieldSet__text
|
||||
This is the service that is associated with this credential. You'll be able to use this key to
|
||||
authenticate to this type of service only.
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :name, :autofocus => @credential.persisted?, :class => 'input input--text'
|
||||
%p.fieldSet__text
|
||||
This is a friendly name so you can identify this credential later. You can enter anything
|
||||
you want here, the more descriptive the better.
|
||||
.fieldSet__field
|
||||
= f.label :key, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :key, :readonly => true, :class => 'input input--text input--code', :placeholder => "Automatically generated", :tabindex => 1000, :value => (@credential.new_record? ? '' : @credential.key)
|
||||
%p.fieldSet__text
|
||||
This is the unique key which will be used to authenticate any requests to the API or our SMTP servers.
|
||||
It will be generated randomly and cannot be changed. If you need a new token, you can create a new one and then
|
||||
delete the old one when you're ready.
|
||||
.fieldSet__field
|
||||
= f.label :hold, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :hold, [["Process all messages", false], ["Hold messages from this credential", true]], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
You may wish to automatically hold all messages that are sent by this credential. This allows you to preview them
|
||||
for they are delivered to their recipients. This is useful for credentials for development environments.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit @credential.new_record? ? "Create credential" : "Save credential", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
- if f.object.persisted?
|
||||
= link_to "Delete credential", [organization, @server, @credential], :remote => true, :class => 'button button--danger', :method => :delete, :data => {:confirm => "Are you sure you wish to delete this credential?"}
|
||||
|
||||
8
app/views/credentials/edit.html.haml
Normal file
8
app/views/credentials/edit.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Credentials"
|
||||
- page_title << "Edit"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :credentials
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
41
app/views/credentials/index.html.haml
Normal file
41
app/views/credentials/index.html.haml
Normal file
@@ -0,0 +1,41 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Credentials"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :credentials
|
||||
.pageContent.pageContent--compact
|
||||
- if @credentials.empty?
|
||||
.noData.noData--goat.noData--clean
|
||||
%h2.noData__title This is goating out of hand. You have no credentials!
|
||||
%p.noData__text
|
||||
In order to authenticate to your mail server, you use credentials. Once
|
||||
you've added a credential, you'll have a unique token which you can use to
|
||||
authenticate against our SMTP service or our HTTP API.
|
||||
.noData__button= link_to "Add your first credential", [:new, organization, @server, :credential], :class => 'button button--positive'
|
||||
- else
|
||||
%p.pageContent__intro.u-margin
|
||||
In order to authenticate to your mail server, you use credentials. Once
|
||||
you've added a credential, you'll have a unique token which you can use to
|
||||
authenticate against our SMTP service or our HTTP API.
|
||||
%p.u-margin.pageContent__helpLink= link_to "Read more about sending outgoing e-mails", [organization, @server, :help_outgoing]
|
||||
%ul.credentialList.u-margin
|
||||
- for credential in @credentials
|
||||
%li.credentialList__item
|
||||
= link_to [:edit, organization, @server, credential], :class => 'credentialList__link' do
|
||||
.credentialList__type
|
||||
%span.label{:class => "label--credentialType-#{credential.type.underscore}"}= credential.type
|
||||
.credentialList__properties
|
||||
%p.credentialList__name
|
||||
= credential.name
|
||||
- if credential.hold?
|
||||
%span.label.label--red Holding
|
||||
%p.credentialList__key= credential.key
|
||||
.credentialList__usedAt{:class => "credentialList__usedAt--#{credential.usage_type.underscore}"}
|
||||
- if credential.last_used_at
|
||||
%p.credentialList__usedAtTitle= credential.usage_type
|
||||
%p Used #{distance_of_time_in_words_to_now credential.last_used_at} ago
|
||||
- else
|
||||
%p Not been used yet
|
||||
|
||||
%p.u-center.buttonSet.buttonSet--center
|
||||
= link_to "Add another credential", [:new, organization, @server, :credential], :class => 'button button--positive'
|
||||
8
app/views/credentials/new.html.haml
Normal file
8
app/views/credentials/new.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Credentials"
|
||||
- page_title << "Add Credential"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :credentials
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
4
app/views/domains/_nav.html.haml
Normal file
4
app/views/domains/_nav.html.haml
Normal file
@@ -0,0 +1,4 @@
|
||||
.navBar.navBar--secondary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Domains", organization_server_domains_path(organization, @server), :class => ['navBar__link', active_nav == :domains ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Tracking Domains", organization_server_track_domains_path(organization, @server), :class => ['navBar__link', active_nav == :track_domains ? 'is-active' : '']
|
||||
13
app/views/domains/_verify_with_dns.html.haml
Normal file
13
app/views/domains/_verify_with_dns.html.haml
Normal file
@@ -0,0 +1,13 @@
|
||||
%p.pageContent__intro.u-margin
|
||||
To verify your ownership of <b>#{@domain.name}</b>, you need to add a TXT record to this domain.
|
||||
The TXT record should include the value shown below.
|
||||
|
||||
%pre.codeBlock.u-margin= @domain.dns_verification_string
|
||||
|
||||
%p.pageContent__intro.u-margin
|
||||
Once you've added this, click the button below to verify the presence of this record and
|
||||
verify your domain.
|
||||
|
||||
.buttonSet
|
||||
= link_to "Verify TXT record", [:verify, organization, @server, @domain], :remote => true, :method => :post, :class => "button"
|
||||
= link_to "Back to domain list", [organization, @server, :domains], :class => "button button--neutral"
|
||||
25
app/views/domains/_verify_with_email.html.haml
Normal file
25
app/views/domains/_verify_with_email.html.haml
Normal file
@@ -0,0 +1,25 @@
|
||||
- if params[:email_address]
|
||||
%p.pageContent__intro.u-margin
|
||||
We've sent an email to <b>#{params[:email_address]}</b>. Please check your e-mail and enter
|
||||
the code you've been sent in the box below.
|
||||
= form_tag request.fullpath, :remote => true do
|
||||
= hidden_field_tag 'email_address', params[:email_address]
|
||||
%p.u-margin
|
||||
= text_field_tag "code", params[:code], :autofocus => true, :class => 'input input--text js-multibox'
|
||||
.buttonSet
|
||||
= submit_tag "Verify this domain", :class => 'button js-form-submit'
|
||||
= link_to "Back to domain list", [organization, @server, :domains], :class => "button button--neutral"
|
||||
|
||||
|
||||
- else
|
||||
%p.pageContent__intro.u-margin
|
||||
To verify your ownership of <b>#{@domain.name}</b> by e-mail, choose an e-mail address from the list
|
||||
below. We'll then send you an email with a code which you'll need to enter below.
|
||||
|
||||
= form_tag request.fullpath, :remote => true do
|
||||
%p.u-margin
|
||||
= select_tag "email_address", options_for_select(@domain.verification_email_addresses), :class => 'input input--select', :autofocus => true
|
||||
%p.buttonSet
|
||||
= submit_tag "Continue", :class => 'button'
|
||||
= link_to "Back to domain list", [organization, @server, :domains], :class => "button button--neutral"
|
||||
|
||||
74
app/views/domains/index.html.haml
Normal file
74
app/views/domains/index.html.haml
Normal file
@@ -0,0 +1,74 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << "Domains"
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'nav', :active_nav => :domains
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
Domains
|
||||
= render 'organizations/nav', :active_nav => :domains
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @domains.empty?
|
||||
.noData.noData--penguin.noData--clean
|
||||
%h2.noData__title Brrrr. It's chilly in here without any domains.
|
||||
%p.noData__text
|
||||
To send & receive messages you need to add & verify the domain you wish to send/receive
|
||||
messages to/from. Add your domain below to get started.
|
||||
%p.noData__button= link_to "Add your first domain", [:new, organization, @server, :domain], :class => "button button--positive"
|
||||
|
||||
- else
|
||||
%ul.domainList.u-margin
|
||||
- for domain in @domains
|
||||
%li.domainList__item
|
||||
.domainList__details
|
||||
%p.domainList__name
|
||||
= link_to domain.name, [:setup, organization, @server, domain]
|
||||
- if domain.use_for_any?
|
||||
%span.label.label--blue Any
|
||||
%ul.domainList__checks
|
||||
- if domain.spf_status == 'OK'
|
||||
%li.domainList__check.domainList__check--ok SPF
|
||||
- elsif domain.spf_status.nil?
|
||||
- else
|
||||
%li.domainList__check.domainList__check--warning{:title => domain.spf_error}= link_to "SPF", [:setup, organization, @server, domain]
|
||||
|
||||
- if domain.dkim_status == 'OK'
|
||||
%li.domainList__check.domainList__check--ok DKIM
|
||||
- elsif domain.dkim_status.nil?
|
||||
- else
|
||||
%li.domainList__check.domainList__check--warning{:title => domain.dkim_error}= link_to "DKIM", [:setup, organization, @server, domain]
|
||||
|
||||
- if domain.mx_status == 'OK'
|
||||
%li.domainList__check.domainList__check--ok MX
|
||||
- elsif domain.mx_status.nil?
|
||||
- else
|
||||
%li.domainList__check.domainList__check--neutral-cross{:title => domain.mx_error}= link_to "MX", [:setup, organization, @server, domain]
|
||||
|
||||
- if domain.return_path_status == 'OK'
|
||||
%li.domainList__check.domainList__check--ok Return Path
|
||||
- elsif domain.return_path_status.nil?
|
||||
- elsif domain.return_path_status == 'Missing'
|
||||
%li.domainList__check.domainList__check--neutral{:title => domain.return_path_error}= link_to "Return Path", [:setup, organization, @server, domain]
|
||||
- else
|
||||
%li.domainList__check.domainList__check--warning{:title => domain.return_path_error}= link_to "Return Path", [:setup, organization, @server, domain]
|
||||
|
||||
%ul.domainList__properties
|
||||
- if domain.verified?
|
||||
%li.domainList__verificationTime Verified on #{domain.verified_at.to_s(:long)}
|
||||
- else
|
||||
%li= link_to "Verify this domain", [:verify, organization, @server, domain], :class => "domainList__verificationLink"
|
||||
%li.domainList__links
|
||||
- if domain.verified?
|
||||
= link_to "DNS setup", [:setup, organization, @server, domain]
|
||||
= link_to "Delete", [organization, @server, domain], :remote => :delete, :method => :delete, :data => {:confirm => "Are you sure you wish to remove this domain?", :disable_with => "Deleting..."}, :class => 'domainList__delete'
|
||||
|
||||
%p.u-center= link_to "Add new domain", [:new, organization, @server, :domain], :class => "button button--positive"
|
||||
35
app/views/domains/new.html.haml
Normal file
35
app/views/domains/new.html.haml
Normal file
@@ -0,0 +1,35 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << "Add Domain"
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'nav', :active_nav => :domains
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→ Domains →
|
||||
Add new domain
|
||||
= render 'organizations/nav', :active_nav => :domains
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
= form_for [organization, @server, @domain], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :name, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :verification_method, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :verification_method, Domain::VERIFICATION_METHODS, {}, :class => 'input input--select'
|
||||
.fieldSet__text
|
||||
Choose how you'd like to verify your ownership of this domain. If you choose <b>E-Mail</b> we can send you
|
||||
an email with a code whcih you'll need to enter - you can choose from a set of pre-defined addresses for
|
||||
the domain. Using <b>DNS</b> you'll need to add a TXT record on this domain using your DNS provider.
|
||||
|
||||
.fieldSetSubmit
|
||||
= f.submit :class => "button button--positive js-form-submit"
|
||||
104
app/views/domains/setup.html.haml
Normal file
104
app/views/domains/setup.html.haml
Normal file
@@ -0,0 +1,104 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << @domain.name
|
||||
- page_title << "DNS Setup"
|
||||
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'nav', :active_nav => :domains
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→ Domains →
|
||||
= @domain.name
|
||||
= render 'organizations/nav', :active_nav => :domains
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
%h2.pageContent__title DNS Setup for #{@domain.name}
|
||||
%p.pageContent__intro.u-margin
|
||||
Follow the instructions below to configure SPF & DKIM records for this domain.
|
||||
We highly recommend that you do this to ensure your messages are delivered
|
||||
correctly and quickly.
|
||||
|
||||
.u-margin.buttonSet
|
||||
= link_to "Check my records are correct", [:check, organization, @server, @domain], :remote => true, :method => :post, :class => 'button'
|
||||
= link_to "Back to domain list", [organization, @server, :domains], :class => 'button button--neutral'
|
||||
- if @domain.dns_checked_at
|
||||
%p.u-margin We last checked the validity of your DNS records #{distance_of_time_in_words_to_now @domain.dns_checked_at} ago.
|
||||
|
||||
%h3.pageContent__subTitle SPF Record
|
||||
- if @domain.spf_status == 'OK'
|
||||
%p.pageContent__text.u-green.u-bold
|
||||
%span.label.label--green Good
|
||||
Your SPF record looks good!
|
||||
- elsif !@domain.spf_status.nil?
|
||||
%p.pageContent__text.u-orange.u-bold
|
||||
%span.label.label--orange Warning
|
||||
= @domain.spf_error
|
||||
|
||||
%p.pageContent__text
|
||||
You need to add a TXT record at the apex/root of your domain (@) with the following
|
||||
content. If you already send mail from another service, you may just need to add
|
||||
<b>include:#{Postal.config.dns.spf_include}</b> to your existing record.
|
||||
%pre.codeBlock.u-margin= @domain.spf_record
|
||||
|
||||
%h3.pageContent__subTitle DKIM Record
|
||||
- if @domain.dkim_status == 'OK'
|
||||
%p.pageContent__text.u-green.u-bold
|
||||
%span.label.label--green Good
|
||||
Your DKIM record looks good!
|
||||
- elsif !@domain.dkim_status.nil?
|
||||
%p.pageContent__text.u-orange.u-bold
|
||||
%span.label.label--orange Warning
|
||||
= @domain.dkim_error
|
||||
|
||||
%p.pageContent__text
|
||||
You need to add a new TXT record with the name <b>#{@domain.dkim_record_name}</b>
|
||||
with the following content.
|
||||
%pre.codeBlock.u-margin= @domain.dkim_record
|
||||
|
||||
%h3.pageContent__subTitle Return Path
|
||||
- if @domain.return_path_status == 'OK'
|
||||
%p.pageContent__text.u-green.u-bold
|
||||
%span.label.label--green Good
|
||||
Your return path looks good. We'll use this when sending e-mail from this domain.
|
||||
- elsif @domain.return_path_status == 'Missing'
|
||||
%p.pageContent__text.u-grey.u-bold
|
||||
%span.label.label--grey OK
|
||||
There's no return path for this domain. This is OK but we recommend adding the record to improve deliverability and achieve DMARC alignment.
|
||||
- elsif !@domain.return_path_status.nil?
|
||||
%p.pageContent__text.u-orange.u-bold
|
||||
%span.label.label--orange Warning
|
||||
= @domain.return_path_error
|
||||
|
||||
%p.pageContent__text
|
||||
This is optional but we recommend adding this to improve deliverability. You should add
|
||||
a <b>CNAME</b> record at <b>#{@domain.return_path_domain}</b> to point to the hostname below.
|
||||
%pre.codeBlock.u-margin= Postal.config.dns.return_path
|
||||
|
||||
|
||||
%h3.pageContent__subTitle MX Records
|
||||
- if @domain.mx_status == 'OK'
|
||||
%p.pageContent__text.u-green.u-bold
|
||||
%span.label.label--green Good
|
||||
Your MX records look like they're good to go!
|
||||
- elsif @domain.mx_status == 'Missing'
|
||||
%p.pageContent__text.u-grey.u-bold
|
||||
%span.label.label--grey OK
|
||||
None of the MX records for this domain point to us. Incoming mail won't be sent to us.
|
||||
- elsif !@domain.mx_status.nil?
|
||||
%p.pageContent__text.u-orange.u-bold
|
||||
%span.label.label--orange Warning
|
||||
= @domain.mx_error
|
||||
|
||||
%p.pageContent__text
|
||||
If you wish to receive incoming e-mail for this domain, you need to add the following MX records
|
||||
to the domain. You don't have to do this and we'll only tell you if they're set up or not. Both
|
||||
records should be priority <b>10</b>.
|
||||
%pre.codeBlock.u-margin= Postal.config.dns.mx_records.join("\n")
|
||||
|
||||
|
||||
21
app/views/domains/verify.html.haml
Normal file
21
app/views/domains/verify.html.haml
Normal file
@@ -0,0 +1,21 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << @domain.name
|
||||
- page_title << "Verify"
|
||||
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'nav', :active_nav => :domains
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→ Domains →
|
||||
= @domain.name
|
||||
= render 'organizations/nav', :active_nav => :domains
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
= render :partial => "verify_with_#{@domain.verification_method.underscore}"
|
||||
5
app/views/help/_header.html.haml
Normal file
5
app/views/help/_header.html.haml
Normal file
@@ -0,0 +1,5 @@
|
||||
.navBar.navBar--secondary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Sending E-Mail", [organization, @server, :help_outgoing], :class => ['navBar__link', active_nav == :outgoing ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Receiving E-Mail", [organization, @server, :help_incoming], :class => ['navBar__link', active_nav == :incoming ? 'is-active' : '']
|
||||
|
||||
41
app/views/help/incoming.html.haml
Normal file
41
app/views/help/incoming.html.haml
Normal file
@@ -0,0 +1,41 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Help"
|
||||
- page_title << "Receiving E-Mail"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :help
|
||||
= render 'header', :active_nav => :incoming
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
%h1.pageContent__title Receiving e-mail
|
||||
%h2.pageContent__intro.u-margin
|
||||
This system can handle your incoming e-mail by accepting it from other mail servers and
|
||||
sending it on to your own applications using HTTP or to forward it to other SMTP servers.
|
||||
%p.u-margin.pageContent__helpLink= link_to "Read more about sending e-mails", [organization, @server, :help_outgoing]
|
||||
.u-margin
|
||||
%h2.pageContent__subTitle Forwarding e-mails
|
||||
%p.pageContent__text
|
||||
If you already have a incoming mail server for your domain, you may find the quickest
|
||||
way to get up and running is to simply forward e-mail from that server.
|
||||
You don't need to make any changes to your DNS to do this.
|
||||
%p.pageContent__text
|
||||
Just #{link_to "create an incoming route", [organization, @server, :routes], :class => "u-link"}
|
||||
for the address you want to receive messages for and then you'll be provided with
|
||||
an e-mail address that messages can be forward to. Any message that is received to
|
||||
this address will be treated as if it had been sent directly to the address on the route.
|
||||
%p.pageContent__text
|
||||
The address to forward mail to can be found by clicking on the route and copying the
|
||||
field marked Address from the form.
|
||||
|
||||
.u-margin
|
||||
%h2.pageContent__subTitle Setting your MX records
|
||||
%p.pageContent__text
|
||||
If you don't already have a mail server on your domain, you can simply set your
|
||||
MX records to point to this system. The MX records are shown
|
||||
below and you should add these both as priority 10 in your DNS configuration. Once
|
||||
these have been added successfully they will show with a green tick on your domain list.
|
||||
%dl.pageContent__definitions
|
||||
%dt MX Records
|
||||
%dd
|
||||
- for mx in Postal.config.dns.mx_records
|
||||
%p.pageContent__definitionCode= mx
|
||||
|
||||
60
app/views/help/outgoing.html.haml
Normal file
60
app/views/help/outgoing.html.haml
Normal file
@@ -0,0 +1,60 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Help"
|
||||
- page_title << "Sending E-Mail"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :help
|
||||
= render 'header', :active_nav => :outgoing
|
||||
.pageContent.pageContent--compact
|
||||
%h1.pageContent__title Sending e-mail
|
||||
%h2.pageContent__intro.u-margin
|
||||
There are a couple of different ways you send outgoing mail through a
|
||||
mail server. These methods are shown below:
|
||||
%p.u-margin.pageContent__helpLink= link_to "Read more about receiving e-mails", [organization, @server, :help_incoming]
|
||||
.u-margin
|
||||
%h2.pageContent__subTitle Important notes
|
||||
%ul.pageContent__list
|
||||
%li
|
||||
E-mails can only be sent from addresses with domains that you have added to mail server or the server's organization.
|
||||
Mail servers can be enabled to send mail from any domain by the administrator.
|
||||
%li
|
||||
If a message cannot be delivered, the system will not send you a bounce message but dispatch a webhook (if you set one up).
|
||||
If a message delivery fails but can be retried, the system will try #{QueuedMessage::MAX_ATTEMPTS} times to deliver it before giving up.
|
||||
.u-margin
|
||||
%h2.pageContent__subTitle Sending using SMTP
|
||||
%p.pageContent__text
|
||||
These instructions explain how to send messages using the SMTP server.
|
||||
|
||||
%dl.pageContent__definitions
|
||||
%dt SMTP Server Address
|
||||
%dd
|
||||
%p.pageContent__definitionCode= Postal.config.dns.smtp_server_hostname
|
||||
%dt Port
|
||||
%dd
|
||||
%p.pageContent__definitionCode 25 or 2525
|
||||
%p.pageContent__definitionText
|
||||
The SMTP service supports STARTTLS if you wish to send messages securely. Be aware that security
|
||||
cannot guaranteed all the way to their final destination.
|
||||
|
||||
%dt Username
|
||||
%dd
|
||||
%p.pageContent__definitionCode= @server.full_permalink
|
||||
%dt Password
|
||||
%dd
|
||||
- if @credentials['SMTP'].present?
|
||||
%p.pageContent__definitionCode
|
||||
= @credentials['SMTP'].first.key
|
||||
%p.pageContent__definitionText= link_to "Create more credentials", [organization, @server, :credentials], :class => "u-link"
|
||||
- else
|
||||
%p.warningBox
|
||||
%b No SMTP credentials created for this server yet.
|
||||
A password can be generated from the #{link_to 'credentials', [:new, organization, @server, :credential], :class => "u-link"}
|
||||
page. Just create a credential with the <b>SMTP</b> type and add a name which suits the place you'll be using the credentials.
|
||||
|
||||
%dt Authentication Methods
|
||||
%dd
|
||||
%p.pageContent__definitionCode PLAIN, LOGIN or CRAM-MD5
|
||||
|
||||
.u-margin
|
||||
%h2.pageContent__subTitle Sending over HTTP using our API
|
||||
%p.pageContent__text
|
||||
For full information about how to use our HTTP API, please #{link_to 'see the documentation', 'https://gopostal.io/~/http-sending', :class => "u-link"}.
|
||||
59
app/views/http_endpoints/_form.html.haml
Normal file
59
app/views/http_endpoints/_form.html.haml
Normal file
@@ -0,0 +1,59 @@
|
||||
= form_for [organization, @server, @http_endpoint], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :name, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :url, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :url, :class => 'input input--text'
|
||||
%p.fieldSet__text
|
||||
Enter the full URL that we should POST your messages to. We recommend using https URLs here to
|
||||
ensure your data remains secure in transit.
|
||||
.fieldSet__field
|
||||
= f.label :encoding, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :encoding, HTTPEndpoint::ENCODINGS.map { |e| [t("http_endpoint_encodings.#{e.underscore}"), e] }, {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
You can choose how the data will be delivered to your server. We recommend receiving data as JSON which will be
|
||||
posted to your endpoint with an application/json content type. If you choose to use form data, you'll be able
|
||||
to read parameters as normal without parsing any JSON.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :format, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :format, HTTPEndpoint::FORMATS.map { |e| [t("http_endpoint_formats.#{e.underscore}"), e] }, {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
You can choose whether to receive the full raw message or whether you'd prefer to receive a individual properties
|
||||
for a message individually.
|
||||
.fieldSet__field
|
||||
= f.label :strip_replies, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :strip_replies, [["Send the full message as received", false], ["Try to seperate replies/signatures from plain body", true]], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
If enabled, we'll try to remove the replies/signatures from the plain body and send them seperately to the rest of the body.
|
||||
This is useful if you just want to see the latest message in a thread.
|
||||
.fieldSet__field
|
||||
= f.label :include_attachments, "Attachments", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :include_attachments, [["Include attachment data", true], ["Don't include attachment data", false]], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
You can choose whether or not attachment data will be delivered to your app. This only applies when the message is delivered
|
||||
as a hash (rather than the raw message - these will always have attachment data within).
|
||||
.fieldSet__field
|
||||
= f.label :timeout, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :timeout, :class => 'input input--text', :placeholder => "Default: 5"
|
||||
%p.fieldSet__text
|
||||
This is how long (in seconds) we should wait for your server to respond before giving up and trying again later. By default this is 5
|
||||
seconds. The maximum value is 60 seconds.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit @http_endpoint.new_record? ? "Create HTTP endpoint" : "Save HTTP endpoint", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
- if f.object.persisted?
|
||||
= link_to "Delete HTTP endpoint", [organization, @server, @http_endpoint], :remote => true, :class => 'button button--danger', :method => :delete, :data => {:confirm => "Are you sure you wish to delete this HTTP endpoint?\n\r#{pluralize @http_endpoint.routes.size, 'route'} that uses this endpoint will also be deleted."}
|
||||
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
= hidden_field_tag 'return_notice', params[:return_notice]
|
||||
11
app/views/http_endpoints/edit.html.haml
Normal file
11
app/views/http_endpoints/edit.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "HTTP Endpoints"
|
||||
- page_title << "Edit"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :http_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
38
app/views/http_endpoints/index.html.haml
Normal file
38
app/views/http_endpoints/index.html.haml
Normal file
@@ -0,0 +1,38 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "HTTP Endpoints"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :http_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @http_endpoints.empty?
|
||||
.noData.noData--cock.noData--clean
|
||||
%h2.noData__title Oh cock! There aren't any HTTP endpoints yet.
|
||||
%p.noData__text
|
||||
HTTP endpoints are essentially URLs that you'd like incoming e-mails
|
||||
to be delivered to. Once you've added some endpoints, you can route messages
|
||||
to them by creating #{link_to 'routes', [organization, @server, :routes], :class => 'u-link'}.
|
||||
%p.noData__button
|
||||
= link_to "Add your first HTTP endpoint", [:new, organization, @server, :http_endpoint], :class => 'button button--positive'
|
||||
|
||||
- else
|
||||
|
||||
%ul.endpointList.u-margin
|
||||
- for endpoint in @http_endpoints
|
||||
%li.endpointList__item
|
||||
= link_to [:edit, organization, @server, endpoint], :class => 'endpointList__link' do
|
||||
.endpointList__main
|
||||
%p.endpointList__name= endpoint.name
|
||||
%p.endpointList__url= endpoint.url
|
||||
%ul.endpointList__details
|
||||
%li.endpointList__detailItem= t("http_endpoint_encodings.#{endpoint.encoding.underscore}")
|
||||
%li.endpointList__detailItem= t("http_endpoint_formats.#{endpoint.format.underscore}")
|
||||
%li.endpointList__detailItem
|
||||
- if endpoint.last_used_at
|
||||
Last used #{distance_of_time_in_words_to_now endpoint.last_used_at} ago
|
||||
- else
|
||||
Not used yet
|
||||
|
||||
%p.u-center= link_to "Add another HTTP endpoint", [:new, organization, @server, :http_endpoint], :class => 'button button--positive'
|
||||
11
app/views/http_endpoints/new.html.haml
Normal file
11
app/views/http_endpoints/new.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "HTTP Endpoints"
|
||||
- page_title << "New"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :http_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
35
app/views/ip_pool_rules/_form.html.haml
Normal file
35
app/views/ip_pool_rules/_form.html.haml
Normal file
@@ -0,0 +1,35 @@
|
||||
.pageContent.pageContent--compact
|
||||
= form_for [organization, @server, @ip_pool_rule], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
%h2.fieldSet__title.fieldSet__title--noMargin Rule match conditions
|
||||
.fieldSet__field
|
||||
= f.label :to_text, "To Addresses", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
~ f.text_area :to_text, :autofocus => true, :class => 'input input--text input--smallArea'
|
||||
%p.fieldSet__text
|
||||
This is a list of addresses or domains which should be matched. This
|
||||
applies to e-mail address of the recipient of a message.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :from_text, "From Addresses", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
~ f.text_area :from_text, :class => 'input input--text input--smallArea'
|
||||
%p.fieldSet__text
|
||||
This is a list of addresses or domains which should be matched. This
|
||||
applies to value <code>From</code> in the From header of the message
|
||||
that is being delivered.
|
||||
%fieldset.fieldSet
|
||||
%h2.fieldSet__title Selected IP Pool
|
||||
.fieldSet__field
|
||||
= f.label :ip_pool_id, "IP Pool", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.collection_select :ip_pool_id, organization.ip_pools.includes(:ip_addresses).order("`default` desc, name asc"), :id, :description, {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
This is the IP pool that this message should be delivered from.
|
||||
|
||||
.fieldSetSubmit
|
||||
= f.submit "Save Rule", :class => "button button--positive js-form-submit"
|
||||
.fieldSetSubmit__delete
|
||||
- if f.object.persisted?
|
||||
= link_to "Delete Rule", [organization, @server, @ip_pool_rule], :remote => true, :class => 'button button--danger', :method => :delete, :data => {:confirm => "Are you sure you wish to delete this rule?"}
|
||||
20
app/views/ip_pool_rules/edit.html.haml
Normal file
20
app/views/ip_pool_rules/edit.html.haml
Normal file
@@ -0,0 +1,20 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << "Edit IP Pool Rule"
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :settings
|
||||
= render 'servers/settings_header', :active_nav => :ip_pool_rules
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
IP Pool Rules
|
||||
→
|
||||
Edit rule
|
||||
= render 'organizations/nav', :active_nav => :ips
|
||||
= render 'ip_pools/nav', :active_nav => :rules
|
||||
= render 'form'
|
||||
65
app/views/ip_pool_rules/index.html.haml
Normal file
65
app/views/ip_pool_rules/index.html.haml
Normal file
@@ -0,0 +1,65 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << "IP Pool Rules"
|
||||
- else
|
||||
- page_title << "IPs"
|
||||
- page_title << "Rules"
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :settings
|
||||
= render 'servers/settings_header', :active_nav => :ip_pool_rules
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
IP Pool Rules
|
||||
= render 'organizations/nav', :active_nav => :ips
|
||||
= render 'ip_pools/nav', :active_nav => :rules
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
- if @ip_pool_rules.empty?
|
||||
.noData.noData--panda.noData--clean
|
||||
- if @server.nil?
|
||||
%h2.noData__title No global rules have been configured yet.
|
||||
%p.noData__text
|
||||
You can use IP pool rules to configure which IP addresses to use based on the
|
||||
message that are passing through Postal. You can add rules globally or on a
|
||||
per-server basis.
|
||||
%p.noData__button= link_to "Add a global rule", [:new, organization, @server, :ip_pool_rule], :class => "button button--positive"
|
||||
- else
|
||||
%h2.noData__title No IP rules have been configured for this server yet.
|
||||
%p.noData__text
|
||||
You can use IP pool rules to configure which IP addresses to use based on the
|
||||
message that are passing through Postal. You can add rules globally or on a
|
||||
per-server basis.
|
||||
%p.noData__button= link_to "Add a server rule", [:new, organization, @server, :ip_pool_rule], :class => "button button--positive"
|
||||
-
|
||||
- else
|
||||
.ipPoolRuleList.u-margin
|
||||
- for ip_pool_rule in @ip_pool_rules
|
||||
.ipPoolRuleList__item
|
||||
= link_to [:edit, organization, @server, ip_pool_rule], :class => 'ipPoolRuleList__link' do
|
||||
- if ip_pool_rule.to.present?
|
||||
%dl.ipPoolRuleList__condition
|
||||
%dt Any messages sent to:
|
||||
%dd
|
||||
%ul
|
||||
- for a in ip_pool_rule.to
|
||||
%li= a
|
||||
- if ip_pool_rule.from.present?
|
||||
%dl.ipPoolRuleList__condition
|
||||
%dt Any message sent from:
|
||||
%dd
|
||||
%ul
|
||||
- for a in ip_pool_rule.from
|
||||
%li= a
|
||||
|
||||
%dl.ipPoolRuleList__condition
|
||||
%dt Will be sent using:
|
||||
%dd= ip_pool_rule.ip_pool.description
|
||||
- if @server
|
||||
%p.ipPoolRuleListDefault.u-margin All mail that doesn't match a rule above will be sent using #{@server.ip_pool.description}.
|
||||
%p.u-center= link_to "Add another rule", [:new, organization, @server, :ip_pool_rule], :class => "button button--positive"
|
||||
21
app/views/ip_pool_rules/new.html.haml
Normal file
21
app/views/ip_pool_rules/new.html.haml
Normal file
@@ -0,0 +1,21 @@
|
||||
- if @server
|
||||
- page_title << @server.name
|
||||
- page_title << "Add IP Pool Rule"
|
||||
|
||||
- if @server
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :settings
|
||||
= render 'servers/settings_header', :active_nav => :ip_pool_rules
|
||||
- else
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
IP Pool Rules
|
||||
→
|
||||
Add new rule
|
||||
= render 'organizations/nav', :active_nav => :ips
|
||||
= render 'ip_pools/nav', :active_nav => :rules
|
||||
|
||||
= render 'form'
|
||||
4
app/views/ip_pools/_nav.html.haml
Normal file
4
app/views/ip_pools/_nav.html.haml
Normal file
@@ -0,0 +1,4 @@
|
||||
.navBar.navBar--secondary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Dedicated IPs", organization_ip_pools_path(organization), :class => ['navBar__link', active_nav == :ips ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Rules", organization_ip_pool_rules_path(organization), :class => ['navBar__link', active_nav == :rules ? 'is-active' : '']
|
||||
38
app/views/ip_pools/index.html.haml
Normal file
38
app/views/ip_pools/index.html.haml
Normal file
@@ -0,0 +1,38 @@
|
||||
- page_title << "IPs"
|
||||
- page_title << "Rules"
|
||||
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
Dedicated IPs
|
||||
|
||||
= render 'organizations/nav', :active_nav => :ips
|
||||
= render 'nav', :active_nav => :ips
|
||||
.pageContent.pageContent--compact
|
||||
- if @ip_pools.empty?
|
||||
.noData.noData--koala.noData--clean
|
||||
- if @server.nil?
|
||||
%h2.noData__title You don't have any dedicated IP addresses.
|
||||
%p.noData__text
|
||||
Once you've been assigned dedicated IP addresses they will appear here. You can then use them in rules and
|
||||
for servers. To request dedicated IP addresses please contact our team.
|
||||
- else
|
||||
.ipList
|
||||
- for ip_pool in @ip_pools
|
||||
.ipList__item
|
||||
%p.ipList__name= ip_pool.name
|
||||
%ul.ipList__addressList
|
||||
%li.ipList__address.ipList__address--header
|
||||
%p.ipList__ipv4 IPv4 Address
|
||||
%p.ipList__ipv6 IPv6 Address
|
||||
%p.ipList__hostname Hostname
|
||||
|
||||
- for address in ip_pool.ip_addresses
|
||||
%li.ipList__address
|
||||
%p.ipList__ipv4= address.ipv4
|
||||
%p.ipList__ipv6= address.ipv6
|
||||
%p.ipList__hostname= address.hostname
|
||||
|
||||
|
||||
52
app/views/layouts/application.html.haml
Normal file
52
app/views/layouts/application.html.haml
Normal file
@@ -0,0 +1,52 @@
|
||||
!!!
|
||||
%html.main
|
||||
%head
|
||||
%title #{page_title.reverse.join(' - ')}
|
||||
= csrf_meta_tags
|
||||
= stylesheet_link_tag 'application/application', 'data-turbolinks-track' => 'reload'
|
||||
= javascript_include_tag 'application/application', 'data-turbolinks-track' => 'reload'
|
||||
%link{:href => asset_path('favicon.png'), :rel => 'shortcut icon'}
|
||||
<meta name="turbolinks-cache-control" content="no-cache">
|
||||
= yield :head
|
||||
%body
|
||||
= display_flash
|
||||
%header.siteHeader{'data-turbolinks-permanent' => true}
|
||||
- if flash[:remember_login] && !auth_session.persistent?
|
||||
.siteHeader__remember.js-remember
|
||||
.siteHeader__rememberText
|
||||
%p.siteHeader__rememberTextTitle Would you like to stay logged in?
|
||||
%p This will keep you logged in in this browser for 2 months.
|
||||
.siteHeader__rememberButtons.buttonSet
|
||||
= link_to "Remember me", '#', :class => 'button button--positive button--small', :data => {:remember => 'yes'}
|
||||
= link_to "Close", '#', :class => 'button button--dark button--small', :data => {:remember => 'no'}
|
||||
|
||||
.siteHeader__inside
|
||||
.siteHeader__logo= link_to "Postal", root_path
|
||||
%p.siteHeader__version The open source e-mail platform
|
||||
%ul.siteHeader__nav
|
||||
- if defined?(organization) && organization
|
||||
%li.siteHeader__navItem
|
||||
%li.siteHeader__navItem.siteHeader__navItem--organization
|
||||
= link_to organization.name, organization_root_path(organization), :class => 'siteHeader__navLinkWithMenu'
|
||||
%ul.siteHeader__subMenu
|
||||
%li.siteHeader__subMenuItem.siteHeader__subMenuItem--header= link_to organization.name, organization_settings_path(organization)
|
||||
- if organization.admin?(current_user)
|
||||
%li.siteHeader__subMenuItem= link_to "Organization Settings", organization_settings_path(organization), :class => 'siteHeader__subMenuLink'
|
||||
%li.siteHeader__subMenuItem= link_to "Manage Users", organization_users_path(organization), :class => 'siteHeader__subMenuLink'
|
||||
|
||||
%li.siteHeader__subMenuItem.siteHeader__subMenuItem--div= link_to "Create new organization", :new_organization, :class => 'siteHeader__subMenuLink'
|
||||
- if current_user.organizations.present.count > 1
|
||||
%li.siteHeader__subMenuItem= link_to "Switch organization", root_path, :class => 'siteHeader__subMenuLink'
|
||||
%li.siteHeader__navItem.siteHeader__navItem--user= current_user.name
|
||||
- if current_user.admin?
|
||||
%li.siteHeader__navItem= link_to "Admin", admin_root_path, :class => 'sideHeader__navItemLink'
|
||||
%li.siteHeader__navItem= link_to "My Settings", settings_path, :class => 'sideHeader__navItemLink'
|
||||
%li.siteHeader__navItem= link_to "Logout", logout_path, :method => :delete, :class => 'sideHeader__navItemLink'
|
||||
|
||||
.siteContent
|
||||
- if content_for?(:sidebar)
|
||||
%nav.sidebar
|
||||
= content_for :sidebar
|
||||
|
||||
%section.siteContent__main
|
||||
= yield
|
||||
13
app/views/layouts/sub.html.haml
Normal file
13
app/views/layouts/sub.html.haml
Normal file
@@ -0,0 +1,13 @@
|
||||
!!!
|
||||
%html.subPage
|
||||
%head
|
||||
%title #{page_title.reverse.join(' - ')}
|
||||
= csrf_meta_tags
|
||||
= stylesheet_link_tag 'application/application', 'data-turbolinks-track' => 'reload'
|
||||
= javascript_include_tag 'application/application', 'data-turbolinks-track' => 'reload'
|
||||
%link{:href => asset_path('favicon.png'), :rel => 'shortcut icon'}
|
||||
<meta name="turbolinks-cache-control" content="no-cache">
|
||||
%body
|
||||
.subPageBox{:class => @wide ? "subPageBox--wide" : ''}
|
||||
= yield
|
||||
|
||||
48
app/views/messages/_deliveries.html.haml
Normal file
48
app/views/messages/_deliveries.html.haml
Normal file
@@ -0,0 +1,48 @@
|
||||
%ul.deliveryList
|
||||
- if message.queued_message && message.queued_message.locked?
|
||||
%li.deliveryList__item.deliveryList__item--header
|
||||
%p Message is currently being processed.
|
||||
- elsif message.queued_message && message.queued_message.retry_after
|
||||
%li.deliveryList__item.deliveryList__item--header
|
||||
%p This message will be retried automatically in #{distance_of_time_in_words_to_now message.queued_message.retry_after}.
|
||||
%p= link_to "Retry delivery now", retry_organization_server_message_path(organization, @server, message.id), :class => "button button--small", :remote => true, :method => :post
|
||||
- elsif message.held?
|
||||
%li.deliveryList__item.deliveryList__item--header
|
||||
%p
|
||||
This message has been held. By releasing the message, we will allow it to continue on its way to its destination.
|
||||
- if @message.hold_expiry
|
||||
It will be held until #{@message.hold_expiry.to_s(:long)}.
|
||||
%p.buttonSet
|
||||
= link_to "Release message", retry_organization_server_message_path(organization, @server, message.id), :class => "button button--small", :remote => true, :method => :post
|
||||
= link_to "Cancel hold", cancel_hold_organization_server_message_path(organization, @server, message.id), :class => "button button--small button--danger", :remote => true, :method => :post
|
||||
- elsif @server.mode == 'Development'
|
||||
%li.deliveryList__item.deliveryList__item--header
|
||||
%p This server is in development mode so this message can be redelivered as if it had just been received.
|
||||
%p= link_to "Redeliver message", retry_organization_server_message_path(organization, @server, message.id), :class => "button button--small", :remote => true, :method => :post
|
||||
|
||||
- if message.deliveries.empty?
|
||||
%li.deliveryList__item
|
||||
.noData.noData--fox.noData--clean
|
||||
%h2.noData__text No delivery attempts yet.
|
||||
- else
|
||||
- for delivery in message.deliveries.reverse
|
||||
%li.deliveryList__item
|
||||
.deliveryList__top
|
||||
.deliveryList__time
|
||||
= delivery.timestamp.to_s(:long)
|
||||
.deliveryList__status
|
||||
- if delivery.sent_with_ssl == 1
|
||||
= image_tag 'icons/lock.svg', :class => 'deliveryList__secure'
|
||||
%span.label.label--large{:class => "label--messageStatus-#{delivery.status.underscore}"}= delivery.status.underscore.humanize
|
||||
- if delivery.details
|
||||
%p.deliveryList__error= format_delivery_details(@server, delivery.details)
|
||||
- if delivery.log_id || delivery.output
|
||||
= link_to "Show technical details", '#', :class => 'js-toggle js-tech-link deliveryList__techLink', :data => {:element => '.js-tech-link, .js-tech-output'}
|
||||
.deliveryList__error.deliveryList__error--output.js-tech-output.is-hidden
|
||||
%p.deliveryList__error--output-text= delivery.output
|
||||
- if delivery.time
|
||||
%p.deliveryList__error--output-ref Time: #{delivery.time}s
|
||||
- if delivery.log_id
|
||||
%p.deliveryList__error--output-ref Support Ref: #{delivery.log_id}
|
||||
- if message.queued_message && !message.queued_message.locked?
|
||||
%p.deliveryList-removeLink= link_to "Remove from queue", remove_from_queue_organization_server_message_path(organization, @server, message.id), :method => :delete, :remote => true, :data => {:disable_with => "Removing...", :confirm => "Are you sure you wish to remove this message from the queue?"}, :class => "u-link"
|
||||
8
app/views/messages/_header.html.haml
Normal file
8
app/views/messages/_header.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
.navBar.navBar--secondary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Outgoing Messages", [:outgoing, organization, @server, :messages], :class => ['navBar__link', active_nav == :outgoing ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Incoming Messages", [:incoming, organization, @server, :messages], :class => ['navBar__link', active_nav == :incoming ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Queue", [:queue, organization, @server], :class => ['navBar__link', active_nav == :queue ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Held", [:held, organization, @server, :messages], :class => ['navBar__link', active_nav == :held ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Send Message", [:new, organization, @server, :message], :class => ['navBar__link', active_nav == :new ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Suppressions", [:suppressions, organization, @server, :messages], :class => ['navBar__link', active_nav == :suppressions ? 'is-active' : '']
|
||||
13
app/views/messages/_index.html.haml
Normal file
13
app/views/messages/_index.html.haml
Normal file
@@ -0,0 +1,13 @@
|
||||
.pageContent.js-ajax-region
|
||||
- if @searchable
|
||||
= render 'search'
|
||||
|
||||
- if @messages[:records].empty?
|
||||
.noData.noData--clean.noData--koala
|
||||
%h2.noData__title No koalified messages found matching your filter.
|
||||
%p.noData__text
|
||||
There were no messages which matched the query that you entered. Sorry about that.
|
||||
- else
|
||||
= render 'list', :messages => @messages[:records]
|
||||
= render 'shared/message_db_pagination', :data => @messages, :name => "message"
|
||||
|
||||
24
app/views/messages/_list.html.haml
Normal file
24
app/views/messages/_list.html.haml
Normal file
@@ -0,0 +1,24 @@
|
||||
%ul.messageList
|
||||
- for message in messages
|
||||
- if message.is_a?(QueuedMessage)
|
||||
- message = message.message
|
||||
%li.messageList__message
|
||||
= link_to organization_server_message_path(organization, @server, message.id), :class => 'messageList__link' do
|
||||
.messageList__details{:class => 'messageList__details--' + message.scope}
|
||||
%p.messageList__subject= message.subject || "No subject"
|
||||
%dl.messageList__addresses
|
||||
%dt To
|
||||
%dd
|
||||
- if message.rcpt_to_return_path?
|
||||
%span.returnPathTag Return Path
|
||||
- else
|
||||
= message.rcpt_to || "none"
|
||||
%dt From
|
||||
%dd= message.mail_from || "none"
|
||||
|
||||
.messageList__meta
|
||||
%p.messageList__timestamp= message.timestamp.in_time_zone.to_s(:long)
|
||||
%p.messageList__status
|
||||
- if message.read?
|
||||
%span.label.label--purple Opened
|
||||
%span.label{:class => "label--messageStatus-#{message.status.underscore}"}= message.status.underscore.humanize
|
||||
38
app/views/messages/_message_header.html.haml
Normal file
38
app/views/messages/_message_header.html.haml
Normal file
@@ -0,0 +1,38 @@
|
||||
.messageHeader
|
||||
.messageHeader__header{:class => "messageHeader__header--#{@message.scope}"}
|
||||
%p.messageHeader__status
|
||||
%span.label{:class => "label--messageStatus-#{@message.status.underscore}"}= @message.status.underscore.humanize
|
||||
%h2.messageHeader__subject
|
||||
= @message.subject || "No subject"
|
||||
|
||||
.messageHeader__basicProperties
|
||||
%dl
|
||||
%dt From
|
||||
%dd
|
||||
- if @message.mail_from
|
||||
= link_to @message.mail_from || "[blank]", send("#{@message.scope}_organization_server_messages_path", organization, @server, :query => "from: #{@message.mail_from}"), :class => 'u-link'
|
||||
- else
|
||||
None
|
||||
|
||||
%dl
|
||||
%dt To
|
||||
%dd
|
||||
- if @message.rcpt_to_return_path?
|
||||
%span.returnPathTag.returnPathTag--inMessageHeader= link_to "Return Path", send("#{@message.scope}_organization_server_messages_path", organization, @server, :query => "to: #{@message.rcpt_to}"), :class => 'u-link'
|
||||
- else
|
||||
= link_to @message.rcpt_to || "[blank]", send("#{@message.scope}_organization_server_messages_path", organization, @server, :query => "to: #{@message.rcpt_to}"), :class => 'u-link'
|
||||
%dl
|
||||
%dt Received
|
||||
%dd= @message.timestamp.in_time_zone.to_s(:long)
|
||||
|
||||
.navBar.navBar--tertiary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Properties", organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :properties ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Activity", activity_organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :activity ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Headers", headers_organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :headers ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Spam Checks", spam_checks_organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :spam_checks ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Plain Text", plain_organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :plain ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "HTML", html_organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :html ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Attachments", attachments_organization_server_message_path(organization, @server, @message.id), :class => ['navBar__link', active_nav == :attachments ? 'is-active' : '']
|
||||
- if @message.raw_message?
|
||||
%li.navBar__item= link_to "Download", download_organization_server_message_path(organization, @server, @message.id), :data => {:turbolinks => 'false'}, :class =>'navBar__link'
|
||||
41
app/views/messages/_search.html.haml
Normal file
41
app/views/messages/_search.html.haml
Normal file
@@ -0,0 +1,41 @@
|
||||
= form_tag request.fullpath, :method => :get, :remote => true, :class => 'messageSearch', :enforce_utf8 => false do
|
||||
%p
|
||||
= link_to "Need help with filtering?", '#', :class => 'messageSearch__help js-toggle-helpbox'
|
||||
= text_field_tag 'query', @query, :class => 'messageSearch__input js-focus-on-f js-form-submit', :placeholder => "Filter messages...", :data => {:disable_with => 'Searching...'}
|
||||
|
||||
.messageSearch__helpBox.is-hidden.js-helpbox
|
||||
.messageSearch__left
|
||||
%h3.messageSearch__helpBoxTitle
|
||||
Filtering your messages
|
||||
%p.messageSearch__helpBoxText
|
||||
You can filter your messages on a number of attributes. At present, it is not possible to
|
||||
search the content of your messages. To filter though, you can insert any of the strings
|
||||
as shown opposite into the box above and press enter.
|
||||
.messageSearch__right
|
||||
%dl.messageSearch__definition
|
||||
%dt to: rachel@example.com
|
||||
%dd Returns all mail addressed to the address provided.
|
||||
%dl.messageSearch__definition
|
||||
%dt from: tom@example.com
|
||||
%dd Returns all mail sent from to the address provided.
|
||||
%dl.messageSearch__definition
|
||||
%dt status: pending
|
||||
%dd Returns all messages with the status provided. The suitable statuses are: <code>pending</code>, <code>sent</code>, <code>held</code>, <code>softfail</code>, <code>hardfail</code> and <code>bounced</code>.
|
||||
%dl.messageSearch__definition
|
||||
%dt before: yyyy-mm-dd hh:mm
|
||||
%dd Returns any message received before the given timestamp.
|
||||
%dl.messageSearch__definition
|
||||
%dt after: yyyy-mm-dd hh:mm
|
||||
%dd Returns any message received after the given timestamp.
|
||||
%dl.messageSearch__definition
|
||||
%dt msgid: 57f3a85b35545@server01.mail
|
||||
%dd Returns any message with the given Message-ID header.
|
||||
%dl.messageSearch__definition
|
||||
%dt tag: password-reset
|
||||
%dd Returns any message tagged with the tag provided.
|
||||
%dl.messageSearch__definition
|
||||
%dt spam: yes
|
||||
%dd By default, spam is not shown in results. To show spam instead of non-spam, just add this to the query.
|
||||
%dl.messageSearch__definition
|
||||
%dt order: oldest-first
|
||||
%dd By default, newest messages are shown first. To show oldest messages first, you can add this.
|
||||
45
app/views/messages/activity.html.haml
Normal file
45
app/views/messages/activity.html.haml
Normal file
@@ -0,0 +1,45 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
- page_title << "Activity"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :activity
|
||||
.pageContent.pageContent--compact
|
||||
%ul.messageActivity
|
||||
- for entry in @entries.reverse
|
||||
- if entry.is_a?(Postal::MessageDB::Delivery)
|
||||
%li.messageActivity__event
|
||||
%p.messageActivity__timestamp= entry.timestamp.to_s(:long)
|
||||
.messageActivity__details.messageActivity--detailsDelivery
|
||||
%p.messageActivity__subject
|
||||
=# entry.status.underscore.humanize
|
||||
%span.label.label--large{:class => "label--messageStatus-#{entry.status.underscore}"}= entry.status.underscore.humanize
|
||||
|
||||
%p.messageActivity__extra= entry.details
|
||||
|
||||
- elsif entry.is_a?(Postal::MessageDB::Click)
|
||||
%li.messageActivity__event
|
||||
%p.messageActivity__timestamp= entry.timestamp.to_s(:long)
|
||||
.messageActivity__details.messageActivity--detailsClick
|
||||
%p.messageActivity__subject Click for #{entry.url}
|
||||
%p.messageActivity__extra Clicked from #{entry.ip_address} (#{entry.user_agent})
|
||||
|
||||
- elsif entry.is_a?(Postal::MessageDB::Load)
|
||||
%li.messageActivity__event
|
||||
%p.messageActivity__timestamp= entry.timestamp.to_s(:long)
|
||||
.messageActivity__details.messageActivity--detailsLoad
|
||||
%p.messageActivity__subject Message Viewed
|
||||
%p.messageActivity__extra Opened from #{entry.ip_address} (#{entry.user_agent})
|
||||
|
||||
%li.messageActivity__event
|
||||
%p.messageActivity__timestamp= @message.timestamp.to_s(:long)
|
||||
.messageActivity__details
|
||||
%p.messageActivity__subject
|
||||
Message received by Postal
|
||||
%p.messageActivity__extra
|
||||
- if @message.credential
|
||||
Received using the #{@message.credential.name} #{@message.credential.type} credential.
|
||||
- if @message.received_with_ssl == 1
|
||||
Connection secured with SSL.
|
||||
23
app/views/messages/attachments.html.haml
Normal file
23
app/views/messages/attachments.html.haml
Normal file
@@ -0,0 +1,23 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
- page_title << "Attachments"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :attachments
|
||||
.pageContent.pageContent--compact
|
||||
- if @message.attachments.empty?
|
||||
.noData.noData--clean.noData--wolf
|
||||
%h2.noData__title There are no attachments for this message.
|
||||
%p.noData__text
|
||||
This means that we no longer store the raw data for this e-mail
|
||||
or the e-mail just didn't have any attached files.
|
||||
- else
|
||||
%ul.largeList
|
||||
- @message.attachments.each_with_index do |attachment, i|
|
||||
%li.largeList__item
|
||||
= link_to attachment_organization_server_message_path(organization, @server, @message.id, :attachment => i), :class => 'largeList__link', :data => {:turbolinks => "false"} do
|
||||
%p.largeList__rightLabel= number_to_human_size attachment.body.to_s.bytesize
|
||||
%p= attachment.filename
|
||||
%p.largeList__subText= attachment.mime_type
|
||||
25
app/views/messages/headers.html.haml
Normal file
25
app/views/messages/headers.html.haml
Normal file
@@ -0,0 +1,25 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
- page_title << "Headers"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :headers
|
||||
|
||||
- if @message.headers.empty?
|
||||
.pageContent.pageContent--compact
|
||||
.noData.noData--clean.noData--cat2
|
||||
%h2.noData__title There are no headers for this message.
|
||||
%p.noData__text
|
||||
This means that we no longer store the raw data for this e-mail.
|
||||
|
||||
- else
|
||||
.pageContent
|
||||
.headersList
|
||||
- for key, values in @message.headers
|
||||
- for value in values
|
||||
%dl.headersList__item
|
||||
%dt= key
|
||||
%dd= value
|
||||
|
||||
16
app/views/messages/held.html.haml
Normal file
16
app/views/messages/held.html.haml
Normal file
@@ -0,0 +1,16 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Held"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => :held
|
||||
- if @messages.empty? && !@queried
|
||||
.pageContent--compact
|
||||
.noData.noData--deer.noData--clean
|
||||
%h2.noData__title You haven't got any held messages.
|
||||
%p.noData__text
|
||||
You haven't sent any messages through this mail server yet. Not to worry though
|
||||
they'll start appearing here as soon as you start sending them.
|
||||
- else
|
||||
= render 'index'
|
||||
|
||||
17
app/views/messages/html.html.haml
Normal file
17
app/views/messages/html.html.haml
Normal file
@@ -0,0 +1,17 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
- page_title << "HTML"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :html
|
||||
- if @message.html_body.blank?
|
||||
.pageContent.pageContent--compact
|
||||
.noData.noData--clean.noData--panda
|
||||
%h2.noData__title There's no HTML body for this message.
|
||||
%p.noData__text
|
||||
This means that we no longer store the raw data for this e-mail
|
||||
or the e-mail didn't include a HTML part.
|
||||
- else
|
||||
%iframe{:width => "100%", :height => "100%", :src => html_raw_organization_server_message_path(organization, @server, @message.id)}
|
||||
18
app/views/messages/incoming.html.haml
Normal file
18
app/views/messages/incoming.html.haml
Normal file
@@ -0,0 +1,18 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Incoming"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => :incoming
|
||||
- if @messages[:records].empty? && !@queried
|
||||
.pageContent--compact
|
||||
.noData.noData--deer.noData--clean
|
||||
%h2.noData__title Oh deer! You haven't received any messages yet.
|
||||
%p.noData__text
|
||||
You haven't received any messages through this mail server yet. Not to worry though
|
||||
they'll start appearing here as soon as you start receiving them.
|
||||
%p.noData__button
|
||||
= link_to "View spam messages", incoming_organization_server_messages_path(organization, @server, :query => "spam: yes"), :class => "button button--neutral"
|
||||
|
||||
- else
|
||||
= render 'index'
|
||||
49
app/views/messages/new.html.haml
Normal file
49
app/views/messages/new.html.haml
Normal file
@@ -0,0 +1,49 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Send"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => :new
|
||||
.pageContent.pageContent--compact
|
||||
%p.pageContent__intro.u-margin
|
||||
You can use this form to send a message through this mail server. This is useful
|
||||
for testing and debugging purposes.
|
||||
- if @message.is_a?(OutgoingMessagePrototype)
|
||||
%p.pageContent__text.u-margin.newMessageType.newMessageType--outgoing
|
||||
<b>You are sending an outgoing message.</b> This e-mail will be routed as if it was an e-mail sent from your mail server.
|
||||
= link_to "Simulate an incoming e-mail instead?", {:direction => 'incoming'}, :class => 'u-link'
|
||||
- else
|
||||
%p.pageContent__text.u-margin.newMessageType.newMessageType--incoming
|
||||
<b>You are sending an incoming message.</b> This e-mail will can only be sent to your routes and will behave as if it was received by your mail server.
|
||||
= link_to "Simulate an outgoing e-mail instead?", {:direction => 'outgoing'}, :class => 'u-link'
|
||||
= form_tag [organization, @server, :messages], :remote => true do
|
||||
= hidden_field_tag 'direction', params[:direction]
|
||||
.fieldSet
|
||||
- if @message.is_a?(OutgoingMessagePrototype)
|
||||
.fieldSet__field
|
||||
= label_tag :message_from, "From ", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= text_field_tag "message[from]", @message.from, :autofocus => true, :class => 'input input--text'
|
||||
%p.fieldSet__text
|
||||
Enter the address that you wish to wish to send the message from. This must be
|
||||
an address which exists at one of your verified domains.
|
||||
.fieldSet__field
|
||||
= label_tag :message_to, "To", :class => 'fieldSet__label'
|
||||
.fieldSet__input= text_field_tag "message[to]", @message.to, :class => 'input input--text'
|
||||
- else
|
||||
.fieldSet__field
|
||||
= label_tag :message_route_id, "Route", :class => 'fieldSet__label'
|
||||
.fieldSet__input= text_field_tag "message[to]", @message.to, :class => 'input input--text'
|
||||
|
||||
.fieldSet__field
|
||||
= label_tag :message_from, "From", :class => 'fieldSet__label'
|
||||
.fieldSet__input= text_field_tag "message[from]", @message.from, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= label_tag :message_subject, "Subject", :class => 'fieldSet__label'
|
||||
.fieldSet__input= text_field_tag "message[subject]", @message.subject, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= label_tag :message_plain_body, "Body", :class => 'fieldSet__label'
|
||||
.fieldSet__input= text_area_tag "message[plain_body]", @message.plain_body, :class => 'input input--area'
|
||||
.fieldSetSubmit.buttonSet
|
||||
= submit_tag "Send Message", :class => 'button button--positive js-form-submit'
|
||||
|
||||
16
app/views/messages/outgoing.html.haml
Normal file
16
app/views/messages/outgoing.html.haml
Normal file
@@ -0,0 +1,16 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Outgoing"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => :outgoing
|
||||
- if @messages[:records].empty? && !@queried
|
||||
.pageContent--compact
|
||||
.noData.noData--deer.noData--clean
|
||||
%h2.noData__title Oh deer! You haven't sent any messages yet.
|
||||
%p.noData__text
|
||||
You haven't sent any messages through this mail server yet. Not to worry though
|
||||
they'll start appearing here as soon as you start sending them.
|
||||
- else
|
||||
= render 'index'
|
||||
|
||||
17
app/views/messages/plain.html.haml
Normal file
17
app/views/messages/plain.html.haml
Normal file
@@ -0,0 +1,17 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
- page_title << "Plain Text"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :plain
|
||||
.pageContent.pageContent--compact
|
||||
- if @message.plain_body.blank?
|
||||
.noData.noData--clean.noData--owl
|
||||
%h2.noData__title There's no plain text body for this message.
|
||||
%p.noData__text
|
||||
This means that we no longer store the raw data for this e-mail
|
||||
or the e-mail didn't include a plain text part.
|
||||
- else
|
||||
%pre.codeBlock= @message.plain_body
|
||||
76
app/views/messages/show.html.haml
Normal file
76
app/views/messages/show.html.haml
Normal file
@@ -0,0 +1,76 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :properties
|
||||
.pageContent
|
||||
.messagePropertiesPage
|
||||
.messagePropertiesPage__left
|
||||
.messagePropertiesPage__propertyPair
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Spam Status
|
||||
%dd
|
||||
= link_to spam_checks_organization_server_message_path(organization, @server, @message.id) do
|
||||
%span.label.label--large{:class => "label--spamStatus-#{@message.spam_status.underscore}"}= @message.spam_status.underscore.humanize
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Tag
|
||||
%dd= @message.tag ? link_to(@message.tag, send("#{@message.scope}_organization_server_messages_path", organization, @server, :query => "tag: #{@message.tag}"), :class => "u-link") : "Not tagged"
|
||||
.messagePropertiesPage__propertyPair
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Raw Message
|
||||
%dd= @message.raw_message? ? "Available" : "Removed"
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Message Size
|
||||
%dd= @message.size ? number_to_human_size(@message.size) : "n/a"
|
||||
|
||||
.messagePropertiesPage__propertyPair
|
||||
- if @message.scope == 'incoming'
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Route
|
||||
%dd
|
||||
- if @message.route
|
||||
= link_to @message.route.name, [:edit, organization, @server, @message.route], :class => "u-link"
|
||||
- else
|
||||
Unknown Route
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Domain
|
||||
%dd
|
||||
- if @message.domain
|
||||
= link_to @message.domain.name, [organization, @server, :domains], :class => "u-link"
|
||||
- else
|
||||
Unknown Domain
|
||||
- else
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Credential
|
||||
%dd
|
||||
- if @message.credential
|
||||
= link_to @message.credential.name, [:edit, organization, @server, @message.credential], :class => "u-link"
|
||||
- else
|
||||
Unknown Credential
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Domain
|
||||
%dd
|
||||
- if @message.domain
|
||||
= link_to @message.domain.name, [organization, @server, :domains], :class => "u-link"
|
||||
- else
|
||||
Unknown Domain
|
||||
- if @message.threat == 1
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Threat
|
||||
%dd= @message.threat_details
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Message ID
|
||||
%dd= @message.message_id || "No message ID"
|
||||
- unless @message.received_with_ssl.nil?
|
||||
%dl.messagePropertiesPage__property
|
||||
%dt Transport Security
|
||||
- if @message.received_with_ssl == 1
|
||||
%dd.messagePropertiesPage__property--locked Received over a SSL connection
|
||||
- else
|
||||
%dd Not received with SSL
|
||||
|
||||
.messagePropertiesPage__right
|
||||
= render 'deliveries', :message => @message
|
||||
|
||||
31
app/views/messages/spam_checks.html.haml
Normal file
31
app/views/messages/spam_checks.html.haml
Normal file
@@ -0,0 +1,31 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Message ##{@message.id}"
|
||||
- page_title << "Spam checks"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => @message.scope.to_sym
|
||||
= render 'message_header', :active_nav => :spam_checks
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @spam_checks.empty?
|
||||
.noData.noData--clean
|
||||
%h2.noData__title This message doesn't have any spam checks.
|
||||
%p.noData__text
|
||||
This likely means we haven't scanned this message to determine its likelyhood
|
||||
of being spam. It may take a few seconds to appear after a new message is
|
||||
received.
|
||||
|
||||
- else
|
||||
%ul.spamCheckList
|
||||
%li.spamCheckList__item.spamCheckList__item--total
|
||||
%p.spamCheckList__score{:class => @message.spam_score <= 0 ? (@message.spam_score == 0 ? 'spamCheckList__score--neutral' : 'spamCheckList__score--positive') : 'spamCheckList__score--negative'}= @message.spam_score
|
||||
.spamCheckList__details.spamCheckList__details--total
|
||||
Total spam score for e-mail
|
||||
- for spam_check in @spam_checks
|
||||
%li.spamCheckList__item
|
||||
%p.spamCheckList__score{:class => spam_check['score'] <= 0 ? (spam_check['score'] == 0 ? 'spamCheckList__score--neutral' : 'spamCheckList__score--positive') : 'spamCheckList__score--negative'}= spam_check['score']
|
||||
.spamCheckList__details
|
||||
%p.spamCheckList__code= spam_check['code']
|
||||
%p.spamCheckList__description= spam_check['description']
|
||||
|
||||
26
app/views/messages/suppressions.html.haml
Normal file
26
app/views/messages/suppressions.html.haml
Normal file
@@ -0,0 +1,26 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Suppression List"
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :messages
|
||||
= render 'header', :active_nav => :suppressions
|
||||
.pageContent.pageContent--compact
|
||||
- if @suppressions[:records].empty?
|
||||
.noData.noData--clean.noData--owl
|
||||
%h2.noData__title No addresses on the suppression list.
|
||||
%p.noData__text
|
||||
When messages cannot be delivered, addresses are added to the suppression list which stops
|
||||
future messages to the same recipient being sent through.
|
||||
- else
|
||||
%p.pageContent__intro.u-margin
|
||||
When messages cannot be delivered, addresses are added to the suppression list which stops
|
||||
future messages to the same recipient being sent through. Recipients are removed from the list after 30 days.
|
||||
%ul.suppressionList
|
||||
- for suppression in @suppressions[:records]
|
||||
%li.suppressionList__item
|
||||
.suppressionList__left
|
||||
%p.suppressionList__address= link_to suppression['address'], outgoing_organization_server_messages_path(organization, @server, :query => "to: #{suppression['address']}")
|
||||
%p.suppressionList__reason= suppression['reason'].capitalize
|
||||
.suppressionList__right
|
||||
%p.suppressionList__timestamp Added #{Time.at(suppression['timestamp']).to_s(:long)}
|
||||
= render 'shared/message_db_pagination', :data => @suppressions, :name => "suppression"
|
||||
10
app/views/organizations/_nav.html.haml
Normal file
10
app/views/organizations/_nav.html.haml
Normal file
@@ -0,0 +1,10 @@
|
||||
- if organization.admin?(current_user)
|
||||
.navBar
|
||||
%ul
|
||||
%li.navBar__item= link_to "Mail Servers", organization_root_path(organization), :class => ['navBar__link', active_nav == :servers ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Domains", organization_domains_path(organization), :class => ['navBar__link', active_nav == :domains ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Settings", organization_settings_path(organization), :class => ['navBar__link', active_nav == :settings ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "IPs", organization_ip_pools_path(organization), :class => ['navBar__link', active_nav == :ips ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Users", organization_users_path(organization), :class => ['navBar__link', active_nav == :users ? 'is-active' : '']
|
||||
- if organization.owner?(current_user)
|
||||
%li.navBar__item= link_to "Delete Organization", organization_delete_path(organization), :class => ['navBar__link', active_nav == :delete ? 'is-active' : '']
|
||||
24
app/views/organizations/delete.html.haml
Normal file
24
app/views/organizations/delete.html.haml
Normal file
@@ -0,0 +1,24 @@
|
||||
- page_title << organization.name
|
||||
- page_title << "Delete"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= organization.name
|
||||
→
|
||||
Delete organization
|
||||
= render 'nav', :active_nav => :delete
|
||||
.pageContent.pageContent--compact
|
||||
%h2.pageContent__intro.u-margin
|
||||
If you no longer need this organization you can delete it. When you delete an organization
|
||||
all its mail servers & data will be deleted from our systems.
|
||||
.dangerZone
|
||||
%p.pageContent__text.u-margin
|
||||
To continue to delete this organization, please enter your password in the field below and press
|
||||
continue. <b class='u-red'>There will be no other confirmations.</b>
|
||||
= form_tag [organization, :delete], :method => :delete, :remote => true do
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
%p.u-margin
|
||||
= password_field_tag "password", '', :class => 'input input--text input--danger'
|
||||
.buttonSet.u-center
|
||||
= submit_tag "Delete this organization, mail servers and all messages", :class => 'button button--danger js-form-submit'
|
||||
|
||||
28
app/views/organizations/edit.html.haml
Normal file
28
app/views/organizations/edit.html.haml
Normal file
@@ -0,0 +1,28 @@
|
||||
- page_title << @organization.name
|
||||
- page_title << "Organization Settings"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
Settings
|
||||
|
||||
= render 'nav', :active_nav => :settings
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
= form_for @organization_obj, :url => organization_settings_path(@organization_obj), :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :name, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :time_zone, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.time_zone_select :time_zone, [], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
Choose the time zone that your organization exists within. This is used when displaying times in places
|
||||
where there isn't a logged in user to provide their own time zone.
|
||||
|
||||
%p.fieldSetSubmit.buttonSet
|
||||
= f.submit "Save Settings", :class => 'button button--positive js-form-submit'
|
||||
28
app/views/organizations/index.html.haml
Normal file
28
app/views/organizations/index.html.haml
Normal file
@@ -0,0 +1,28 @@
|
||||
- page_title << "Welcome"
|
||||
|
||||
.pageHeader
|
||||
%h1.pageHeader__title Welcome to Postal, #{current_user.first_name}
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @organizations.empty?
|
||||
.noData.noData--panda.noData--clean
|
||||
%p.noData__title This is unbearable! You don't have any organizations.
|
||||
%p.noData__text
|
||||
That's not on. You need an organization otherwise you can't do much here. Hit
|
||||
the button below and you'll be up and running with 10,000 free e-mails before
|
||||
you know it.
|
||||
%p.noData__button= link_to "Create your first organization", :new_organization, :class => 'button button--positive'
|
||||
- else
|
||||
%p.pageContent__intro.u-margin
|
||||
Organizations are entities which are able to deploy mail servers.
|
||||
Choose an existing organization from the list opposite or use the button below
|
||||
to create a new one.
|
||||
|
||||
%ul.largeList.u-margin
|
||||
- for organization in @organizations
|
||||
%li.largeList__item
|
||||
= link_to organization_root_path(organization), :class => 'largeList__link' do
|
||||
= organization.name
|
||||
|
||||
%p.u-center= link_to "Start another organization", :new_organization, :class => 'button button--positive'
|
||||
25
app/views/organizations/new.html.haml
Normal file
25
app/views/organizations/new.html.haml
Normal file
@@ -0,0 +1,25 @@
|
||||
- page_title << "Create a new organization"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title Create a new organization
|
||||
.pageContent.pageContent--compact
|
||||
%p.pageContent__intro.u-margin
|
||||
If you're starting a new organization you can do so by completing this form. You'll be able
|
||||
to invite new users & create mail servers as soon as it has been created.
|
||||
= form_for @organization, :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :name, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :permalink, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :permalink, :class => 'input input--text', :placeholder => "Automatically generated"
|
||||
%p.fieldSet__text
|
||||
This is a short name which is used in usernames and the API to identify your organization.
|
||||
It should only contain letters, numbers & hyphens.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit "Create organization", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
= link_to "Back to homepage", root_path, :class => 'button button--neutral'
|
||||
56
app/views/routes/_form.html.haml
Normal file
56
app/views/routes/_form.html.haml
Normal file
@@ -0,0 +1,56 @@
|
||||
= form_for [organization, @server, @route], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
.routeNameInput
|
||||
= f.text_field :name, :autofocus => true, :class => 'input input--text routeNameInput__name'
|
||||
%span.routeNameInput__at @
|
||||
= f.select :domain_id, domain_options_for_select(@server, @route.domain), {}, :class => 'input input--select routeNameInput__domain'
|
||||
%p.fieldSet__text
|
||||
Enter the address you wish to route. In addition to the name you enter, you'll also received "tagged" mail for this
|
||||
address. See our documentation for details about tagged mail.
|
||||
.fieldSet__field
|
||||
= f.label :_endpoint, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :_endpoint, endpoint_options_for_select(@server, @route._endpoint), {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
This is the endpoint where mail to this address will be delivered to. If you need to add different endpoints,
|
||||
you can do this using the links above this form.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :_endpoint, "Additional Endpoints", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
.fieldSet__selectList
|
||||
- for endpoint in @route.additional_route_endpoints_array
|
||||
= select_tag "route[additional_route_endpoints_array][]", endpoint_options_for_select(@server, endpoint, :other => false), :class => 'input input--select'
|
||||
= select_tag "route[additional_route_endpoints_array][]", endpoint_options_for_select(@server, nil, :other => false), :class => 'input input--select'
|
||||
|
||||
%p.fieldSet__text
|
||||
If you wish to deliver a message to multiple endpoints, you can do so by choosing them from the list above.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :spam_mode, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :spam_mode, Route::SPAM_MODES, {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
You can choose what should happen to mail which we identify as spam. If you choose <b>Mark</b> we'll tell you
|
||||
we think its spam when we deliver it to your endpoint. If you choose <b>Quarantine</b>, we won't send the message
|
||||
to you at all and you'll have manually accept it through our web interface or the API if you want it delivered.
|
||||
If you choose <b>Fail</b>, the message will simply be failed without any attempt to deliver your message.
|
||||
- if @route.persisted?
|
||||
.fieldSet__field
|
||||
= f.label :forward_address, "Address", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :forward_address, :class => 'input input--text', :readonly => true
|
||||
%p.fieldSet__text
|
||||
If you don't wish to point your MX records to our server, you can redirect your mail to this address and
|
||||
will be routed to your endpoint as if it was sent to the address you entered above.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit @route.new_record? ? "Create route" : "Save route", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
- if f.object.persisted?
|
||||
= link_to "Delete route", [organization, @server, @route], :remote => true, :class => 'button button--danger', :method => :delete, :data => {:confirm => "Are you sure you wish to delete this route?"}
|
||||
|
||||
6
app/views/routes/_header.html.haml
Normal file
6
app/views/routes/_header.html.haml
Normal file
@@ -0,0 +1,6 @@
|
||||
.navBar.navBar--secondary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Routes", [organization, @server, :routes], :class => ['navBar__link', active_nav == :routes ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "HTTP Endpoints", [organization, @server, :http_endpoints], :class => ['navBar__link', active_nav == :http_endpoints ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "SMTP Endpoints", [organization, @server, :smtp_endpoints], :class => ['navBar__link', active_nav == :smtp_endpoints ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Address Endpoints", [organization, @server, :address_endpoints], :class => ['navBar__link', active_nav == :address_endpoints ? 'is-active' : '']
|
||||
10
app/views/routes/edit.html.haml
Normal file
10
app/views/routes/edit.html.haml
Normal file
@@ -0,0 +1,10 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routes"
|
||||
- page_title << "Edit Route"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'header', :active_nav => :routes
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
47
app/views/routes/index.html.haml
Normal file
47
app/views/routes/index.html.haml
Normal file
@@ -0,0 +1,47 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routes"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'header', :active_nav => :routes
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
- if @routes.empty?
|
||||
.noData.noData--monkey.noData--clean
|
||||
%h2.noData__title We heard on the ape vine, you've got no routes yet.
|
||||
%p.noData__text
|
||||
To receive incoming mail, you need to add routes so where we should send
|
||||
messages we receive for your domain. You can send incoming e-mail to
|
||||
HTTP endpoints or other SMTP servers.
|
||||
|
||||
- if @server.smtp_endpoints.empty? && @server.http_endpoints.empty?
|
||||
%p.noData__button.buttonSet.buttonSet--center
|
||||
= link_to "Add a HTTP endpoint", new_organization_server_http_endpoint_path(organization, @server, :return_to => new_organization_server_route_path(organization, @server), :return_notice => "You can now go ahead and add your first route for this HTTP endpoint"), :class => 'button button--positive'
|
||||
= link_to "Add a SMTP endpoint", new_organization_server_smtp_endpoint_path(organization, @server, :return_to => new_organization_server_route_path(organization, @server), :return_notice => "You can now go ahead and add your first route for this SMTP endpoint"), :class => 'button button--positive'
|
||||
%p.noData__postButtonText
|
||||
Once you've added these, you'll be able to come back here to route a
|
||||
specific e-mail address to your newly created endpoint. You can
|
||||
#{link_to "add a route without an endpoint", new_organization_server_route_path(organization, @server), :class => "u-link"} if you really want.
|
||||
- else
|
||||
%p.noData__button
|
||||
= link_to "Add your first route", [:new, organization, @server, :route], :class => 'button button--positive'
|
||||
- else
|
||||
%p.pageContent__intro.u-margin
|
||||
Routes control where incoming mail for your domain is sent. Messages can be sent to
|
||||
HTTP endpoints or other SMTP servers.
|
||||
%p.u-margin.pageContent__helpLink= link_to "Read more about receiving e-mails", [organization, @server, :help_incoming]
|
||||
|
||||
%ul.routeList.u-margin
|
||||
- for route in @routes
|
||||
%li.routeList__item
|
||||
= link_to [:edit, organization, @server, route], :class => 'routeList__link' do
|
||||
%p.routeList__name= route.description
|
||||
.routeList__details
|
||||
%p.routeList__endpoint{:class => "routeList__endpoint--#{route.endpoint_type&.underscore || 'none'}"}
|
||||
- if route.mode == 'Endpoint'
|
||||
= route.endpoint.description
|
||||
- else
|
||||
= t("route_modes.#{route.mode.underscore}")
|
||||
%p.routeList__spamMode= t("route_spam_modes.#{route.spam_mode.underscore}")
|
||||
|
||||
%p.u-center= link_to "Add another route", [:new, organization, @server, :route], :class => 'button button--positive'
|
||||
10
app/views/routes/new.html.haml
Normal file
10
app/views/routes/new.html.haml
Normal file
@@ -0,0 +1,10 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routes"
|
||||
- page_title << "Add Route"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'header', :active_nav => :routes
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
52
app/views/servers/_form.html.haml
Normal file
52
app/views/servers/_form.html.haml
Normal file
@@ -0,0 +1,52 @@
|
||||
= form_for [organization, @server], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :name, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :permalink, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :permalink, :class => 'input input--text', :placeholder => "Automatically generated", :disabled => @server.persisted?
|
||||
%p.fieldSet__text
|
||||
This is a short name which is used in usernames and the API to identify your organization.
|
||||
It should only contain letters, numbers & hyphens.
|
||||
.fieldSet__field
|
||||
= f.label :mode, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :mode, Server::MODES, {}, :autofocus => true, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
The mode you choose will determine how messages are handled. When in <b>Live</b> mode, all
|
||||
e-mail will be routed normally to the intended recipients. When in <b>Development</b> mode,
|
||||
outgoing & incoming mail will be held and only visible in the web interface and will not be
|
||||
sent to any recipients or HTTP endpoints.
|
||||
.fieldSet__field
|
||||
= f.label :ip_pool_id, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.collection_select :ip_pool_id, organization.ip_pools.includes(:ip_addresses).order("`default` desc, name asc"), :id, :description, {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
This is the set of IP addresses which outbound e-mails will be delivered from.
|
||||
|
||||
- if @server.persisted?
|
||||
.fieldSet__field
|
||||
= f.label :allow_sender, "Send as any", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
.input.is-disabled= @server.allow_sender? ? "Enabled" : "Disabled"
|
||||
%p.fieldSet__text
|
||||
When enabled, you will be able to use any e-mail address in the <code>From</code> header on outgoing e-mails.
|
||||
You will need to add a <code>Sender</code> header which must be an address at one of your verified domains.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :postmaster_address, "Postmaster", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :postmaster_address, :class => 'input input--text', :placeholder => "Set based on the domain"
|
||||
%p.fieldSet__text
|
||||
This is the e-mail address that is included in any bounce messages that are sent when incoming
|
||||
messages cannot be delivered. By default, the address is <code>postmaster@[yourdomain.com]</code>.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit f.object.new_record? ? "Build server" : "Save server", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
- unless f.object.persisted?
|
||||
= link_to "Back to server list", organization_root_path(organization), :class => 'button button--neutral'
|
||||
|
||||
60
app/views/servers/_header.html.haml
Normal file
60
app/views/servers/_header.html.haml
Normal file
@@ -0,0 +1,60 @@
|
||||
.serverHeader
|
||||
.serverHeader__stripe{:class => "serverHeader__stripe--#{@server.status.underscore}"}= @server.status
|
||||
|
||||
.serverHeader__info
|
||||
%p.serverHeader__title= @server.name
|
||||
|
||||
%ul.serverHeader__list
|
||||
- total, unverified, bad_dns = @server.domain_stats
|
||||
- if total == 0
|
||||
%li No domains have been added for this server
|
||||
- elsif bad_dns == 0
|
||||
%li.serverHeader__list--ok DKIM & SPF configured correctly on #{pluralize total - unverified, 'domain'}
|
||||
- else
|
||||
%li.serverHeader__list--warning= link_to "#{pluralize bad_dns, 'domain'} has misconfigured DNS records", [organization, @server, :domains]
|
||||
- if unverified > 0
|
||||
%li= link_to "#{pluralize unverified, 'domain'} is awaiting verification", [organization, @server, :domains]
|
||||
%li Sending via #{@server.ip_pool.name}
|
||||
|
||||
.serverHeader__stats{"data-turbolinks-permanent" => true, :id => "serverStats-#{@server.uuid}"}
|
||||
%ul.serverHeader__statsList
|
||||
%li.serverHeader__stat-held
|
||||
= link_to "#{pluralize @server.held_messages, 'message'} held", held_organization_server_messages_path(organization, @server), :class => 'js-held-count'
|
||||
%li.serverHeader__stat-queue
|
||||
= link_to pluralize(@server.queue_size, 'queued message'), queue_organization_server_path(organization, @server), :class => "js-queue-size"
|
||||
%li.serverHeader__stat-bounces
|
||||
= link_to "#{number_to_percentage @server.bounce_rate, :precision => 1} bounce rate", outgoing_organization_server_messages_path(organization, @server, :query => "status: hardfail status:bounced"), :class => 'js-bounce-rate'
|
||||
%li.serverHeader__stat-size
|
||||
= link_to "#{number_to_human_size @server.message_db.total_size} used", [:retention, organization, @server], :class => 'js-disk-size'
|
||||
|
||||
.serverHeader__usage{"data-turbolinks-permanent" => true, :id => "serverUsage-#{@server.uuid}"}
|
||||
%p.serverHeader__usageTitle Message throughput — last 60 minutes
|
||||
|
||||
.serverHeader__usageLine
|
||||
.serverHeader__usageLineLabel Outgoing messages
|
||||
.serverHeader__usageLineBar
|
||||
.bar
|
||||
.bar__inner.js-outgoing-bar{:style => style_width(@server.throughput_stats[:outgoing_usage], :color => true)}
|
||||
.serverHeader__usageLineValue.js-outgoing-count{:title => "Limit: #{@server.send_limit || '∞'} every 60 minutes"}
|
||||
= number_with_delimiter @server.throughput_stats[:outgoing]
|
||||
.serverHeader__usageLine
|
||||
.serverHeader__usageLineLabel Incoming messages
|
||||
.serverHeader__usageLineValue.js-incoming-count
|
||||
= number_with_delimiter @server.throughput_stats[:incoming]
|
||||
|
||||
.serverHeader__usageLine
|
||||
.serverHeader__usageLineLabel Message Rate
|
||||
.serverHeader__usageLineValueLarge
|
||||
%b.js-message-rate= number_with_precision @server.message_rate, :precision => 2
|
||||
messages/minute
|
||||
|
||||
.navBar
|
||||
%ul
|
||||
%li.navBar__item= link_to "Overview", [organization, @server], :class => ['navBar__link', active_nav == :overview ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Messages", [:outgoing, organization, @server, :messages], :class => ['navBar__link', active_nav == :messages ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Domains", [organization, @server, :domains], :class => ['navBar__link', active_nav == :domains ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Routing", [organization, @server, :routes], :class => ['navBar__link', active_nav == :routing ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Credentials", [organization, @server, :credentials], :class => ['navBar__link', active_nav == :credentials ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Webhooks", [organization, @server, :webhooks], :class => ['navBar__link', active_nav == :webhooks ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Settings", [:edit, organization, @server], :class => ['navBar__link', active_nav == :settings ? 'is-active' : '']
|
||||
%li.navBar__item.navBar__item--end= link_to "Help", [organization, @server, :help_outgoing], :class => ['navBar__link', active_nav == :help ? 'is-active' : '']
|
||||
11
app/views/servers/_settings_header.html.haml
Normal file
11
app/views/servers/_settings_header.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
.navBar.navBar--secondary
|
||||
%ul
|
||||
%li.navBar__item= link_to "Server Settings", [:edit, organization, @server], :class => ['navBar__link', active_nav == :settings ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Spam", [:spam, organization, @server], :class => ['navBar__link', active_nav == :spam ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Retention", [:retention, organization, @server], :class => ['navBar__link', active_nav == :retention ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "Send Limit", [:limits, organization, @server], :class => ['navBar__link', active_nav == :limits ? 'is-active' : '']
|
||||
%li.navBar__item= link_to "IP Rules", [organization, @server, :ip_pool_rules], :class => ['navBar__link', active_nav == :ip_pool_rules ? 'is-active' : '']
|
||||
- if current_user.admin?
|
||||
%li.navBar__item= link_to "Admin", [:admin, organization, @server], :class => ['navBar__link', active_nav == :admin ? 'is-active' : '']
|
||||
- if organization.admin?(current_user)
|
||||
%li.navBar__item= link_to "Delete", [:delete, organization, @server], :class => ['navBar__link', active_nav == :delete ? 'is-active' : '']
|
||||
17
app/views/servers/_sidebar.html.haml
Normal file
17
app/views/servers/_sidebar.html.haml
Normal file
@@ -0,0 +1,17 @@
|
||||
- servers = organization.servers.present.order(:name).to_a
|
||||
|
||||
= content_for :sidebar do
|
||||
.js-searchable
|
||||
= form_tag '', :class => 'sidebar__search js-searchable__input' do
|
||||
= text_field_tag 'query', '', :class => 'sidebar__searchInput js-focus-on-s', :placeholder => "Filter servers..."
|
||||
%p.sidebar__placeholder.js-searchable__empty{:class => ("is-hidden" if servers.any?)}
|
||||
No servers found.
|
||||
%ul.sidebarServerList.js-searchable__list{:class => ("is-hidden" if servers.empty?)}
|
||||
- for server in servers
|
||||
%li.sidebarServerList__item.js-searchable__item{:data => {:url => organization_server_path(organization, server), :value => server.name.downcase.gsub(/\W/, '')}}
|
||||
= link_to [organization, server], :class => ['sidebarServerList__link', (active_server == server ? 'is-active' : '')] do
|
||||
%p.sidebarServerList__mode.label{:class => "label--serverStatus-#{server.status.underscore}"}= t("server_statuses.#{server.status.underscore}")
|
||||
%p.sidebarServerList__title= server.name
|
||||
%p.sidebarServerList__quantity #{number_with_precision server.message_rate, :precision => 2} messages/minute
|
||||
- if organization.admin?(current_user)
|
||||
%p.sidebar__new= link_to "Build a new mail server", [:new, organization, :server]
|
||||
53
app/views/servers/admin.html.haml
Normal file
53
app/views/servers/admin.html.haml
Normal file
@@ -0,0 +1,53 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Settings"
|
||||
- page_title << "Admin"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :settings
|
||||
= render 'settings_header', :active_nav => :admin
|
||||
.pageContent.pageContent--compact
|
||||
.u-margin
|
||||
= form_for [organization, @server], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet.fieldSet--wide
|
||||
.fieldSet__field
|
||||
= f.label :send_limit, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :send_limit, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :allow_sender, "Allow sender header", :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.select :allow_sender, [["No", false], ["Yes - can use Sender header", true]], {}, :class => 'input input--select'
|
||||
.fieldSet__field
|
||||
= f.label :log_smtp_data, "Log SMTP data?", :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.select :log_smtp_data, [["No", false], ["Yes - log all SMTP DATA (debug only)", true]], {}, :class => 'input input--select'
|
||||
.fieldSet__field
|
||||
= f.label :outbound_spam_threshold, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :outbound_spam_threshold, :class => 'input input--text', :placeholder => "No outbound spam checking"
|
||||
.fieldSet__field
|
||||
= f.label :message_retention_days, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :message_retention_days, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :raw_message_retention_days, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :raw_message_retention_days, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :raw_message_retention_size, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :raw_message_retention_size, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :ip_pool_id, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.collection_select :ip_pool_id, IPPool.order(:name), :id, :name, {}, :class => 'input input--select'
|
||||
|
||||
.fieldSetSubmit.fieldSetSubmit--wide.buttonSet
|
||||
= f.submit "Save server", :class => 'button button--positive js-form-submit'
|
||||
|
||||
- if @server.suspended_at
|
||||
= form_tag [:unsuspend, organization, @server], :remote => true do
|
||||
.fieldSetSubmit.fieldSetSubmit--wide.buttonSet
|
||||
= submit_tag "Unsuspend server", :class => 'button button--danger js-form-submit'
|
||||
|
||||
- else
|
||||
= form_tag [:suspend, organization, @server], :remote => true do
|
||||
%fieldset.fieldSet.fieldSet--wide
|
||||
.fieldSet__field
|
||||
= label_tag :reason, 'Suspension Reason', :class => 'fieldSet__label'
|
||||
.fieldSet__input= text_field_tag :reason, '', :class => 'input input--text', :required => true
|
||||
|
||||
.fieldSetSubmit.fieldSetSubmit--wide.buttonSet
|
||||
= submit_tag "Suspend server", :class => 'button button--positive js-form-submit'
|
||||
21
app/views/servers/delete.html.haml
Normal file
21
app/views/servers/delete.html.haml
Normal file
@@ -0,0 +1,21 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Delete Server"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :settings
|
||||
= render 'settings_header', :active_nav => :delete
|
||||
.pageContent.pageContent--compact
|
||||
%h2.pageContent__intro.u-margin
|
||||
If you no longer need this server you can remove it. When you remove a server all
|
||||
retained messages will be deleted and all mail which is received will be rejected
|
||||
immediately.
|
||||
.dangerZone
|
||||
%p.pageContent__text.u-margin
|
||||
To continue to remove this server, please enter your password in the field below and press
|
||||
continue. <b class='u-red'>There will be no other confirmations.</b>
|
||||
= form_tag [organization, @server], :remote => true, :method => :delete do
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
%p.u-margin
|
||||
= password_field_tag "password", '', :class => 'input input--text input--danger'
|
||||
.buttonSet.u-center
|
||||
= submit_tag "Delete this mail server and all messages", :class => 'button button--danger'
|
||||
|
||||
8
app/views/servers/edit.html.haml
Normal file
8
app/views/servers/edit.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Settings"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :settings
|
||||
= render 'settings_header', :active_nav => :settings
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
35
app/views/servers/index.html.haml
Normal file
35
app/views/servers/index.html.haml
Normal file
@@ -0,0 +1,35 @@
|
||||
- page_title << "Choose mail server"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
Mail Servers
|
||||
= render 'organizations/nav', :active_nav => :servers
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @servers.empty?
|
||||
.noData.noData--owl.noData--clean
|
||||
%p.noData__title Well owls about that, you've no mail servers yet.
|
||||
%p.noData__text
|
||||
Great - you've got an organization, now you need to provision a mail server.
|
||||
Once you've got a mail server, you can start sending & receiving messages.
|
||||
%p.noData__button.buttonSet.buttonSet--center
|
||||
= link_to "Build your first mail server", [:new, organization, :server], :class => 'button button--positive'
|
||||
- else
|
||||
.js-searchable
|
||||
%p.messageSearch= text_field_tag 'query', params[:query], :class => 'messageSearch__input js-searchable__input js-focus-on-s', :placeholder => "Find a server..."
|
||||
|
||||
%ul.largeList.u-margin.js-searchable__list
|
||||
- for server in @servers
|
||||
%li.largeList__item.js-searchable__item{:data => {:value => server.name.downcase.gsub(/\W/, ''), :url => url_for([organization, server])}}
|
||||
= link_to [organization, server], :class => 'largeList__link' do
|
||||
%span.largeList__rightLabel.label{:class => "label--serverStatus-#{server.status.underscore}"}= t("server_statuses.#{server.status.underscore}")
|
||||
%p= server.name
|
||||
%p.largeList__subText #{number_with_precision server.message_rate, :precision => 2} messages/minute
|
||||
.js-searchable__empty.is-hidden
|
||||
.noData.noData--owl.noData--clean
|
||||
%p.noData__title Well owls about that, no servers found.
|
||||
%p.noData__text
|
||||
There were no servers found matching what you've typed it.
|
||||
%p.u-center= link_to "Build a new mail server", [:new, organization, :server], :class => 'button button--positive'
|
||||
45
app/views/servers/limits.html.haml
Normal file
45
app/views/servers/limits.html.haml
Normal file
@@ -0,0 +1,45 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Limits"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :settings
|
||||
= render 'settings_header', :active_nav => :limits
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
%p.pageContent__intro.u-margin
|
||||
In order to protect our reputation and ensure the resiliency of our service,
|
||||
we implement limits on the amount of e-mail that can pass through your mail
|
||||
server.
|
||||
%p.pageContent__text.u-margin
|
||||
The main limit to be aware of is the amount of e-mail that you can send
|
||||
from your mail server to external recipients in a rolling 60 minute window.
|
||||
New mail servers start with a low limit which is increased automatically as it gets older.
|
||||
Your current limit is shown below.
|
||||
|
||||
%ul.limits.u-margin
|
||||
%li.limits__limit
|
||||
%p.limits__value
|
||||
- if @server.send_limit
|
||||
= number_with_delimiter @server.send_limit
|
||||
- else
|
||||
unlimited
|
||||
%p.limits__frequency e-mails every 60 minutes*
|
||||
|
||||
|
||||
%p.pageContent__text
|
||||
You can view your current usage & limit on the top of right of every mail server
|
||||
page in the web interface. The bars will show you how close you are to reaching the
|
||||
limits. Although we show your incoming mail throughput, it is not limited at present.
|
||||
|
||||
%p.pageContent__subTitle What happens if I reach my limit?
|
||||
%p.pageContent__text
|
||||
If you reach your outgoing limit, any new e-mails that you try to send will be held and
|
||||
will need to be released manually when your usage has dropped.
|
||||
|
||||
%p.pageContent__text
|
||||
You will be notified by e-mail (and with a webhook if enabled) when you are approaching
|
||||
and/or exceeding your limits.
|
||||
|
||||
%p.pageContent__subTitle Can I have a higher limit?
|
||||
%p.pageContent__text
|
||||
If you need higher limits, that's usually not a problem. Just drop us an email with
|
||||
what sort of e-mail you're sending and we'll get your limits increased.
|
||||
11
app/views/servers/new.html.haml
Normal file
11
app/views/servers/new.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << "Build new mail server"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
Build a new mail server
|
||||
= render 'organizations/nav', :active_nav => :servers
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
23
app/views/servers/queue.html.haml
Normal file
23
app/views/servers/queue.html.haml
Normal file
@@ -0,0 +1,23 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Messages"
|
||||
- page_title << "Queue"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :messages
|
||||
= render 'messages/header', :active_nav => :queue
|
||||
|
||||
- if @messages.empty?
|
||||
.pageContent--compact
|
||||
.noData.noData--cat2.noData--clean
|
||||
%h2.noData__title Your queue is empty. It won't stay like that fur-ever.
|
||||
%p.noData__text
|
||||
Messages which haven't yet been delivered successfully will appear in your queue until
|
||||
we've delivered them or we've given up trying.
|
||||
- else
|
||||
.pageContent
|
||||
%p.pageContent__intro.u-margin
|
||||
All messages that pass through your mail server first enter this queue. Any messages
|
||||
that cannot be delivered immediately remain in the queue until they can be successfully
|
||||
delivered or we give up on them.
|
||||
= render 'messages/list', :messages => @messages_with_message
|
||||
|
||||
= paginate @messages
|
||||
48
app/views/servers/retention.html.haml
Normal file
48
app/views/servers/retention.html.haml
Normal file
@@ -0,0 +1,48 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Message Rentention"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :settings
|
||||
= render 'settings_header', :active_nav => :retention
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
%p.pageContent__intro.u-margin
|
||||
The length of time that messages are stored by us are shown below. If you need
|
||||
to store messages for longer, please contact us and we can work out a custom
|
||||
plan.
|
||||
|
||||
.retentionLimits
|
||||
%dl.retentionLimits__limit
|
||||
.retentionLimits__label Number of days that raw message data will be stored
|
||||
.retentionLimits__info
|
||||
.retentionLimits__value
|
||||
- if @server.raw_message_retention_days
|
||||
= pluralize @server.raw_message_retention_days, 'day'
|
||||
- else
|
||||
Indefinitely
|
||||
.retentionLimits__text
|
||||
This is the number of whole days that raw message content will be stored by us.
|
||||
Raw message is the actual content of the message including headers & attachments.
|
||||
%dl.retentionLimits__limit
|
||||
.retentionLimits__label Volume of raw message data that will be stored
|
||||
.retentionLimits__info
|
||||
.retentionLimits__value
|
||||
- if @server.raw_message_retention_size
|
||||
= number_to_human_size @server.raw_message_retention_size * 1024 * 1024
|
||||
- else
|
||||
No limit
|
||||
.retentionLimits__text
|
||||
This is the amount of e-mail that can be stored. When you exceed this amount, messages will be removed in
|
||||
whole day increments starting with the oldest stored day.
|
||||
|
||||
%dl.retentionLimits__limit
|
||||
.retentionLimits__label Number of days of message meta data will be available
|
||||
.retentionLimits__info
|
||||
.retentionLimits__value
|
||||
- if @server.message_retention_days
|
||||
= pluralize @server.message_retention_days, 'day'
|
||||
- else
|
||||
Indefinitely
|
||||
.retentionLimits__text
|
||||
This is the number of days of messages that will be available through the web interface.
|
||||
You will be able to view basic meta information & delivery details but raw data might not
|
||||
be available unless it is within the retention periods above.
|
||||
49
app/views/servers/show.html.haml
Normal file
49
app/views/servers/show.html.haml
Normal file
@@ -0,0 +1,49 @@
|
||||
- page_title << @server.name
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :overview
|
||||
|
||||
- if @messages.empty?
|
||||
.pageContent--compact
|
||||
.noData.noData--cat.noData--clean
|
||||
%h2.noData__title Stop pro-cat-inating! Your new mail server is ready.
|
||||
%p.noData__text
|
||||
We can't wait to help you get up and running. The first thing you need
|
||||
to do is add & verify your domain so you can send & receive e-mail to/from it.
|
||||
It'll only take a few seconds.
|
||||
%p.noData__button.buttonSet.buttonSet--center
|
||||
= link_to "Read about sending e-mail", [organization, @server, :help_outgoing], :class => "button"
|
||||
= link_to "Read about receiving e-mail", [organization, @server, :help_incoming], :class => "button"
|
||||
- else
|
||||
.pageContent
|
||||
- if @server.suspended?
|
||||
.suspensionBox.u-margin
|
||||
%p
|
||||
This server has been suspended and is not permitted to send or receive e-mail.
|
||||
If you have any questions about this please contact our support team for assistance.
|
||||
Please be aware that suspended servers will be fully deleted from our system 30 days after
|
||||
suspension.
|
||||
- if @server.actual_suspension_reason
|
||||
%p.suspensionBox__reason
|
||||
<b>Reason:</b> #{@server.actual_suspension_reason}
|
||||
|
||||
.mailGraph.u-margin{:data => {:data => @graph_data.to_json}}
|
||||
%ul.mailGraph__key
|
||||
%li.mailGraph__key--in Incoming Messages
|
||||
%li.mailGraph__key--out Outgoing Messages
|
||||
|
||||
.mailGraph__graph
|
||||
%ul.mailGraph__labels
|
||||
- if @graph_type == :hourly
|
||||
%li #{@first_date.strftime("%A at %l%P")} →
|
||||
%li Today at #{Time.now.strftime("%l%P")}
|
||||
- else
|
||||
%li #{@first_date.to_date.to_s(:long)} →
|
||||
%li Today
|
||||
|
||||
.titleWithLinks.u-margin
|
||||
%h2.titleWithLinks__title Recently processed e-mails
|
||||
%ul.titleWithLinks__links
|
||||
%li= link_to "View message queue", [:queue, organization, @server], :class => 'titleWithLinks__link'
|
||||
%li= link_to "View full e-mail history", [:outgoing, organization, @server, :messages], :class => 'titleWithLinks__link'
|
||||
= render 'messages/list', :messages => @messages
|
||||
|
||||
40
app/views/servers/spam.html.haml
Normal file
40
app/views/servers/spam.html.haml
Normal file
@@ -0,0 +1,40 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Spam Handling"
|
||||
= render 'sidebar', :active_server => @server
|
||||
= render 'header', :active_nav => :settings
|
||||
= render 'settings_header', :active_nav => :spam
|
||||
.pageContent.pageContent--compact
|
||||
%p.pageContent__intro.u-margin
|
||||
Postal inspects all incoming messages for spam and other threats. Incoming messages
|
||||
are assigned a score which represents how likely an e-mail is to be spam. From here
|
||||
you can choose at which level you'd like to identify messages as spam.
|
||||
|
||||
= form_for [organization, @server], :remote => true do |f|
|
||||
.u-margin
|
||||
%p.pageContent__subTitle Incoming Spam Threshold
|
||||
%p.pageContent__text.u-margin
|
||||
The main spam threshold is what determines whether a message is spam or not. How incoming
|
||||
messages that are detected as spam is determined by the route which the incoming message was
|
||||
sent to. You can choose between marking the message as spam and sending it on to your endpoint,
|
||||
putting it into quarantine (holding it until manually released) or just failing it.
|
||||
%p= f.text_field :spam_threshold, :type => :range, :class => 'spamRange', :min => -10, :max => 25, :step => 0.5, :data => {:update => "js-spam-threshold-text"}
|
||||
%p.spamRangeLabel Threshold is currently <b class='js-spam-threshold-text'>#{@server.spam_threshold}</b>
|
||||
|
||||
.u-margin
|
||||
%p.pageContent__subTitle Incoming Spam Failure Threshold
|
||||
%p.pageContent__text.u-margin
|
||||
Any messages which are over your spam failure threshold will failed immediately. This is used
|
||||
to catch messages that we very sure at spam to avoid sending them needless around the place.
|
||||
%p= f.text_field :spam_failure_threshold, :type => :range, :class => 'spamRange spamRange--hot', :min => 10, :max => 50, :step => 0.5, :data => {:update => "js-spam-failure-threshold-text"}
|
||||
%p.spamRangeLabel Threshold is currently <b class='js-spam-failure-threshold-text'>#{@server.spam_failure_threshold}</b>
|
||||
|
||||
- if @server.outbound_spam_threshold
|
||||
.u-margin
|
||||
%p.pageContent__subTitle Outgoing Spam Threshold
|
||||
%p.pageContent__text.u-margin
|
||||
To prevent abuse of our services, we check outgoing messages to see whether they're likely to be
|
||||
caught as spam by other providers. Messages that score higher than the threshold set by us will
|
||||
not be passed through. If this limit needs adjusting, contact us for assistance.
|
||||
%b The threshold for this server is currently #{@server.outbound_spam_threshold}.
|
||||
|
||||
%p= f.submit "Save Spam Thresholds", :class => "button button--positive js-form-submit"
|
||||
16
app/views/sessions/begin_password_reset.html.haml
Normal file
16
app/views/sessions/begin_password_reset.html.haml
Normal file
@@ -0,0 +1,16 @@
|
||||
- page_title << "Reset your password"
|
||||
.subPageBox__title
|
||||
Reset your password
|
||||
= display_flash
|
||||
.subPageBox__content
|
||||
%p.subPageBox__text
|
||||
If you've forgotten your password, just enter your e-mail address below and we'll send you an email with a link which
|
||||
will allow you to choose a new password.
|
||||
= form_tag login_reset_path, :class => 'loginForm' do
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
%p.loginForm__input= text_field_tag 'email_address', '', :class => 'input input--text input--onWhite', :placeholder => "Your e-mail address", :autofocus => true, :tabindex => 1
|
||||
.loginForm__submit
|
||||
%ul.loginForm__links
|
||||
%li= link_to "Back to login", login_path(:return_to => params[:return_to])
|
||||
%p= submit_tag "Continue", :class => 'button button--positive', :tabindex => 3
|
||||
|
||||
20
app/views/sessions/finish_password_reset.html.haml
Normal file
20
app/views/sessions/finish_password_reset.html.haml
Normal file
@@ -0,0 +1,20 @@
|
||||
- page_title << "Reset your password"
|
||||
.subPageBox__title
|
||||
Choose a new password
|
||||
= display_flash
|
||||
|
||||
.subPageBox__content
|
||||
%p.subPageBox__text
|
||||
If you've forgotten your password, just enter your e-mail address below and we'll send you an email with a link which
|
||||
will allow you to choose a new password.
|
||||
= form_tag '', :class => 'loginForm' do
|
||||
= error_messages_for @user
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
%p.loginForm__input= password_field_tag 'password', params[:password], :class => 'input input--text input--onWhite', :placeholder => "Choose a new password", :autofocus => true, :tabindex => 1
|
||||
%p.loginForm__input= password_field_tag 'password_confirmation', params[:password_confirmation], :class => 'input input--text input--onWhite', :placeholder => "and enter it again to confirm", :tabindex => 2
|
||||
|
||||
.loginForm__submit
|
||||
%ul.loginForm__links
|
||||
%li= link_to "Back to login", login_path(:return_to => params[:return_to])
|
||||
%p= submit_tag "Login", :class => 'button button--positive', :tabindex => 3
|
||||
|
||||
19
app/views/sessions/new.html.haml
Normal file
19
app/views/sessions/new.html.haml
Normal file
@@ -0,0 +1,19 @@
|
||||
- page_title << "Login"
|
||||
.subPageBox__title
|
||||
Welcome to Postal
|
||||
= display_flash
|
||||
|
||||
.subPageBox__content
|
||||
= form_tag login_path, :class => 'loginForm' do
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
- if params[:return_to] && params[:return_to] =~ /\/join\//
|
||||
%p.loginForm__invite.warningBox.u-margin To accept your invitation you need to login to your account or create a new one. Choose from the options below to continue.
|
||||
|
||||
%p.loginForm__input= text_field_tag 'email_address', '', :type => 'email', :autocomplete => 'off', :spellcheck => 'false', :class => 'input input--text input--onWhite', :placeholder => "Your e-mail address", :autofocus => true, :tabindex => 1
|
||||
%p.loginForm__input= password_field_tag 'password', '', :class => 'input input--text input--onWhite', :placeholder => "Your password", :tabindex => 2
|
||||
.loginForm__submit
|
||||
%ul.loginForm__links
|
||||
%li= link_to "Forgotten your password?", login_reset_path(:return_to => params[:return_to])
|
||||
%li= link_to "Create a new user", signup_path(:return_to => params[:return_to])
|
||||
%p= submit_tag "Login", :class => 'button button--positive', :tabindex => 3
|
||||
|
||||
10
app/views/shared/_message_db_pagination.html.haml
Normal file
10
app/views/shared/_message_db_pagination.html.haml
Normal file
@@ -0,0 +1,10 @@
|
||||
.simplePagination
|
||||
%p.simplePagination__previous
|
||||
- if data[:page] > 1
|
||||
= link_to "← Previous page".html_safe, request.params.merge(:page => data[:page] - 1), :class => 'simplePagination__link'
|
||||
.simplePagination__current
|
||||
%p.simplePagination__info Showing #{number_with_delimiter data[:records].size} of #{number_with_delimiter data[:total]} #{data[:total] == 1 ? name : name.pluralize}
|
||||
%p Page #{data[:page]} of #{number_with_delimiter data[:total_pages]}
|
||||
%p.simplePagination__next
|
||||
- if data[:total_pages] > data[:page]
|
||||
= link_to "Next page →".html_safe, request.params.merge(:page => data[:page] + 1), :class => 'simplePagination__link'
|
||||
30
app/views/smtp_endpoints/_form.html.haml
Normal file
30
app/views/smtp_endpoints/_form.html.haml
Normal file
@@ -0,0 +1,30 @@
|
||||
= form_for [organization, @server, @smtp_endpoint], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :name, :autofocus => true, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :hostname, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :hostname, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :port, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :port, :class => 'input input--text', :placeholder => "25 (by default)"
|
||||
.fieldSet__field
|
||||
= f.label :ssl_mode, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :ssl_mode, SMTPEndpoint::SSL_MODES, {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
Choose what, if any, SSL mode you'd like to use when delivering mail to this mail server.
|
||||
Be aware that any mail sent with no SSL is insecure and not protected in anyway.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit @smtp_endpoint.new_record? ? "Create SMTP endpoint" : "Save SMTP endpoint", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
- if f.object.persisted?
|
||||
= link_to "Delete SMTP endpoint", [organization, @server, @smtp_endpoint], :remote => true, :class => 'button button--danger', :method => :delete, :data => {:confirm => "Are you sure you wish to delete this SMTP endpoint?\n\r#{pluralize @smtp_endpoint.routes.size, 'route'} that uses this endpoint will also be deleted."}
|
||||
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
= hidden_field_tag 'return_notice', params[:return_notice]
|
||||
11
app/views/smtp_endpoints/edit.html.haml
Normal file
11
app/views/smtp_endpoints/edit.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "SMTP Endpoints"
|
||||
- page_title << "Edit"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :smtp_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
36
app/views/smtp_endpoints/index.html.haml
Normal file
36
app/views/smtp_endpoints/index.html.haml
Normal file
@@ -0,0 +1,36 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "SMTP Endpoints"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :smtp_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @smtp_endpoints.empty?
|
||||
.noData.noData--dog.noData--clean
|
||||
%h2.noData__title Im-paws-ible! You've got no SMTP endpoints.
|
||||
%p.noData__text
|
||||
SMTP endpoints are other mail servers that you'd like incoming e-mails
|
||||
to be passed onto. Once you've added some endpoints, you can route messages
|
||||
to them by creating #{link_to 'routes', [organization, @server, :routes], :class => 'u-link'}.
|
||||
%p.noData__button
|
||||
= link_to "Add your first SMTP endpoint", [:new, organization, @server, :smtp_endpoint], :class => 'button button--positive'
|
||||
|
||||
- else
|
||||
|
||||
%ul.endpointList.u-margin
|
||||
- for endpoint in @smtp_endpoints
|
||||
%li.endpointList__item
|
||||
= link_to [:edit, organization, @server, endpoint], :class => 'endpointList__link' do
|
||||
.endpointList__main
|
||||
%p.endpointList__name= endpoint.name
|
||||
%p.endpointList__url= endpoint.hostname
|
||||
%ul.endpointList__details
|
||||
%li.endpointList__detailItem
|
||||
- if endpoint.last_used_at
|
||||
Last used #{distance_of_time_in_words_to_now endpoint.last_used_at} ago
|
||||
- else
|
||||
Not used yet
|
||||
|
||||
%p.u-center= link_to "Add another SMTP endpoint", [:new, organization, @server, :smtp_endpoint], :class => 'button button--positive'
|
||||
11
app/views/smtp_endpoints/new.html.haml
Normal file
11
app/views/smtp_endpoints/new.html.haml
Normal file
@@ -0,0 +1,11 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Routing"
|
||||
- page_title << "SMTP Endpoints"
|
||||
- page_title << "New"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :routing
|
||||
= render 'routes/header', :active_nav => :smtp_endpoints
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
50
app/views/track_domains/_form.html.haml
Normal file
50
app/views/track_domains/_form.html.haml
Normal file
@@ -0,0 +1,50 @@
|
||||
= form_for [organization, @server, @track_domain], :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :name, "Domain", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
.routeNameInput
|
||||
= f.text_field :name, :autofocus => true, :class => 'input input--text routeNameInput__name', :disabled => @track_domain.persisted?
|
||||
%span.routeNameInput__at .
|
||||
= f.select :domain_id, domain_options_for_select(@server, @track_domain.domain), {}, :class => 'input input--select routeNameInput__domain', :disabled => @track_domain.persisted?
|
||||
%p.fieldSet__text
|
||||
This is the domain that requests for tracked links will be directed through when you use click tracking. We recommend using something like
|
||||
<b>click.yourdomain.com</b>. You will need to a CNAME record to point to <b>#{Postal.config.dns.track_domain}</b> for this once you've added it.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :ssl_enabled, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :ssl_enabled, [["Yes - use SSL for tracking whenever possible", true], ["No - never use SSL for tracking", false]], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
If enabled, we'll try to remove the replies/signatures from the plain body and send them seperately to the rest of the body.
|
||||
This is useful if you just want to see the latest message in a thread.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :track_loads, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :track_loads, [["Yes - track when HTML e-mails are opened", true], ["No - don't track when HTML e-mails are opened", false]], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
If enabled, we'll insert a 1px image into the footer of any HTML e-mails. When this image is loaded, we'll log
|
||||
this as a view and notify you with a webhook.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :track_clicks, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :track_clicks, [["Yes - track when links are clicked", true], ["No - don't track when links are clicked", false]], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
If enabled, we'll rewrite URLs in your outbound messages to go via this domain. You'll receive a webhook when
|
||||
someone clicks one of your links and it will be displayed in the web interface.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :excluded_click_domains, "Domains excluded from tracking", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
~ f.text_area :excluded_click_domains, :class => 'input input--smallArea'
|
||||
%p.fieldSet__text
|
||||
This is a list of domains of links that you don't wish to be tracked. When click tracking is enabled,
|
||||
you can provide a list (one domain per line) for links that you don't wish to be tracked.
|
||||
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= f.submit @track_domain.new_record? ? "Create Track Domain" : "Save Track Domain", :class => 'button button--positive js-form-submit'
|
||||
|
||||
9
app/views/track_domains/edit.html.haml
Normal file
9
app/views/track_domains/edit.html.haml
Normal file
@@ -0,0 +1,9 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Tracking Domains"
|
||||
- page_title << "Edit Tracking Domain Setting"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'domains/nav', :active_nav => :track_domains
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
47
app/views/track_domains/index.html.haml
Normal file
47
app/views/track_domains/index.html.haml
Normal file
@@ -0,0 +1,47 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Tracking Domains"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'domains/nav', :active_nav => :track_domains
|
||||
|
||||
.pageContent.pageContent--compact
|
||||
|
||||
- if @track_domains.empty?
|
||||
.noData.noData--fox.noData--clean
|
||||
%h2.noData__title You haven't set up any tracking domains yet.
|
||||
%p.noData__text
|
||||
To use Postal's open & click tracking, you need to configure a domain that links will be re-written to use. Enable
|
||||
message tracking by adding a sutiable tracking domain for your outbound e-mails.
|
||||
%p.noData__button= link_to "Add a custom tracking domain", [:new, organization, @server, :track_domain], :class => "button button--positive"
|
||||
|
||||
- else
|
||||
%ul.domainList.u-margin
|
||||
- for track_domain in @track_domains
|
||||
%li.domainList__item
|
||||
.domainList__details
|
||||
%p.domainList__name
|
||||
= link_to track_domain.full_name, [:edit, organization, @server, track_domain]
|
||||
%ul.domainList__checks
|
||||
- if track_domain.dns_status == 'OK'
|
||||
%li.domainList__check.domainList__check--ok CNAME configured correctly
|
||||
- elsif track_domain.dns_status.nil?
|
||||
%li.domainList__check.domainList__check--neutral-cross CNAME/DNS not checked yet
|
||||
- else
|
||||
%li.domainList__check.domainList__check--warning{:title => track_domain.dns_error} CNAME not configured correctly
|
||||
|
||||
- if track_domain.ssl_enabled?
|
||||
- if track_domain.has_ssl?
|
||||
%li.domainList__check.domainList__check--ok= link_to "SSL enabled", [:toggle_ssl, organization, @server, track_domain], :remote => true, :method => :post
|
||||
- else
|
||||
%li.domainList__check.domainList__check--neutral= link_to "SSL setup in progress", [:toggle_ssl, organization, @server, track_domain], :remote => true, :method => :post
|
||||
- else
|
||||
%li.domainList__check.domainList__check--neutral-cross= link_to "SSL disabled", [:toggle_ssl, organization, @server, track_domain], :remote => true, :method => :post
|
||||
|
||||
%ul.domainList__properties
|
||||
%li.domainList__links
|
||||
= link_to "Settings", [:edit, organization, @server, track_domain]
|
||||
= link_to "Check DNS", [:check, organization, @server, track_domain], :remote => true, :method => :post, :data => {:disable_with => "Checking..."}
|
||||
= link_to "Delete", [organization, @server, track_domain], :remote => true, :method => :delete, :data => {:confirm => "Are you sure you wish to remove this domain?", :disable_with => "Deleting..."}, :class => 'domainList__delete'
|
||||
|
||||
%p.u-center= link_to "Add new track domain", [:new, organization, @server, :track_domain], :class => "button button--positive"
|
||||
9
app/views/track_domains/new.html.haml
Normal file
9
app/views/track_domains/new.html.haml
Normal file
@@ -0,0 +1,9 @@
|
||||
- page_title << @server.name
|
||||
- page_title << "Tracking Domains"
|
||||
- page_title << "New Tracking Domain"
|
||||
|
||||
= render 'servers/sidebar', :active_server => @server
|
||||
= render 'servers/header', :active_nav => :domains
|
||||
= render 'domains/nav', :active_nav => :track_domains
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
55
app/views/user/edit.html.haml
Normal file
55
app/views/user/edit.html.haml
Normal file
@@ -0,0 +1,55 @@
|
||||
- page_title << "My Settings"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
My Settings
|
||||
.pageContent.pageContent--compact
|
||||
= form_for @user, :url => settings_path, :remote => true do |f|
|
||||
= f.error_messages
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= label_tag :password, 'Your Password', :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= password_field_tag :password, params[:password], :autofocus => @password_correct.nil?, :disabled => @password_correct, :class => 'input input--text', :placeholder => "Enter your current password to change your details"
|
||||
- if @password_correct
|
||||
= hidden_field_tag :password, params[:password]
|
||||
%p.fieldSet__text
|
||||
In order to protect your account, you need to enter your current password in the field above
|
||||
to authenticate the change of your details.
|
||||
|
||||
.fieldSet__title
|
||||
Your details
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :first_name, "Name", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
.inputPair
|
||||
= f.text_field :first_name, :class => 'input input--text', :autofocus => @password_correct
|
||||
= f.text_field :last_name, :class => 'input input--text'
|
||||
.fieldSet__field
|
||||
= f.label :email_address, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :email_address, :class => 'input input--text'
|
||||
%p.fieldSet__text
|
||||
If you change your e-mail address, you'll need to verify that you own the new one before
|
||||
you can continue using your account.
|
||||
|
||||
.fieldSet__field
|
||||
= f.label :time_zone, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.time_zone_select :time_zone, [], {}, :class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
Choose the time zone that you'd like times to be displayed to you when you use our
|
||||
web interface. By default, times are displayed in UTC.
|
||||
|
||||
.fieldSet__title
|
||||
Change your password?
|
||||
.fieldSet__field
|
||||
= f.label :password, "New Password", :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
.inputPair
|
||||
= f.password_field :password, :class => 'input input--text', :placeholder => "•••••••••••", :value => @user.password
|
||||
= f.password_field :password_confirmation, :class => 'input input--text', :placeholder => "and confirm it", :value => @user.password_confirmation
|
||||
|
||||
|
||||
%p.fieldSetSubmit.buttonSet
|
||||
= f.submit "Save Settings", :class => 'button button--positive js-form-submit'
|
||||
16
app/views/user/join.html.haml
Normal file
16
app/views/user/join.html.haml
Normal file
@@ -0,0 +1,16 @@
|
||||
- page_title << "Join Organization"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
Join Organization
|
||||
.pageContent.pageContent--compact
|
||||
%h2.pageContent__intro.u-margin
|
||||
Welcome to Postal.
|
||||
- if @organizations.size == 1
|
||||
You've been invited to join the <b>#{@organizations.first.name}</b> organization. Once accepted, you'll be able to
|
||||
access this organization's mail servers.
|
||||
- else
|
||||
You've been invited to join an organization
|
||||
|
||||
%p.buttonSet
|
||||
= link_to "Accept " + (@organizations.size == 1 ? "Invitation" : "Invitations"), '', :class => "button button--positive", :remote => true, :method => :post
|
||||
= link_to "Reject " + (@organizations.size == 1 ? "Invitation" : "Invitations"), '', :class => "button button--danger", :remote => true, :method => :delete
|
||||
39
app/views/user/new.html.haml
Normal file
39
app/views/user/new.html.haml
Normal file
@@ -0,0 +1,39 @@
|
||||
- @wide = true
|
||||
- page_title << "Signup"
|
||||
.subPageBox__title
|
||||
Create your own Postal account
|
||||
= display_flash
|
||||
|
||||
.subPageBox__content
|
||||
%p.subPageBox__text
|
||||
To create an account, just enter your details below and you'll be on your way.
|
||||
Be sure to enter a valid e-mail address because we'll send you a verification
|
||||
e-mail as part of the signup process.
|
||||
.signupForm
|
||||
= form_for @user, :url => signup_path do |f|
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
= f.error_messages
|
||||
.fieldSet.fieldSet--compact.u-margin
|
||||
.fieldSet__fieldPair
|
||||
.fieldSet__field
|
||||
= f.label :first_name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :first_name, :class => 'input input--text input--onWhite', :autofocus => true
|
||||
.fieldSet__field
|
||||
= f.label :last_name, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :last_name, :class => 'input input--text input--onWhite'
|
||||
.fieldSet__field
|
||||
= f.label :email_address, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.text_field :email_address, :class => 'input input--text input--onWhite'
|
||||
.fieldSet__fieldPair
|
||||
.fieldSet__field
|
||||
= f.label :password, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.password_field :password, :class => 'input input--text input--onWhite', :placeholder => '•••••••••••'
|
||||
.fieldSet__field
|
||||
= f.label :password_confirmation, " ".html_safe, :class => 'fieldSet__label'
|
||||
.fieldSet__input= f.password_field :password_confirmation, :class => 'input input--text input--onWhite', :placeholder => '•••••••••••'
|
||||
|
||||
.loginForm__submit
|
||||
%ul.loginForm__links
|
||||
%li= link_to "Back to login", login_path(:return_to => params[:return_to])
|
||||
%p= submit_tag "Create Account", :class => 'button button--positive', :tabindex => 3
|
||||
|
||||
18
app/views/user/verify.html.haml
Normal file
18
app/views/user/verify.html.haml
Normal file
@@ -0,0 +1,18 @@
|
||||
- page_title << "Verify your e-mail address"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
Please verify your e-mail address
|
||||
.pageContent.pageContent--compact
|
||||
%h2.pageContent__intro.u-margin
|
||||
We need to verify that you're the owner of the e-mail address on your account. It is currently <b>#{current_user.email_address}</b>. To
|
||||
do this, we've sent you an e-mail with a 6-digit code. Please check your e-mail and enter the code within in the box below.
|
||||
%p.pageContent__text
|
||||
If you need to change your e-mail address, you can do this in from your #{link_to 'settings page', settings_path, :class => "u-link"}.
|
||||
If you haven't received the e-mail, you can #{link_to 'click here to resend it', '', :class => "u-link"}.
|
||||
= form_tag request.fullpath, :remote => true do
|
||||
= hidden_field_tag 'return_to', params[:return_to]
|
||||
%p.u-margin
|
||||
= text_field_tag "code", params[:code], :autofocus => true, :class => 'input input--text js-multibox'
|
||||
.buttonSet.u-center
|
||||
= submit_tag "Verify my e-mail address", :class => 'button button--positive js-form-submit'
|
||||
|
||||
24
app/views/users/_form.html.haml
Normal file
24
app/views/users/_form.html.haml
Normal file
@@ -0,0 +1,24 @@
|
||||
= form_for @organization_user, :url => @organization_user.new_record? ? organization_users_path(organization) : organization_user_path(organization, @organization_user.user), :remote => true do |f|
|
||||
= f.error_messages
|
||||
= hidden_field_tag 'invite', params[:invite]
|
||||
%fieldset.fieldSet
|
||||
.fieldSet__field
|
||||
= f.label :email_address, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.text_field :email_address, :autofocus => true, :class => 'input input--text', :disabled => @organization_user.persisted?
|
||||
.fieldSet__title
|
||||
What level of access do you wish to grant?
|
||||
.fieldSet__field
|
||||
= f.label :admin, :class => 'fieldSet__label'
|
||||
.fieldSet__input
|
||||
= f.select :admin, [["No - do not grant admin access", false], ["Yes - grant admin access", true]], {},:class => 'input input--select'
|
||||
%p.fieldSet__text
|
||||
Users who have admin access will be permitted to manage the organization as if they had the same
|
||||
access as the organization owner. This includes managing users, creating & deleting mail servers,
|
||||
and even removing the account. This level of access should granted carefully.
|
||||
Regardless of which level you select, this user will have access to all servers within the organization.
|
||||
|
||||
.fieldSetSubmit.buttonSet
|
||||
= submit_tag @organization_user.new_record? ? "Add User" : "Save User", :class => 'button button--positive js-form-submit'
|
||||
.fieldSetSubmit__delete
|
||||
= link_to "Back to user list", [organization, :users], :class => 'button button--neutral'
|
||||
15
app/views/users/edit.html.haml
Normal file
15
app/views/users/edit.html.haml
Normal file
@@ -0,0 +1,15 @@
|
||||
- page_title << "Users"
|
||||
- page_title << "Permissions"
|
||||
.pageHeader
|
||||
%h1.pageHeader__title
|
||||
%span.pageHeader__titlePrevious
|
||||
= @organization.name
|
||||
→
|
||||
Users
|
||||
→
|
||||
Edit user permissions
|
||||
|
||||
= render 'organizations/nav', :active_nav => :users
|
||||
.pageContent.pageContent--compact
|
||||
= render 'form'
|
||||
|
||||
لم تُعرض بعض الملفات لأن الكثير من الملفات تغيرت في هذا الاختلاف إظهار المزيد
المرجع في مشكلة جديدة
حظر مستخدم