Skip to content
Open

Dev #386

Show file tree
Hide file tree
Changes from all commits
Commits
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
96 changes: 96 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# This file is a "template" of what your .env file should look like.
# Set variables here that may be different on each deployment target of the app,
# e.g. development, staging, production.
#
# On `composer install`/`composer update`, this file is copied to `.env` (unless
# it already exists) and PHPLIST_SECRET is replaced with a freshly generated value.
#
# https://symfony.com/doc/current/configuration.html#configuring-environment-variables-in-env-files

PHPLIST_DATABASE_DRIVER=pdo_mysql
PHPLIST_DATABASE_PATH=
PHPLIST_DATABASE_HOST=127.0.0.1
PHPLIST_DATABASE_PORT=3306
PHPLIST_DATABASE_NAME=phplistdb
PHPLIST_DATABASE_USER=phplist
PHPLIST_DATABASE_PASSWORD=phplist
DATABASE_PREFIX=phplist_
LIST_TABLE_PREFIX=listattr_
PHPLIST_ADMIN_PASSWORD=admin

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not ship a usable default administrator password.

When .env is absent, src/Core/Bootstrap.php:162-170 loads .env.dist. This can make admin the administrator password. Replace this value with a non-operational placeholder and fail fast until deployment provides a strong password. Alternatively, stop loading .env.dist as a runtime fallback.

Proposed template change
-PHPLIST_ADMIN_PASSWORD=admin
+PHPLIST_ADMIN_PASSWORD=__SET_DURING_DEPLOYMENT__
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 19-19: [UnorderedKey] The PHPLIST_ADMIN_PASSWORD key should go before the PHPLIST_DATABASE_DRIVER key

(UnorderedKey)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.env.dist at line 19, Replace the usable PHPLIST_ADMIN_PASSWORD value in the
environment template with a non-operational placeholder, and update the
bootstrap logic around the .env fallback (the code loading .env.dist near
Bootstrap initialization) to fail fast when that placeholder or an otherwise
missing deployment password is used, ensuring deployment must provide a strong
administrator password.


APP_DEV_VERSION=0
APP_DEV_EMAIL=dev@dev.com
APP_POWERED_BY_PHPLIST=0
PREFERENCEPAGE_SHOW_PRIVATE_LISTS=0

API_BASE_URL=http://api.phplist.local/
FRONT_END_BASE_URL=http://frontend.phplist.local

PARALLER_USE_WITH_PHPLIST3=0

# Email configuration
MAILER_FROM=noreply@phplist.com
MAILER_DSN=null://null
CONFIRMATION_URL=http://api.phplist.local/api/v2/subscriber/confirm/
SUBSCRIPTION_CONFIRMATION_URL=http://api.phplist.local/api/v2/subscription/confirm/
PASSWORD_RESET_URL=https://example.com/reset/
SHOW_UNSUBSCRIBELINK=1

# Bounce email settings
BOUNCE_EMAIL=bounce@phplist.com
BOUNCE_IMAP_PASS=bounce@phplist.com
BOUNCE_IMAP_HOST=imap.phplist.com
BOUNCE_IMAP_PORT=993
BOUNCE_IMAP_ENCRYPTION=ssl
BOUNCE_IMAP_MAILBOX=/var/spool/mail/bounces
BOUNCE_IMAP_MAILBOX_NAME=INBOX,ONE_MORE
BOUNCE_IMAP_PROTOCOL=imap
BOUNCE_IMAP_UNSUBSCRIBE_THRESHOLD=5
BOUNCE_IMAP_BLACKLIST_THRESHOLD=3
BOUNCE_IMAP_PURGE=0
BOUNCE_IMAP_PURGE_UNPROCESSED=0

# Messenger configuration for asynchronous processing
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=true

# A secret key that's used to generate certain security-related tokens
PHPLIST_SECRET=%s
VERIFY_SSL=1
Comment on lines +56 to +58

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)(\.env\.dist|Bootstrap\.php|composer\.json)$|Dotenv' || true

echo
echo "== .env.dist relevant lines =="
if [ -f .env.dist ]; then
  nl -ba .env.dist | sed -n '45,65p'
fi

echo
echo "== composer scripts and dotenv package version =="
if [ -f composer.json ]; then
  sed -n '1,220p' composer.json | rg -n '"scripts"|"symfony/dotenv"|"require-dev":|"dotenv"' -C 4 || true
fi

echo
echo "== search for env.dist or Dotenv usage =="
rg -n 'env\.dist|Dotenv|loadEnv|PHPLIST_SECRET' -S . --glob '!vendor/**' --glob '!node_modules/**' || true

Repository: phpList/core

Length of output: 282


🌐 Web query:

Symfony Dotenv 6.4 loadEnv .env.dist fallback behavior source Dotenv.php

💡 Result:

In Symfony 6.4, the loadEnv method in the Dotenv component implements a specific fallback mechanism for the.env file. According to the source code (Dotenv.php), if the primary.env file is missing, the component will automatically attempt to load the.env.dist file if it exists [1][2][3]. The specific logic within loadEnv is implemented as follows: if (is_file($path) ||!is_file($p = "$path.dist")) { $this->doLoad($overrideExistingVars, [$path]); } else { $this->doLoad($overrideExistingVars, [$p]); } This means that if the provided path (usually.env) is not found (is_file($path) is false) AND a file with a.dist extension exists at that location (.env.dist), the Dotenv component will load the.env.dist file instead [1][2][4]. Key points regarding this behavior: - Fallback Priority: The primary.env file always takes precedence. The.env.dist file is only used as a fallback when the primary.env file is absent [1][3]. - Modern Usage: While this fallback exists for compatibility, modern Symfony best practices emphasize that.env should be committed to the repository containing non-sensitive default values, effectively replacing the historical role of.env.dist [5]. - Overriding: This loading process respects the overrideExistingVars parameter, which determines whether values from these files can override environment variables already set by the system [6][1]. System environment variables generally always have the highest precedence and cannot be overridden by Dotenv files unless explicitly configured [5][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .env.dist relevant lines =="
if [ -f .env.dist ]; then
  awk '{printf "%6d  %s\n", NR, $0}' .env.dist | sed -n '45,65p'
fi

echo
echo "== composer relevant snippets =="
if [ -f composer.json ]; then
  python3 - <<'PY'
import json, re, sys
from pathlib import Path
p=Path('composer.json')
text=p.read_text()
try: data=json.loads(text)
except Exception as e:
    print("json_parse_error", repr(e))
    for line in text.splitlines()[:240]:
        if any(s in line for s in ['scripts', 'symfony/dotenv', '"dotenv"', 'require-dev', 'require']):
            print(line)
    sys.exit(0)
print("scripts:", data.get("scripts"))
print("symfony/dotenv:", data.get("require", {}).get("symfony/dotenv"), data.get("require-dev", {}).get("symfony/dotenv"))
for key in ("require","require-dev"):
    for pk,ve in data.get(key,{}).items():
        if "dot" in pk.lower() or "symfony" in pk.lower():
            print(key, pk, ve)
PY
fi

echo
echo "== Bootstrap.php outlines/snippets =="
if [ -f src/Core/Bootstrap.php ]; then
  wc -l src/Core/Bootstrap.php
  rg -n 'Dotenv|loadEnv|env\.dist|load\\(|PHPLIST_SECRET|try|catch' src/Core/Bootstrap.php -C 8
fi

echo
echo "== repository-wide env.dist/env.load/fallback =="
rg -n 'env\.dist|loadEnv\\(|new Dotenv|Dotenv::|PHPLIST_SECRET|secret' -S src composer.json .env.dist --glob '!vendor/**' --glob '!node_modules/**' || true

Repository: phpList/core

Length of output: 2686


🌐 Web query:

Symfony Dotenv load .env.dist if .env missing loadEnv $projectRoot/.env

💡 Result:

In Symfony, the Dotenv component's loadEnv method is designed to handle environment file loading automatically, including a fallback mechanism for the.env.dist file [1][2][3]. When calling $dotenv->loadEnv($projectRoot. '/.env'), the component follows these behaviors: 1. Fallback to.env.dist: If a.env file does not exist, the component will load.env.dist if it is present [1][3]. This was implemented to allow projects to define environment variables in.env.dist when a local.env file is intentionally omitted [1]. 2. Loading Order: The loadEnv method loads files in a specific order, where subsequent files can override variables defined in previously loaded files [2][4][3]. The standard sequence (subject to file existence) is: -.env (or.env.dist if.env is missing) [2][3] -.env.local (skipped for the "test" environment) [2][4][3] -.env.$env (based on the APP_ENV variable) [2][3] -.env.$env.local [2][3] This logic is typically invoked in the project's bootstrap file (e.g., config/bootstrap.php) to ensure environment variables are populated before the application kernel or other components are initialized [5][3]. Note that actual system environment variables always take precedence over values defined in these.env files [6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .env.dist relevant lines =="
if [ -f .env.dist ]; then
  awk '{printf "%6d  %s\n", NR, $0}' .env.dist | sed -n '45,65p'
fi

echo
echo "== composer relevant snippets =="
if [ - f composer.json ]; then
  python3 - <<'PY'
import json, re, sys
from pathlib import Path
p=Path('composer.json')
text=p.read_text()
try: data=json.loads(text)
except Exception as e:
    print("json_parse_error", repr(e))
    for line in text.splitlines()[:240]:
        if any(s in line for s in ['scripts', 'symfony/dotenv', '"dotenv"', 'require-dev', 'require']):
            print(line)
    sys.exit(0)
print("scripts:", data.get("scripts"))
print("symfony/dotenv:", data.get("require", {}).get("symfony/dotenv"), data.get("require-dev", {}).get("symfony/dotenv"))
for key in ("require","require-dev"):
    for pk,ve in data.get(key,{}).items():
        if "dot" in pk.lower() or "symfony" in pk.lower():
            print(key, pk, ve)
PY
fi

echo
echo "== Bootstrap.php outlines/snippets =="
if [ -f src/Core/Bootstrap.php ]; then
  wc -l src/Core/Bootstrap.php
  rg -n 'Dotenv|loadEnv|env\.dist|load\\(|PHPLIST_SECRET|try|catch' src/Core/Bootstrap.php -C 8
fi

echo
echo "== repository-wide env.dist/env.load/fallback =="
rg -n 'env\.dist|loadEnv\\(|new Dotenv|Dotenv::|PHPLIST_SECRET|secret' -S src composer.json .env.dist --glob '!vendor/**' --glob '!node_modules/**' || true

Repository: phpList/core

Length of output: 1181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Bootstrap.php Bootstrap.php matches =="
rg -n 'Dotenv|loadEnv|PHPLIST_SECRET|throw new|secret' src/Core/Bootstrap.php composer.json --glob '!vendor/**' --glob '!node_modules/**' || true

echo
echo "== src/Core/Bootstrap.php line 1-180 =="
awk '{printf "%6d  %s\n", NR, $0}' src/Core/Bootstrap.php | sed -n '1,180p'

echo
echo "== src/Core/Bootstrap.php exact Dotenv/loadEnv snippets =="
awk '{printf "%6d  %s\n", NR, $0}' src/Core/Bootstrap.php | sed -n '/Dotenv/,+8p;/loadEnv/,+12p;/PHPLIST_SECRET/,+12p'

Repository: phpList/core

Length of output: 10010


🌐 Web query:

raw github symfony dotenv 6.4 src Symfony Component Dotenv Dotenv.php is_file projectRoot .env.dist

💡 Result:

In Symfony's Dotenv component (including version 6.4), the logic regarding .env.dist is implemented within the loadEnv() method of the Dotenv.php class [1][2][3]. The relevant code snippet typically appears as follows: if (is_file($path) ||!is_file($p = "$path.dist")) { $this->doLoad($overrideExistingVars, [$path]); } else { $this->doLoad($overrideExistingVars, [$p]); } This logic performs the following behavior: 1. It checks if the primary environment file (defined by $path, usually .env) exists using is_file($path) [1][2]. 2. If the primary file exists, it loads that file. 3. If the primary file does not exist, it checks if a corresponding .dist file exists (e.g., .env.dist) using is_file($p = "$path.dist") [1][2]. 4. If the .dist file exists (and the primary file does not), it loads the .dist file instead [1][2]. This mechanism is designed to support projects that provide a template file (like .env.dist or .env.example) for developers to copy and populate while ensuring the application can still load configuration if the main file is missing [1][2].

Citations:


Don’t let .env.dist become the signed secret.

loadEnvironmentVariables() also triggers Dotenv when .env.dist exists, and Symfony Dotenv will load .env.dist if .env is absent. Since PHPLIST_SECRET=%s, anyone missing Composer script output can run with the literal template value as the signing secret. Keep .env.dist strictly template-only and fail fast unless a real generated/supplied secret exists.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.env.dist around lines 55 - 57, Update the environment-loading flow around
loadEnvironmentVariables so .env.dist remains template-only and PHPLIST_SECRET
never accepts the literal “%s” placeholder. Require a non-placeholder generated
or explicitly supplied secret, and fail fast when it is missing before security
tokens are used.

Source: MCP tools


APP_PHPLIST_ISP_CONF_PATH=/etc/phplist.conf

# Message sending
MAILQUEUE_BATCH_SIZE=5
MAILQUEUE_BATCH_PERIOD=5
MAILQUEUE_THROTTLE=5
MESSAGING_MAX_PROCESS_TIME=600
MAX_MAILSIZE=209715200
DEFAULT_MESSAGEAGE=691200
USE_MANUAL_TEXT_PART=0
MESSAGING_BLACKLIST_GRACE_TIME=600
GOOGLE_SENDERID=
USE_AMAZONSES=0
USE_PRECEDENCE_HEADER=0
EMBEDEXTERNALIMAGES=0
EMBEDUPLOADIMAGES=0
EXTERNALIMAGE_MAXAGE=0
EXTERNALIMAGE_TIMEOUT=30
EXTERNALIMAGE_MAXSIZE=204800
FORWARD_ALTERNATIVE_CONTENT=0
EMAILTEXTCREDITS=0
ALWAYS_ADD_USERTRACK=1
SEND_LISTADMIN_COPY=0

FORWARD_EMAIL_PERIOD="1 minute"
FORWARD_EMAIL_COUNT=1
FORWARD_PERSONAL_NOTE_SIZE=0
FORWARD_FRIEND_COUNT_ATTRIBUTE=
KEEPFORWARDERATTRIBUTES=0

UPLOADIMAGES_DIR=uploadimages
PHPLIST_UPLOADS_MAX_SIZE=5M

PUBLIC_SCHEMA=https
PHPLIST_ATTACHMENT_DOWNLOAD_URL=https://example.com/download/
PHPLIST_ATTACHMENT_REPOSITORY_PATH=/tmp
MAX_AVATAR_SIZE=100000
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
/composer.lock
/config/bundles.yml
/config/config_modules.yml
/config/parameters.yml
/.env
/.env.local
/.env.*.local
/config/routing_modules.yml
/nbproject
/var/
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).

### Added
- Graylog integration for centralized logging (#TBD)
- `symfony/dotenv` support: configuration values are now read from a `.env` file (generated from `.env.dist` on install/update), in addition to real environment variables (#TBD)

### Changed
- `config/parameters.yml.dist` no longer contains inline `env(VAR): default` fallbacks; defaults now live in `.env.dist` (#TBD)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the current parameters template path.

This entry names config/parameters.yml.dist, while the migrated template and ScriptHandler now use config/parameters.yml. Use the current path or explicitly describe the rename.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 13, Update the changelog entry to reference the current
parameters template path, config/parameters.yml, or explicitly state that
config/parameters.yml.dist was renamed to config/parameters.yml; keep the
description of defaults moving to .env.dist unchanged.


### Deprecated

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ this code.
The phpList application is configured so that the built-in PHP web server can
run in development and testing mode, while Apache can run in production mode.

Please first set the database credentials in `config/parameters.yml`.
Please first set the database credentials in `.env` (created from `.env.dist` on `composer install`/`composer update`).

### Development

Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@
"ext-fileinfo": "*",
"setasign/fpdf": "^1.8",
"phpdocumentor/reflection-docblock": "^5.2",
"guzzlehttp/guzzle": "^7.4.5"
"guzzlehttp/guzzle": "^7.4.5",
"symfony/dotenv": "^6.4"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
Expand Down Expand Up @@ -127,7 +128,7 @@
"PhpList\\Core\\Composer\\ScriptHandler::createGeneralConfiguration",
"PhpList\\Core\\Composer\\ScriptHandler::createBundleConfiguration",
"PhpList\\Core\\Composer\\ScriptHandler::createRoutesConfiguration",
"PhpList\\Core\\Composer\\ScriptHandler::createParametersConfiguration",
"PhpList\\Core\\Composer\\ScriptHandler::createDotenvConfiguration",
"php bin/console cache:clear",
"php bin/console cache:warmup"
],
Expand Down
100 changes: 100 additions & 0 deletions config/parameters.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# This file is a "template" of what your parameters.yml file should look like
# Set parameters here that may be different on each deployment target of the app, e.g. development, staging, production.
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
#
# These variables are read from environment variables using the "env" construct.
# The environment variables themselves are defined in the ".env" file (see ".env.dist" for the template)
# and/or in the actual environment (e.g. Apache host configuration, command line).
parameters:
database_driver: '%env(PHPLIST_DATABASE_DRIVER)%'
database_path: '%env(PHPLIST_DATABASE_PATH)%'
database_host: '%env(PHPLIST_DATABASE_HOST)%'
database_port: '%env(PHPLIST_DATABASE_PORT)%'
database_name: '%env(PHPLIST_DATABASE_NAME)%'
database_user: '%env(PHPLIST_DATABASE_USER)%'
database_password: '%env(PHPLIST_DATABASE_PASSWORD)%'
database_prefix: '%env(DATABASE_PREFIX)%'
app.default_admin_password: '%env(PHPLIST_DEFAULT_ADMIN_PASSWORD)%'
list_table_prefix: '%env(LIST_TABLE_PREFIX)%'
app.dev_version: '%env(APP_DEV_VERSION)%'
app.dev_email: '%env(APP_DEV_EMAIL)%'
app.powered_by_phplist: '%env(APP_POWERED_BY_PHPLIST)%'
app.preference_page_show_private_lists: '%env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS)%'

app.rest_api_base_url: '%env(API_BASE_URL)%/api/v2'
app.api_base_url: '%env(API_BASE_URL)%'
app.frontend_base_url: '%env(FRONT_END_BASE_URL)%'

parallel_use_with_phplist3: '%env(PARALLER_USE_WITH_PHPLIST3)%'

# Email configuration
app.mailer_from: '%env(MAILER_FROM)%'
app.mailer_dsn: '%env(MAILER_DSN)%'
app.confirmation_url: '%env(CONFIRMATION_URL)%'
app.subscription_confirmation_url: '%env(SUBSCRIPTION_CONFIRMATION_URL)%'
app.password_reset_url: '%env(PASSWORD_RESET_URL)%'
app.show_unsubscribe_link: '%env(SHOW_UNSUBSCRIBELINK)%'

# bounce email settings
imap_bounce.email: '%env(BOUNCE_EMAIL)%'
imap_bounce.password: '%env(BOUNCE_IMAP_PASS)%'
imap_bounce.host: '%env(BOUNCE_IMAP_HOST)%'
imap_bounce.port: '%env(BOUNCE_IMAP_PORT)%'
imap_bounce.encryption: '%env(BOUNCE_IMAP_ENCRYPTION)%'
imap_bounce.mailbox: '%env(BOUNCE_IMAP_MAILBOX)%'
imap_bounce.mailbox_name: '%env(BOUNCE_IMAP_MAILBOX_NAME)%'
imap_bounce.protocol: '%env(BOUNCE_IMAP_PROTOCOL)%'
imap_bounce.unsubscribe_threshold: '%env(BOUNCE_IMAP_UNSUBSCRIBE_THRESHOLD)%'
imap_bounce.blacklist_threshold: '%env(BOUNCE_IMAP_BLACKLIST_THRESHOLD)%'
imap_bounce.purge: '%env(BOUNCE_IMAP_PURGE)%'
imap_bounce.purge_unprocessed: '%env(BOUNCE_IMAP_PURGE_UNPROCESSED)%'

# Messenger configuration for asynchronous processing
app.messenger_transport_dsn: '%env(MESSENGER_TRANSPORT_DSN)%'

# A secret key that's used to generate certain security-related tokens
secret: '%env(PHPLIST_SECRET)%'
phplist.verify_ssl: '%env(VERIFY_SSL)%'

graylog_host: 'graylog.phplist.local'
graylog_port: 12201

app.phplist_isp_conf_path: '%env(APP_PHPLIST_ISP_CONF_PATH)%'

# Message sending
messaging.mail_queue_batch_size: '%env(MAILQUEUE_BATCH_SIZE)%'
messaging.mail_queue_period: '%env(MAILQUEUE_BATCH_PERIOD)%'
messaging.mail_queue_throttle: '%env(MAILQUEUE_THROTTLE)%'
messaging.max_process_time: '%env(MESSAGING_MAX_PROCESS_TIME)%'
messaging.max_mail_size: '%env(MAX_MAILSIZE)%'
messaging.default_message_age: '%env(DEFAULT_MESSAGEAGE)%'
messaging.use_manual_text_part: '%env(USE_MANUAL_TEXT_PART)%'
messaging.blacklist_grace_time: '%env(MESSAGING_BLACKLIST_GRACE_TIME)%'
messaging.google_sender_id: '%env(GOOGLE_SENDERID)%'
messaging.use_amazon_ses: '%env(USE_AMAZONSES)%'
messaging.use_precedence_header: '%env(USE_PRECEDENCE_HEADER)%'
messaging.embed_external_images: '%env(EMBEDEXTERNALIMAGES)%'
messaging.embed_uploaded_images: '%env(EMBEDUPLOADIMAGES)%'
messaging.external_image_max_age: '%env(EXTERNALIMAGE_MAXAGE)%'
messaging.external_image_timeout: '%env(EXTERNALIMAGE_TIMEOUT)%'
messaging.external_image_max_size: '%env(EXTERNALIMAGE_MAXSIZE)%'
messaging.forward_alternative_content: '%env(FORWARD_ALTERNATIVE_CONTENT)%'
messaging.email_text_credits: '%env(EMAILTEXTCREDITS)%'
messaging.always_add_user_track: '%env(ALWAYS_ADD_USERTRACK)%'
messaging.send_list_admin_copy: '%env(SEND_LISTADMIN_COPY)%'

phplist.forward_email_period: '%env(FORWARD_EMAIL_PERIOD)%'
phplist.forward_email_count: '%env(FORWARD_EMAIL_COUNT)%'
phplist.forward_personal_note_size: '%env(FORWARD_PERSONAL_NOTE_SIZE)%'
phplist.forward_friend_count_attribute: '%env(FORWARD_FRIEND_COUNT_ATTRIBUTE)%'
phplist.keep_forwarded_attributes: '%env(KEEPFORWARDERATTRIBUTES)%'

phplist.upload_images_dir: '%env(UPLOADIMAGES_DIR)%'
phplist.uploads.allowed_mime_types: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']
phplist.uploads.allowed_extensions: ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']
phplist.uploads.max_size: '%env(PHPLIST_UPLOADS_MAX_SIZE)%'

phplist.public_schema: '%env(PUBLIC_SCHEMA)%'
phplist.attachment_download_url: '%env(PHPLIST_ATTACHMENT_DOWNLOAD_URL)%'
phplist.attachment_repository_path: '%env(PHPLIST_ATTACHMENT_REPOSITORY_PATH)%'
phplist.max_avatar_size: '%env(MAX_AVATAR_SIZE)%'
Loading
Loading