1
0
مراية لـ https://github.com/postalserver/postal.git تم المزامنة 2025-12-01 05:43:04 +00:00

initial commit from appmail

هذا الالتزام موجود في:
Adam Cooke
2017-04-19 13:07:25 +01:00
الأصل a3eff53792
التزام 2fdba0ceb5
474 ملفات معدلة مع 51228 إضافات و0 حذوفات

عرض الملف

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

عرض الملف

@@ -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 &mdash; 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' : '']

عرض الملف

@@ -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' : '']

عرض الملف

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

عرض الملف

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

عرض الملف

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

عرض الملف

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

عرض الملف

@@ -0,0 +1,35 @@
- page_title << "Choose mail server"
.pageHeader
%h1.pageHeader__title
%span.pageHeader__titlePrevious
= @organization.name
&rarr;
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'

عرض الملف

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

عرض الملف

@@ -0,0 +1,11 @@
- page_title << "Build new mail server"
.pageHeader
%h1.pageHeader__title
%span.pageHeader__titlePrevious
= @organization.name
&rarr;
Build a new mail server
= render 'organizations/nav', :active_nav => :servers
.pageContent.pageContent--compact
= render 'form'

عرض الملف

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

عرض الملف

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

عرض الملف

@@ -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")} &rarr;
%li Today at #{Time.now.strftime("%l%P")}
- else
%li #{@first_date.to_date.to_s(:long)} &rarr;
%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

عرض الملف

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