Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add defaults for SMTP user and password #2535

Merged
merged 23 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2a75073
feature: add defaults for SMTP configuration
Jan 27, 2025
9b23a41
fix: empty string for user/password causes startup failure
Jan 27, 2025
7e78ff4
fix: smtp server and port are mandatory
Jan 27, 2025
7c514b0
fix: document SMTP values in helm chart
Jan 27, 2025
96d3b35
feature: bump Helm chart version
Jan 27, 2025
2e19c83
fix: helm chart version
Jan 27, 2025
49f99ac
Merge branch 'main' into fix/PZ-4748-optional-mailserver-configuration
hsiliev Jan 27, 2025
97a3e00
fix: helm chart linting error
Jan 27, 2025
1f438db
fix: set user/password as needed for mail session
Jan 28, 2025
a59ac0b
feature: extract constants
Jan 28, 2025
d4d2e19
fix: remove unneeded imports
Jan 28, 2025
d512063
fix: use PostConstruct to initialize mail authentication
Jan 28, 2025
5827329
feature: use config properties for smtp credentials
Jan 28, 2025
00513e2
fix: remove redundant property set
Jan 28, 2025
eecb7fd
fix: remove mailjet environment settings
Jan 28, 2025
1603cd3
feature: disable smtp authentication if no username available
Jan 28, 2025
b55dfc2
Merge branch 'main' into fix/PZ-4748-optional-mailserver-configuration
hsiliev Jan 28, 2025
7a14853
feature: bump helm chart version
Jan 28, 2025
664c23f
fix: spotless code
Jan 28, 2025
b545f49
feature: describe why we disable mail authentication
Jan 29, 2025
8209f10
fix: mail authentication comment
Jan 29, 2025
6294e61
feature: add more descriptive mail credentials defaults
Jan 29, 2025
35cea5a
feature: add comment with link to javaee package docu
Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ KLANTINTERACTIES_API_TOKEN=dummyToken
KVK_API_CLIENT_MP_REST_URL=https://api.kvk.nl/test/
# The (fixed) API key of the KVK test environment. Note that it should not be surrounded by quotes.
KVK_API_KEY=l7xx1f2691f2520d487b902f4e0b57a0b197
# Please replace by your own Mailjet API key and secret key in order to send emails from ZAC.
# You will need to create a Mailjet account. A free account will suffice for testing purposes.
MAILJET_API_KEY=XXX
MAILJET_API_SECRET_KEY=XXX
# Maximum file upload size in MB. Currently cannot be increased much over the default value due to technical limitations.
# We use the Base2 system to calculate the max file size in bytes.
MAX_FILE_SIZE_MB=80
Expand All @@ -86,6 +82,14 @@ SMARTDOCUMENTS_CLIENT_MP_REST_URL=XXX
# For integrating with the production Smart Documents it should not be set, assuming that
# there is a solution in place to sync all users with the Smart Documents environment.
SMARTDOCUMENTS_FIXED_USER_NAME=development-user
# SMTP server address, used to send emails from ZAC. Required
SMTP_SERVER=smtp.example.com
# SMTP server port (587 for TLS, 25 for relaying). Required
SMTP_PORT=587
# SMTP server user name if authentication is required. Optional
SMTP_USERNAME=user
# SMTP server password if authentication is required. Optional
SMTP_PASSWORD=XXX
# Delete any signaleringen older than this number of days when the corresponding admin endpoint is called.
SIGNALERINGEN_DELETE_OLDER_THAN_DAYS=14
# Solr URL
Expand Down
2 changes: 0 additions & 2 deletions .env.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ KLANTINTERACTIES_API_CLIENT_MP_REST_URL=http://localhost:8002
KLANTINTERACTIES_API_TOKEN=dummyToken
KVK_API_CLIENT_MP_REST_URL=op://Dimpact/ZAC-.env-$APP_ENV/KVK/API_CLIENT_MP_REST_URL
KVK_API_KEY=op://Dimpact/ZAC-.env-$APP_ENV/KVK/API_KEY
MAILJET_API_KEY=op://Dimpact/ZAC-.env-$APP_ENV/MAILJET/API_KEY
hsiliev marked this conversation as resolved.
Show resolved Hide resolved
MAILJET_API_SECRET_KEY=op://Dimpact/ZAC-.env-$APP_ENV/MAILJET/API_SECRET_KEY
# We use the Base2 system to calculate the max file size in bytes.
MAX_FILE_SIZE_MB=80
OBJECTS_API_CLIENT_MP_REST_URL=http://host.docker.internal:8010
Expand Down
2 changes: 1 addition & 1 deletion charts/zac/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
apiVersion: v2
name: zaakafhandelcomponent
description: A Helm chart for installing Zaakafhandelcomponent
version: 0.4.6
version: 0.4.7
appVersion: "latest"
icon: https://raw.githubusercontent.com/infonl/dimpact-zaakafhandelcomponent/49f8dee60948282b546ebdfdc5cff6f8bbef0305/docs/manuals/ZAC-gebruikershandleiding/images/pic.svg
dependencies:
Expand Down
10 changes: 5 additions & 5 deletions charts/zac/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ A Helm chart for installing Zaakafhandelcomponent
| gemeente.naam | string | `""` | |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.repository | string | `"ghcr.io/infonl/zaakafhandelcomponent"` | |
| image.tag | string | `"1.12.269@sha256:79178b78f60b25e0052fb5d763dd123f0d2e6a215d14515d55fa1d65c545ca89"` | Overrides the image tag whose default is the chart appVersion. |
| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
| imagePullSecrets | list | `[]` | specifies image pull secrets |
| ingress.annotations | object | `{}` | |
| ingress.className | string | `""` | |
Expand All @@ -66,10 +66,10 @@ A Helm chart for installing Zaakafhandelcomponent
| klantinteractiesApi.url | string | `""` | |
| kvkApi.apiKey | string | `""` | |
| kvkApi.url | string | `""` | |
| mail.smtp.password | string | `""` | |
| mail.smtp.port | string | `"587"` | |
| mail.smtp.server | string | `""` | |
| mail.smtp.username | string | `""` | |
| mail.smtp.password | string | `""` | SMTP server password if authentication is required. Optional |
| mail.smtp.port | string | `"587"` | SMTP server port: 587 for TLS, port 25 for relaying. Required |
| mail.smtp.server | string | `""` | SMTP server host (for example localhost or in-v3.mailjet.com). Required |
| mail.smtp.username | string | `""` | SMTP server username if authentication is required. Optional |
| maxFileSizeMB | int | `80` | Maximum size (in Mega Bytes) of files that can be uploaded. |
| nameOverride | string | `""` | name to use |
| nginx.allowedHosts | string | `""` | |
Expand Down
4 changes: 2 additions & 2 deletions charts/zac/templates/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ data:
{{- end }}
OPEN_FORMS_URL: {{ required "Valid .Values.openForms.url entry required!" .Values.openForms.url }}
SIGNALERINGEN_DELETE_OLDER_THAN_DAYS: {{ required "Valid .Values.signaleringen.deleteOlderThanDays entry required!" .Values.signaleringen.deleteOlderThanDays | quote }}
SMTP_PORT: {{ required "Valid .Values.mail.smtp.port entry required!" .Values.mail.smtp.port | quote }}
SMTP_SERVER: {{ required "Valid .Values.mail.smtp.server entry required!" .Values.mail.smtp.server }}
SMTP_PORT: {{ .Values.mail.smtp.port | quote }}
SMTP_SERVER: {{ .Values.mail.smtp.server }}
{{- if index .Values "opentelemetry-collector" "enabled" }}
SUBSYSTEM_OPENTELEMETRY__SAMPLER_TYPE: {{ ((.Values.opentelemetry_zaakafhandelcomponent).sampler_type) | default "-off" }}
SUBSYSTEM_OPENTELEMETRY__ENDPOINT: {{ ((.Values.opentelemetry_zaakafhandelcomponent).endpoint) | default (printf "http://%s-opentelemetry-collector:4317" .Release.Name) }}
Expand Down
8 changes: 6 additions & 2 deletions charts/zac/templates/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ stringData:
{{- if .Values.smartDocuments.enabled }}
SMARTDOCUMENTS_AUTHENTICATION: "{{ required "Valid .Values.smartDocuments.authentication entry required!" .Values.smartDocuments.authentication | toString }}"
{{- end }}
SMTP_PASSWORD: "{{ .Values.mail.smtp.password | default "" | toString }}"
SMTP_USERNAME: "{{ .Values.mail.smtp.username | default "" | toString }}"
{{- if .Values.mail.smtp.password }}
SMTP_PASSWORD: "{{ .Values.mail.smtp.password | toString }}"
{{- end }}
{{- if .Values.mail.smtp.username }}
SMTP_USERNAME: "{{ .Values.mail.smtp.username | toString }}"
{{- end }}
ZGW_API_SECRET: "{{ required "Valid .Values.zgwApis.secret entry required!" .Values.zgwApis.secret | toString }}"
11 changes: 7 additions & 4 deletions charts/zac/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,16 @@ gemeente:
naam: ""
mail: ""

# mail Configuration email sending connection
# -- Email sending connection. SPF record needs to be properly setup in DNS
mail:
# SMTP server and port are required, spf record needs to be properly setup in DNS
smtp:
server: "" # -- SMTP server host (for example localhost or in-v3.mailjet.com)
port: "587" # -- port 587 for TLS, port 25 for relaying
# -- SMTP server host (for example localhost or in-v3.mailjet.com). Required
server: ""
# -- SMTP server port: 587 for TLS, port 25 for relaying. Required
port: "587"
# -- SMTP server username if authentication is required. Optional
username: ""
# -- SMTP server password if authentication is required. Optional
password: ""

# zgwApis Configuration of ZGW API's provider (Open Zaak)
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,6 @@ services:
- KEYCLOAK_ADMIN_CLIENT_SECRET=zaakafhandelcomponentAdminClientSecret
- KVK_API_CLIENT_MP_REST_URL=${KVK_API_CLIENT_MP_REST_URL:-dummyKvkApiUrl}
- KVK_API_KEY=${KVK_API_KEY:-dummyKvkApiKey}
- MAILJET_API_KEY=${MAILJET_API_KEY:-dummyMailjetApiKey}
- MAILJET_API_SECRET_KEY=${MAILJET_API_SECRET_KEY:-dummyMailjetApiSecretKey}
- OFFICE_CONVERTER_CLIENT_MP_REST_URL=http://office-converter:8080
- OBJECTS_API_CLIENT_MP_REST_URL=http://objecten-api.local:8000
- OBJECTS_API_TOKEN=dummyZacObjectsToken
Expand Down
32 changes: 29 additions & 3 deletions src/main/kotlin/net/atos/zac/mail/MailService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.itextpdf.layout.element.IBlockElement
import com.itextpdf.layout.element.IElement
import com.itextpdf.layout.element.Paragraph
import jakarta.annotation.PostConstruct
import jakarta.annotation.Resource
import jakarta.enterprise.context.ApplicationScoped
import jakarta.enterprise.inject.Instance
Expand Down Expand Up @@ -44,12 +45,14 @@
import nl.info.zac.util.NoArgConstructor
import nl.info.zac.util.toBase64String
import org.apache.commons.lang3.StringUtils
import org.eclipse.microprofile.config.inject.ConfigProperty
import org.htmlcleaner.HtmlCleaner
import org.htmlcleaner.PrettyXmlSerializer
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.time.LocalDate
import java.util.Base64
import java.util.Optional
import java.util.UUID
import java.util.function.Consumer
import java.util.logging.Level
Expand All @@ -58,13 +61,17 @@
@ApplicationScoped
@NoArgConstructor
@AllOpen
@Suppress("LongParameterList")
class MailService @Inject constructor(
private var configuratieService: ConfiguratieService,
private var zgwApiService: ZGWApiService,
private var ztcClientService: ZtcClientService,
private var drcClientService: DrcClientService,
private var mailTemplateHelper: MailTemplateHelper,
private var loggedInUserInstance: Instance<LoggedInUser>
private var loggedInUserInstance: Instance<LoggedInUser>,

@ConfigProperty(name = "SMTP_USERNAME")
private val smtpUsername: Optional<String> = Optional.empty(),
) {

companion object {
Expand All @@ -74,14 +81,33 @@
lateinit var mailSession: Session

// http://www.faqs.org/rfcs/rfc2822.html
private const val SUBJECT_MAXWIDTH = 78
private const val SUBJECT_MAX_WIDTH = 78

private const val FONT_SIZE = 16f
private const val MAIL_VERZENDER = "Afzender"
private const val MAIL_ONTVANGER = "Ontvanger"
private const val MAIL_BIJLAGE = "Bijlage"
private const val MAIL_ONDERWERP = "Onderwerp"
private const val MAIL_BERICHT = "Bericht"

hsiliev marked this conversation as resolved.
Show resolved Hide resolved
// https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html
private const val JAVAMAIL_SMTP_AUTH_KEY = "mail.smtp.auth"
}

@PostConstruct
@Suppress("UnusedPrivateMember")
private fun initPasswordAuthentication() {
// If there's no SMTP_USERNAME environment variable set, we consider this as a case, where SMTP server
// has no authentication. In this case we disable SMTP authentication in the mail session to prevent sending
// the default dummy credentials configured in src/main/resources/wildfly/configure-wildfly.cli
//
// Without the dummy credentials, the SMTP mail session is not properly configured, and:
// - Weld fails to instantiate the mail session and satisfy the @Resource dependency above
// - mail Transport below throws AuthenticationFailedException because of insufficient configuration
if (!smtpUsername.isPresent) {
mailSession.properties.setProperty(JAVAMAIL_SMTP_AUTH_KEY, "false")
LOG.warning { "SMTP authentication disabled" }

Check warning on line 109 in src/main/kotlin/net/atos/zac/mail/MailService.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/net/atos/zac/mail/MailService.kt#L108-L109

Added lines #L108 - L109 were not covered by tests
}
}

val gemeenteMailAdres
Expand All @@ -90,7 +116,7 @@
fun sendMail(mailGegevens: MailGegevens, bronnen: Bronnen): String {
val subject = StringUtils.abbreviate(
resolveVariabelen(mailGegevens.subject, bronnen),
SUBJECT_MAXWIDTH
SUBJECT_MAX_WIDTH
)
val body = resolveVariabelen(mailGegevens.body, bronnen)
val attachments = getAttachments(mailGegevens.attachments)
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/wildfly/configure-wildfly.cli
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ data-source add \
# Create custom ZAC mail session
/subsystem=mail/mail-session=zac:add(jndi-name=java:jboss/mail/zac,debug=false)
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=zac-smtp-binding:add(host=${env.SMTP_SERVER},port=${env.SMTP_PORT})
/subsystem=mail/mail-session=zac/server=smtp:add(outbound-socket-binding-ref=zac-smtp-binding,username=${env.SMTP_USERNAME},password=${env.SMTP_PASSWORD})
# Use dummy credentials as defaults, to properly configure the mail session. Without credentials (or with empty string for user/password):
# - Weld fails to instantiate the mail session and satisfy the @Resource dependency in MailService
# - mail Transport we use throws AuthenticationFailedException because of insufficient configuration
/subsystem=mail/mail-session=zac/server=smtp:add(outbound-socket-binding-ref=zac-smtp-binding,username=${env.SMTP_USERNAME:dummyDefaultUsername},password=${env.SMTP_PASSWORD:dummyDefaultPassword})

# To set the log level to DEBUG (default is INFO) uncomment the following lines.
# Note that this will result in _a lot_ of logging including SessionRegistry sessionRegistry security sensitive data
Expand Down
2 changes: 1 addition & 1 deletion src/test/kotlin/net/atos/zac/mail/MailServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class MailServiceTest : BehaviorSpec({
ztcClientService,
drcClientService,
mailTemplateHelper,
loggedInUserInstance,
loggedInUserInstance
)

beforeEach {
Expand Down
Loading