1
0
مراية لـ https://github.com/postalserver/postal.git تم المزامنة 2026-03-04 06:44:06 +00:00

Compare commits

13 الالتزامات
3.0.2 ... 3.1.1

المؤلف SHA1 الرسالة التاريخ
github-actions[bot]
4c27baee7f chore(main): release 3.1.1 (#2859)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-08 18:32:33 +00:00
Adam Cooke
9399e32234 fix: don't override paths in dockerfile
This allows for these paths to continue to be set in the config file or environment variable while still maintaining the default of having the default paths in the same directory as the postal config file.
2024-03-08 16:40:58 +00:00
Adam Cooke
22dcd4901f test(smtp-sender): add more tests for AUTH LOGIN
This adds tests for AUTH LOGIN when the username is not provided on the initial line
2024-03-08 14:08:53 +00:00
Adam Cooke
6df963651d Merge pull request #2850 from postalserver/release-please--branches--main
chore(main): release 3.1.0
2024-03-06 14:35:57 +00:00
github-actions[bot]
4acfffd1d8 chore(main): release 3.1.0 2024-03-06 14:09:55 +00:00
Adam Cooke
e2d642c0cb fix(message-dequeuer): ensure SMTP endpoints are sent to SMTP sender appropriately
closes #2853
2024-03-06 14:09:29 +00:00
Adam Cooke
4e1deb2d2a fix(web-server): allow for trusted proxies not be set 2024-03-06 14:05:44 +00:00
Adam Cooke
d1e5b68200 fix(smtp-server): listen on all interfaces by default
This is the same behaviour as when using v1 configuration. Unlike the
web server which is proxied, most people are going to need this so having
the default remain seems like the easiest path for upgrades.

see #2852
2024-03-06 13:23:50 +00:00
Adam Cooke
33513a77c0 fix(ui): fixes typo on queue page 2024-03-05 22:57:39 +00:00
Adam Cooke
3785c99851 feat: configurable trusted proxies for web requests 2024-03-05 22:54:19 +00:00
Adam Cooke
9bf6152060 fix(smtp-server): reset ansi sequence after logging 2024-03-05 22:13:43 +00:00
Adam Cooke
0dc7359431 fix(smtp-server): remove ::ffff: from the start of ipv4 addresses 2024-03-05 22:13:42 +00:00
Adam Cooke
2c20ba65f6 style(rubocop): use _ when not using a variable in helm config exporter 2024-03-05 22:13:38 +00:00
17 ملفات معدلة مع 109 إضافات و35 حذوفات

عرض الملف

@@ -1,3 +1,3 @@
{ {
".": "3.0.2" ".": "3.1.1"
} }

عرض الملف

@@ -2,6 +2,40 @@
This file contains all the latest changes and updates to Postal. This file contains all the latest changes and updates to Postal.
## [3.1.1](https://github.com/postalserver/postal/compare/3.1.0...3.1.1) (2024-03-08)
### Bug Fixes
* don't override paths in dockerfile ([9399e32](https://github.com/postalserver/postal/commit/9399e3223467cdacd010e70b58ad6093e128213d))
### Tests
* **smtp-sender:** add more tests for AUTH LOGIN ([22dcd49](https://github.com/postalserver/postal/commit/22dcd4901f188915cf4b3c758c6f2fc637a4e1e3))
## [3.1.0](https://github.com/postalserver/postal/compare/3.0.2...3.1.0) (2024-03-06)
### Features
* configurable trusted proxies for web requests ([3785c99](https://github.com/postalserver/postal/commit/3785c998513c634d225b489ccb43e926ce3f270a))
### Bug Fixes
* **message-dequeuer:** ensure SMTP endpoints are sent to SMTP sender appropriately ([e2d642c](https://github.com/postalserver/postal/commit/e2d642c0cbf443550886d90abc3a6edf3e4bc4fc)), closes [#2853](https://github.com/postalserver/postal/issues/2853)
* **smtp-server:** listen on all interfaces by default ([d1e5b68](https://github.com/postalserver/postal/commit/d1e5b68200ea4b9710cc8714afb3271bad1f4f66)), closes [#2852](https://github.com/postalserver/postal/issues/2852)
* **smtp-server:** remove ::ffff: from the start of ipv4 addresses ([0dc7359](https://github.com/postalserver/postal/commit/0dc7359431001c9ef1222913f8d1344093397596))
* **smtp-server:** reset ansi sequence after logging ([9bf6152](https://github.com/postalserver/postal/commit/9bf6152060ffb8b611b66818c1d1ac7c929b7ffe))
* **ui:** fixes typo on queue page ([33513a7](https://github.com/postalserver/postal/commit/33513a77c0df24d832ab7ed5237d68e2b1bde887))
* **web-server:** allow for trusted proxies not be set ([4e1deb2](https://github.com/postalserver/postal/commit/4e1deb2d2aeb61d9dddb3729916411c94e73c1c6))
### Styles
* **rubocop:** use _ when not using a variable in helm config exporter ([2c20ba6](https://github.com/postalserver/postal/commit/2c20ba65f64ccb0f8174e3f523dedb3806478782))
## [3.0.2](https://github.com/postalserver/postal/compare/3.0.1...3.0.2) (2024-03-05) ## [3.0.2](https://github.com/postalserver/postal/compare/3.0.1...3.0.2) (2024-03-05)

عرض الملف

@@ -48,9 +48,6 @@ RUN echo $VERSION > VERSION
# Set paths for when running in a container # Set paths for when running in a container
ENV POSTAL_CONFIG_FILE_PATH=/config/postal.yml ENV POSTAL_CONFIG_FILE_PATH=/config/postal.yml
ENV POSTAL_SIGNING_KEY_PATH=/config/signing.key
ENV SMTP_SERVER_TLS_CERTIFICATE_PATH=/config/smtp.cert
ENV SMTP_SERVER_TLS_PRIVATE_KEY_PATH=/config/smtp.key
# Set the CMD # Set the CMD
ENTRYPOINT [ "/docker-entrypoint.sh" ] ENTRYPOINT [ "/docker-entrypoint.sh" ]

عرض الملف

@@ -16,7 +16,7 @@ gem "hashie"
gem "highline", require: false gem "highline", require: false
gem "kaminari" gem "kaminari"
gem "klogger-logger" gem "klogger-logger"
gem "konfig-config", "~> 2.0" gem "konfig-config", "~> 3.0"
gem "mail" gem "mail"
gem "moonrope" gem "moonrope"
gem "mysql2" gem "mysql2"

عرض الملف

@@ -149,7 +149,7 @@ GEM
concurrent-ruby (>= 1.0, < 2.0) concurrent-ruby (>= 1.0, < 2.0)
json json
rouge (>= 3.30, < 5.0) rouge (>= 3.30, < 5.0)
konfig-config (2.1.1) konfig-config (3.0.0)
hashie hashie
loofah (2.22.0) loofah (2.22.0)
crass (~> 1.0.2) crass (~> 1.0.2)
@@ -353,7 +353,7 @@ DEPENDENCIES
jquery-rails jquery-rails
kaminari kaminari
klogger-logger klogger-logger
konfig-config (~> 2.0) konfig-config (~> 3.0)
mail mail
moonrope moonrope
mysql2 mysql2

عرض الملف

@@ -163,7 +163,7 @@ module MessageDequeuer
case queued_message.message.endpoint case queued_message.message.endpoint
when SMTPEndpoint when SMTPEndpoint
sender = @state.sender_for(SMTPSender, queued_message.message.recipient_domain, nil, servers: [queued_message.message.endpoint]) sender = @state.sender_for(SMTPSender, queued_message.message.recipient_domain, nil, servers: [queued_message.message.endpoint.to_smtp_client_server])
when HTTPEndpoint when HTTPEndpoint
sender = @state.sender_for(HTTPSender, queued_message.message.endpoint) sender = @state.sender_for(HTTPSender, queued_message.message.endpoint)
when AddressEndpoint when AddressEndpoint

عرض الملف

@@ -112,21 +112,23 @@ module SMTPServer
# Accept the connection # Accept the connection
new_io = io.accept new_io = io.accept
increment_prometheus_counter :postal_smtp_server_connections_total increment_prometheus_counter :postal_smtp_server_connections_total
# Get the client's IP address and strip `::ffff:` for consistency.
client_ip_address = new_io.remote_address.ip_address.sub(/\A::ffff:/, "")
if Postal::Config.smtp_server.proxy_protocol? if Postal::Config.smtp_server.proxy_protocol?
# If we are using the haproxy proxy protocol, we will be sent the # If we are using the haproxy proxy protocol, we will be sent the
# client's IP later. Delay the welcome process. # client's IP later. Delay the welcome process.
client = Client.new(nil) client = Client.new(nil)
if Postal::Config.smtp_server.log_connections? if Postal::Config.smtp_server.log_connections?
client.logger&.debug "Connection opened from #{new_io.remote_address.ip_address}" client.logger&.debug "Connection opened from #{client_ip_address}"
end end
else else
# We're not using the proxy protocol so we already know the client's IP # We're not using the proxy protocol so we already know the client's IP
client = Client.new(new_io.remote_address.ip_address) client = Client.new(client_ip_address)
if Postal::Config.smtp_server.log_connections? if Postal::Config.smtp_server.log_connections?
client.logger&.debug "Connection opened from #{new_io.remote_address.ip_address}" client.logger&.debug "Connection opened from #{client_ip_address}"
end end
# We know who the client is, welcome them. # We know who the client is, welcome them.
client.logger&.debug "Client identified as #{new_io.remote_address.ip_address}" client.logger&.debug "Client identified as #{client_ip_address}"
new_io.print("220 #{Postal::Config.postal.smtp_hostname} ESMTP Postal/#{client.trace_id}") new_io.print("220 #{Postal::Config.postal.smtp_hostname} ESMTP Postal/#{client.trace_id}")
end end
# Register the client and its socket with nio4r # Register the client and its socket with nio4r
@@ -205,7 +207,7 @@ module SMTPServer
result = [result] unless result.is_a?(Array) result = [result] unless result.is_a?(Array)
result.compact.each do |iline| result.compact.each do |iline|
client.logger&.debug "\e[34m=> #{iline.strip}" client.logger&.debug "\e[34m=> #{iline.strip}\e[0m"
begin begin
io.write(iline.to_s + "\r\n") io.write(iline.to_s + "\r\n")
io.flush io.flush

عرض الملف

@@ -47,4 +47,8 @@ class SMTPEndpoint < ApplicationRecord
routes.each { |r| r.update(endpoint: nil, mode: "Reject") } routes.each { |r| r.update(endpoint: nil, mode: "Reject") }
end end
def to_smtp_client_server
SMTPClient::Server.new(hostname, port: port || 25, ssl_mode: ssl_mode)
end
end end

عرض الملف

@@ -8,7 +8,7 @@
- if @messages.empty? - if @messages.empty?
.pageContent--compact .pageContent--compact
.noData.noData--clean .noData.noData--clean
%h2.noData__title Your queue is current empty. %h2.noData__title Your queue is currently empty.
%p.noData__text %p.noData__text
Messages which haven't yet been delivered successfully will appear in your queue until Messages which haven't yet been delivered successfully will appear in your queue until
we've delivered them or we've given up trying. we've delivered them or we've given up trying.

عرض الملف

@@ -1,15 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
module Rack Rack::Request.ip_filter = lambda { |ip|
class Request if Postal::Config.postal.trusted_proxies&.any? { |net| net.include?(ip) } ||
ip.match(/\A127\.0\.0\.1\Z|\A::1\Z|\Afd[0-9a-f]{2}:.+|\Alocalhost\Z|\Aunix\Z|\Aunix:/i)
module Helpers true
else
def trusted_proxy?(ip) false
ip =~ /^127\.0\.0\.1$|^localhost$|^unix$$/i
end
end
end end
end }

عرض الملف

@@ -17,6 +17,7 @@ This document contains all the environment variables which are available for thi
| `POSTAL_USE_RESENT_SENDER_HEADER` | Boolean | Append a Resend-Sender header to all outgoing e-mails | true | | `POSTAL_USE_RESENT_SENDER_HEADER` | Boolean | Append a Resend-Sender header to all outgoing e-mails | true |
| `POSTAL_SIGNING_KEY_PATH` | String | Path to the private key used for signing | config/postal/signing.key | | `POSTAL_SIGNING_KEY_PATH` | String | Path to the private key used for signing | config/postal/signing.key |
| `POSTAL_SMTP_RELAYS` | Array of strings | An array of SMTP relays in the format of smtp://host:port | | | `POSTAL_SMTP_RELAYS` | Array of strings | An array of SMTP relays in the format of smtp://host:port | |
| `POSTAL_TRUSTED_PROXIES` | Array of strings | An array of IP addresses to trust for proxying requests to Postal (in addition to localhost addresses) | |
| `WEB_SERVER_DEFAULT_PORT` | Integer | The default port the web server should listen on unless overriden by the PORT environment variable | 5000 | | `WEB_SERVER_DEFAULT_PORT` | Integer | The default port the web server should listen on unless overriden by the PORT environment variable | 5000 |
| `WEB_SERVER_DEFAULT_BIND_ADDRESS` | String | The default bind address the web server should listen on unless overriden by the BIND_ADDRESS environment variable | 127.0.0.1 | | `WEB_SERVER_DEFAULT_BIND_ADDRESS` | String | The default bind address the web server should listen on unless overriden by the BIND_ADDRESS environment variable | 127.0.0.1 |
| `WEB_SERVER_MAX_THREADS` | Integer | The maximum number of threads which can be used by the web server | 5 | | `WEB_SERVER_MAX_THREADS` | Integer | The maximum number of threads which can be used by the web server | 5 |

عرض الملف

@@ -27,6 +27,8 @@ postal:
signing_key_path: config/postal/signing.key signing_key_path: config/postal/signing.key
# An array of SMTP relays in the format of smtp://host:port # An array of SMTP relays in the format of smtp://host:port
smtp_relays: [] smtp_relays: []
# An array of IP addresses to trust for proxying requests to Postal (in addition to localhost addresses)
trusted_proxies: []
web_server: web_server:
# The default port the web server should listen on unless overriden by the PORT environment variable # The default port the web server should listen on unless overriden by the PORT environment variable

عرض الملف

@@ -68,7 +68,8 @@ module Postal
string :signing_key_path do string :signing_key_path do
description "Path to the private key used for signing" description "Path to the private key used for signing"
default "config/postal/signing.key" default "$config-file-root/signing.key"
transform { |v| Postal.substitute_config_file_root(v) }
end end
string :smtp_relays do string :smtp_relays do
@@ -84,6 +85,12 @@ module Postal
} }
end end
end end
string :trusted_proxies do
array
description "An array of IP addresses to trust for proxying requests to Postal (in addition to localhost addresses)"
transform { |ip| IPAddr.new(ip) }
end
end end
group :web_server do group :web_server do
@@ -227,7 +234,7 @@ module Postal
string :default_bind_address do string :default_bind_address do
description "The default bind address the SMTP server should listen on unless overriden by the BIND_ADDRESS environment variable" description "The default bind address the SMTP server should listen on unless overriden by the BIND_ADDRESS environment variable"
default "127.0.0.1" default "::"
end end
integer :default_health_server_port do integer :default_health_server_port do
@@ -247,12 +254,14 @@ module Postal
string :tls_certificate_path do string :tls_certificate_path do
description "The path to the SMTP server's TLS certificate" description "The path to the SMTP server's TLS certificate"
default "config/postal/smtp.cert" default "$config-file-root/smtp.cert"
transform { |v| Postal.substitute_config_file_root(v) }
end end
string :tls_private_key_path do string :tls_private_key_path do
description "The path to the SMTP server's TLS private key" description "The path to the SMTP server's TLS private key"
default "config/postal/smtp.key" default "$config-file-root/smtp.key"
transform { |v| Postal.substitute_config_file_root(v) }
end end
string :tls_ciphers do string :tls_ciphers do
@@ -496,4 +505,14 @@ module Postal
end end
end end
class << self
def substitute_config_file_root(string)
return if string.nil?
string.gsub(/\$config-file-root/i, File.dirname(Postal.config_file_path))
end
end
end end

عرض الملف

@@ -12,7 +12,7 @@ module Postal
@schema.groups.each do |group_name, group| @schema.groups.each do |group_name, group|
path << group_name path << group_name
group.attributes.each do |name, attr| group.attributes.each do |name, _|
env_var = Konfig::Sources::Environment.path_to_env_var(path + [name]) env_var = Konfig::Sources::Environment.path_to_env_var(path + [name])
contents << <<~VAR.strip contents << <<~VAR.strip
{{ include "app.envVar" (dict "name" "#{env_var}" "spec" .Values.postal.#{path.join('.')}.#{name} "root" . ) }} {{ include "app.envVar" (dict "name" "#{env_var}" "spec" .Values.postal.#{path.join('.')}.#{name} "root" . ) }}

عرض الملف

@@ -422,7 +422,7 @@ module MessageDequeuer
it "gets a sender from the state and sends the message to it" do it "gets a sender from the state and sends the message to it" do
smtp_sender_double = double("SMTPSender") smtp_sender_double = double("SMTPSender")
expect(smtp_sender_double).to receive(:send_message).with(queued_message.message).and_return(SendResult.new) expect(smtp_sender_double).to receive(:send_message).with(queued_message.message).and_return(SendResult.new)
expect(state).to receive(:sender_for).with(SMTPSender, message.recipient_domain, nil, { servers: [endpoint] }).and_return(smtp_sender_double) expect(state).to receive(:sender_for).with(SMTPSender, message.recipient_domain, nil, { servers: [kind_of(SMTPClient::Server)] }).and_return(smtp_sender_double)
processor.process processor.process
end end
end end

عرض الملف

@@ -17,7 +17,9 @@ module Postal
# by the schema itself. Otherwise, we might see a value returned that # by the schema itself. Otherwise, we might see a value returned that
# looks correct but is actually the default rather than the value from # looks correct but is actually the default rather than the value from
# config file. # config file.
allow_any_instance_of(Konfig::SchemaAttribute).to receive(:default).and_return(nil) allow_any_instance_of(Konfig::SchemaAttribute).to receive(:default) do |a|
a.array? ? [] : nil
end
end end
let(:source) { described_class.new(SOURCE_CONFIG) } let(:source) { described_class.new(SOURCE_CONFIG) }

عرض الملف

@@ -55,6 +55,26 @@ module SMTPServer
it "requests the username" do it "requests the username" do
expect(client.handle("AUTH LOGIN")).to eq("334 VXNlcm5hbWU6") expect(client.handle("AUTH LOGIN")).to eq("334 VXNlcm5hbWU6")
end end
it "requests a password after a username" do
client.handle("AUTH LOGIN")
expect(client.handle("xx")).to eq("334 UGFzc3dvcmQ6")
end
it "authenticates and returns a response if the password is correct" do
client.handle("AUTH LOGIN")
client.handle("xx")
credential = create(:credential, type: "SMTP")
password = Base64.encode64(credential.key)
expect(client.handle(password)).to match(/235 Granted for/)
end
it "returns an error when an invalid credential is provided" do
client.handle("AUTH LOGIN")
client.handle("xx")
password = Base64.encode64("xx")
expect(client.handle(password)).to eq("535 Invalid credential")
end
end end
context "when a username is provided on the first line" do context "when a username is provided on the first line" do
@@ -71,9 +91,7 @@ module SMTPServer
expect(client.handle(password)).to match(/235 Granted for/) expect(client.handle(password)).to match(/235 Granted for/)
expect(client.credential).to eq credential expect(client.credential).to eq credential
end end
end
context "when invalid credentials are provided" do
it "returns an error and resets the state" do it "returns an error and resets the state" do
username = Base64.encode64("xx") username = Base64.encode64("xx")
password = Base64.encode64("xx") password = Base64.encode64("xx")