diff --git a/composer.json b/composer.json
index 92a29565..aba1a887 100644
--- a/composer.json
+++ b/composer.json
@@ -83,7 +83,8 @@
"ext-libxml": "*",
"ext-gd": "*",
"ext-curl": "*",
- "ext-fileinfo": "*"
+ "ext-fileinfo": "*",
+ "setasign/fpdf": "^1.8"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
diff --git a/config/parameters.yml.dist b/config/parameters.yml.dist
index 92b33bed..38e54bf3 100644
--- a/config/parameters.yml.dist
+++ b/config/parameters.yml.dist
@@ -31,6 +31,10 @@ parameters:
env(APP_DEV_EMAIL): 'dev@dev.com'
app.powered_by_phplist: '%%env(APP_POWERED_BY_PHPLIST)%%'
env(APP_POWERED_BY_PHPLIST): '0'
+ app.preference_page_show_private_lists: '%%env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS)%%'
+ env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS): '0'
+ app.rest_api_domain: '%%env(REST_API_DOMAIN)%%'
+ env(REST_API_DOMAIN): 'https://example.com/api/v2'
# Email configuration
app.mailer_from: '%%env(MAILER_FROM)%%'
@@ -115,6 +119,12 @@ parameters:
env(EXTERNALIMAGE_TIMEOUT): '30'
messaging.external_image_max_size: '%%env(EXTERNALIMAGE_MAXSIZE)%%'
env(EXTERNALIMAGE_MAXSIZE): '204800'
+ messaging.forward_alternative_content: '%%env(FORWARD_ALTERNATIVE_CONTENT)%%'
+ env(FORWARD_ALTERNATIVE_CONTENT): '0'
+ messaging.email_text_credits: '%%env(EMAILTEXTCREDITS)%%'
+ env(EMAILTEXTCREDITS): '0'
+ messaging.always_add_user_track: '%%env(ALWAYS_ADD_USERTRACK)%%'
+ env(ALWAYS_ADD_USERTRACK): '1'
phplist.upload_images_dir: '%%env(PHPLIST_UPLOADIMAGES_DIR)%%'
env(PHPLIST_UPLOADIMAGES_DIR): 'images'
diff --git a/config/services/builders.yml b/config/services/builders.yml
index 10a994a4..1b4316dd 100644
--- a/config/services/builders.yml
+++ b/config/services/builders.yml
@@ -23,3 +23,28 @@ services:
PhpList\Core\Domain\Messaging\Service\Builder\MessageOptionsBuilder:
autowire: true
autoconfigure: true
+
+ # Concrete mail constructors
+ PhpList\Core\Domain\Messaging\Service\Constructor\SystemMailContentBuilder: ~
+ PhpList\Core\Domain\Messaging\Service\Constructor\CampaignMailContentBuilder: ~
+
+ # Two EmailBuilder services with different constructors injected
+ Core.EmailBuilder.system:
+ class: PhpList\Core\Domain\Messaging\Service\Builder\EmailBuilder
+ arguments:
+ $mailConstructor: '@PhpList\Core\Domain\Messaging\Service\Constructor\SystemMailContentBuilder'
+ $googleSenderId: '%messaging.google_sender_id%'
+ $useAmazonSes: '%messaging.use_amazon_ses%'
+ $usePrecedenceHeader: '%messaging.use_precedence_header%'
+ $devVersion: '%app.dev_version%'
+ $devEmail: '%app.dev_email%'
+
+ Core.EmailBuilder.campaign:
+ class: PhpList\Core\Domain\Messaging\Service\Builder\EmailBuilder
+ arguments:
+ $mailConstructor: '@PhpList\Core\Domain\Messaging\Service\Constructor\CampaignMailContentBuilder'
+ $googleSenderId: '%messaging.google_sender_id%'
+ $useAmazonSes: '%messaging.use_amazon_ses%'
+ $usePrecedenceHeader: '%messaging.use_precedence_header%'
+ $devVersion: '%app.dev_version%'
+ $devEmail: '%app.dev_email%'
diff --git a/config/services/messenger.yml b/config/services/messenger.yml
index 3c8f27bb..5a3a1f26 100644
--- a/config/services/messenger.yml
+++ b/config/services/messenger.yml
@@ -31,6 +31,11 @@ services:
PhpList\Core\Domain\Messaging\MessageHandler\CampaignProcessorMessageHandler:
autowire: true
+ autoconfigure: true
+ arguments:
+ $campaignEmailBuilder: '@Core.EmailBuilder.campaign'
+ $systemEmailBuilder: '@Core.EmailBuilder.system'
+ $messageEnvelope: '%app.config.message_from_address%'
PhpList\Core\Domain\Subscription\MessageHandler\DynamicTableMessageHandler:
autowire: true
diff --git a/config/services/parameters.yml b/config/services/parameters.yml
index ebf1d99b..18aa6ccf 100644
--- a/config/services/parameters.yml
+++ b/config/services/parameters.yml
@@ -1,4 +1,9 @@
parameters:
+ # Flattened parameters for direct DI usage (Symfony does not support dot access into arrays)
+ app.config.message_from_address: 'news@example.com'
+ app.config.default_message_age: 15768000
+
+ # Keep original grouped array for legacy/config-provider usage
app.config:
message_from_address: 'news@example.com'
admin_address: 'admin@example.com'
diff --git a/config/services/repositories.yml b/config/services/repositories.yml
index ea1f0001..37b31c18 100644
--- a/config/services/repositories.yml
+++ b/config/services/repositories.yml
@@ -22,6 +22,11 @@ services:
arguments:
- PhpList\Core\Domain\Configuration\Model\EventLog
+ PhpList\Core\Domain\Configuration\Repository\UrlCacheRepository:
+ parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
+ arguments:
+ - PhpList\Core\Domain\Configuration\Model\UrlCache
+
PhpList\Core\Domain\Identity\Repository\AdministratorRepository:
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
@@ -145,3 +150,13 @@ services:
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
arguments:
- PhpList\Core\Domain\Messaging\Model\MessageData
+
+ PhpList\Core\Domain\Messaging\Repository\AttachmentRepository:
+ parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
+ arguments:
+ - PhpList\Core\Domain\Messaging\Model\Attachment
+
+ PhpList\Core\Domain\Messaging\Repository\MessageAttachmentRepository:
+ parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
+ arguments:
+ - PhpList\Core\Domain\Messaging\Model\MessageAttachment
diff --git a/config/services/resolvers.yml b/config/services/resolvers.yml
index 99c08356..6dfab328 100644
--- a/config/services/resolvers.yml
+++ b/config/services/resolvers.yml
@@ -13,3 +13,27 @@ services:
PhpList\Core\Bounce\Service\BounceActionResolver:
arguments:
- !tagged_iterator { tag: 'phplist.bounce_action_handler' }
+
+ PhpList\Core\Domain\Configuration\Service\Placeholder\UnsubscribeUrlValueResolver:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Configuration\Service\Placeholder\ConfirmationUrlValueResolver:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Configuration\Service\Placeholder\PreferencesUrlValueResolver:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Configuration\Service\Placeholder\SubscribeUrlValueResolver:
+ autowire: true
+ autoconfigure: true
+
+ _instanceof:
+ PhpList\Core\Domain\Configuration\Service\Placeholder\PlaceholderValueResolverInterface:
+ tags: ['phplist.placeholder_resolver']
+ PhpList\Core\Domain\Configuration\Service\Placeholder\PatternValueResolverInterface:
+ tags: [ 'phplist.pattern_resolver' ]
+ PhpList\Core\Domain\Configuration\Service\Placeholder\SupportingPlaceholderResolverInterface:
+ tags: [ 'phplist.supporting_placeholder_resolver' ]
diff --git a/config/services/services.yml b/config/services/services.yml
index cf298621..c494c3ea 100644
--- a/config/services/services.yml
+++ b/config/services/services.yml
@@ -43,6 +43,51 @@ services:
autowire: true
autoconfigure: true
+ # Html to Text converter used by mail constructors
+ PhpList\Core\Domain\Common\Html2Text:
+ autowire: true
+ autoconfigure: true
+
+ # Rewrites relative asset URLs in fetched HTML to absolute ones
+ PhpList\Core\Domain\Common\HtmlUrlRewriter:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Common\PdfGenerator:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Messaging\Service\AttachmentAdder:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Configuration\Service\UserPersonalizer:
+ autowire: true
+ autoconfigure: true
+
+ # External image caching/downloading helper used by TemplateImageEmbedder
+ PhpList\Core\Domain\Common\ExternalImageService:
+ autowire: true
+ autoconfigure: true
+ arguments:
+ $tempDir: '%kernel.cache_dir%'
+ # Use literal defaults if parameters are not defined in this environment
+ $externalImageMaxAge: 0
+ $externalImageMaxSize: 204800
+ $externalImageTimeout: 30
+
+ # Embed images from templates and filesystem into HTML emails
+ PhpList\Core\Domain\Messaging\Service\TemplateImageEmbedder:
+ autowire: true
+ autoconfigure: true
+ arguments:
+ $documentRoot: '%kernel.project_dir%/public'
+ # Reuse upload_images_dir for editorImagesDir if a dedicated parameter is absent
+ $editorImagesDir: '%phplist.upload_images_dir%'
+ $embedExternalImages: '%messaging.embed_external_images%'
+ $embedUploadedImages: '%messaging.embed_uploaded_images%'
+ $uploadImagesDir: '%phplist.upload_images_dir%'
+
PhpList\Core\Domain\Messaging\Service\RateLimitedCampaignMailer:
autowire: true
autoconfigure: true
@@ -120,9 +165,13 @@ services:
autoconfigure: true
public: true
- PhpList\Core\Domain\Configuration\Service\UserPersonalizer:
+ PhpList\Core\Domain\Configuration\Service\MessagePlaceholderProcessor:
autowire: true
autoconfigure: true
+ arguments:
+ $placeholderResolvers: !tagged_iterator phplist.placeholder_resolver
+ $patternResolvers: !tagged_iterator phplist.pattern_resolver
+ $supportingResolvers: !tagged_iterator phplist.supporting_placeholder_resolver
PhpList\Core\Domain\Configuration\Service\LegacyUrlBuilder:
autowire: true
@@ -139,3 +188,28 @@ services:
autoconfigure: true
arguments:
$maxMailSize: '%messaging.max_mail_size%'
+
+ # Loads and normalises message data for campaigns
+ PhpList\Core\Domain\Messaging\Service\MessageDataLoader:
+ autowire: true
+ autoconfigure: true
+ arguments:
+ $defaultMessageAge: '%app.config.default_message_age%'
+
+ # Common helpers required by precache/message building
+ PhpList\Core\Domain\Common\TextParser:
+ autowire: true
+ autoconfigure: true
+
+ PhpList\Core\Domain\Common\RemotePageFetcher:
+ autowire: true
+ autoconfigure: true
+
+ # Pre-caches base message content (HTML/Text/template) for campaigns
+ PhpList\Core\Domain\Messaging\Service\MessagePrecacheService:
+ autowire: true
+ autoconfigure: true
+ arguments:
+ $useManualTextPart: '%messaging.use_manual_text_part%'
+ $uploadImageDir: '%phplist.upload_images_dir%'
+ $publicSchema: '%phplist.public_schema%'
diff --git a/resources/translations/messages.en.xlf b/resources/translations/messages.en.xlf
index 40a24785..906de934 100644
--- a/resources/translations/messages.en.xlf
+++ b/resources/translations/messages.en.xlf
@@ -750,6 +750,50 @@ Thank you.
phplist has started sending the campaign with subject %subject%
__phplist has started sending the campaign with subject %subject%
+
+ Unsubscribe
+ __Unsubscribe
+
+
+ This link
+ __This link
+
+
+ Confirm
+ __Confirm
+
+
+ Update preferences
+ __Update preferences
+
+
+ Sorry, you are not subscribed to any of our newsletters with this email address.
+ __Sorry, you are not subscribed to any of our newsletters with this email address.
+
+
+ This message contains attachments that can be viewed with a webbrowser
+ __This message contains attachments that can be viewed with a webbrowser
+
+
+ Insufficient memory to add attachment to campaign %campaignId% %tatalSize% - %memLimit%
+ __Insufficient memory to add attachment to campaign %campaignId% %tatalSize% - %memLimit%
+
+
+ Add us to your address book
+ __Add us to your address book
+
+
+ phpList system error
+ __phpList system error
+
+
+ Error, when trying to send campaign %campaignId% the attachment (%remoteFile%) could not be copied to the repository. Check for permissions.
+ __Error, when trying to send campaign %campaignId% the attachment (%remoteFile%) could not be copied to the repository. Check for permissions.
+
+
+ failed to open attachment (%remoteFile%) to add to campaign %campaignId%
+ __failed to open attachment (%remoteFile%) to add to campaign %campaignId%
+