Unsubscribe back-end stopped working

My Mautic version is: 4.4.10
My PHP version is: 7.4
My Database type and version is: MySQL

My problem is:
Unsubscribe back-end is not working, unsubscribe link click will produce correct message but inside mautic, contact will not be marked as “do not contact”.

When I import sample email address and campaign is triggered and email is sent to test email address, when inside that mailbox I click unsubscribe link, correct unsubscribe confirmation message shows up and everything looks fine, yet in the back-end in that specific contacts history no changes will happen and contact will not be marked as “Do not contact”, whereas in the past it would happen immediately. Even after few days it will not be marked as do not contact.

The unsubscribe message that will display after link click is:
"
We are sorry to see you go! actualEmailAdress will no longer receive emails from us. If this was by mistake, re-subscribe link.
"

In local.php I have even set debug mode to true but no logs are produced related to unsubscribe.

@joeyk any suggestions where I should be looking?

Tracking of other links which are inside that email are happening immediately after click. If other link, for example to other page is clicked, contact history will show that immediately as “page hit”

Hello!
Can you give an example how your unsub link looks like?
Do you have the .htaccess file intact in your document root?

@joeyk

.htaccess file inside mautic root folder is intact. When compared it to other working servers .htaccess file they were identical. You can see file contents at the end.

Regarding unsubscribe link, all settings are default and have not changed since the time unsubscribe was working.

Here is image:

In email builder {unsubscribe_text} is included.

When email is received, link is:
https://subserver.ourdomain.com/email/unsubscribe/67164f28061f6044518167

And after going to the link the contents in tab are:
“””
We are sorry to see you go! “RealEmailAdress” will no longer receive emails from us. If this was by mistake, [click here to re-subscribe](https://subserver.ourdomain.com/email/resubscribe/67164f28061f6044518167).
“””

.htaccess file:
“”"

# Use the front controller as index file. It serves as a fallback solution when
# every other rewrite/redirect fails (e.g. in an aliased environment without
# mod_rewrite). Additionally, this reduces the matching process for the
# start page (path "/") because otherwise Apache will apply the rewriting rules
# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).
#DirectoryIndex index.php

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Set Authorization header for OAuth2 for when php is running under fcgi
    RewriteCond %{HTTP:Authorization} .+
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Determine the RewriteBase automatically and set it as environment variable.
    # If you are using Apache aliases to do mass virtual hosting or installed the
    # project in a subdirectory, the base path will be prepended to allow proper
    # resolution of the app.php file and to redirect to the correct URI. It will
    # work in environments without path prefix as well, providing a safe, one-size
    # fits all solution. But as you do not need it in this case, you can comment
    # the following 2 lines to eliminate the overhead.
    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]

    # Redirect to URI without front controller to prevent duplicate content
    # (with and without `/app.php`). Only do this redirect on the initial
    # rewrite by Apache and not on subsequent cycles. Otherwise we would get an
    # endless redirect loop (request -> rewrite to front controller ->
    # redirect -> request -> ...).
    # So in case you get a "too many redirects" error or you always get redirected
    # to the start page because your Apache does not expose the REDIRECT_STATUS
    # environment variable, you have 2 choices:
    # - disable this feature by commenting the following 2 lines or
    # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
    #   following RewriteCond (best solution)
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^index\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

    # If the requested filename exists, simply serve it.
    # We only want to let Apache serve files and not directories.
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .? - [L]

    # Rewrite all other queries to the front controller.
    RewriteRule .? %{ENV:BASE}/index.php [L]
</IfModule>

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        # When mod_rewrite is not available, we instruct a temporary redirect of
        # the start page to the front controller explicitly so that the website
        # and the generated links can still be used.
        RedirectMatch 302 ^(?!/(index\.php|index_dev\.php|app|addons|plugins|media|upgrade))(/(.*))$ /index.php$2
        # RedirectTemp cannot be used instead
    </IfModule>
</IfModule>

<IfModule mod_php5.c>
    # @link https://github.com/mautic/mautic/issues/1504
    php_value always_populate_raw_post_data -1
</IfModule>

<IfModule mod_deflate.c>
    <IfModule mod_filter.c>
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE application/rss+xml
        AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
        AddOutputFilterByType DEFLATE application/x-font
        AddOutputFilterByType DEFLATE application/x-font-opentype
        AddOutputFilterByType DEFLATE application/x-font-otf
        AddOutputFilterByType DEFLATE application/x-font-truetype
        AddOutputFilterByType DEFLATE application/x-font-ttf
        AddOutputFilterByType DEFLATE application/x-javascript
        AddOutputFilterByType DEFLATE font/opentype
        AddOutputFilterByType DEFLATE font/otf
        AddOutputFilterByType DEFLATE font/ttf
        AddOutputFilterByType DEFLATE image/svg+xml
        AddOutputFilterByType DEFLATE image/x-icon
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE text/javascript
        # Do not enable compression for file types that could contain secrets
        #AddOutputFilterByType DEFLATE text/html
        #AddOutputFilterByType DEFLATE text/plain
        #AddOutputFilterByType DEFLATE text/xml
        #AddOutputFilterByType DEFLATE application/xhtml+xml
        #AddOutputFilterByType DEFLATE application/xml
        #AddOutputFilterByType DEFLATE application/json
        <IfModule mod_setenvif.c>
            <IfModule mod_header.c>
                # Remove browser bugs (only needed for really old browsers)
                BrowserMatch ^Mozilla/4 gzip-only-text/html
                BrowserMatch ^Mozilla/4\.0[678] no-gzip
                BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
                Header append Vary User-Agent
            </IfModule>
        </IfModule>
    </IfModule>
</IfModule>

# Apache 2.4+
<IfModule authz_core_module>
    # Deny access via HTTP requests to all PHP files.
    <FilesMatch "\.php$">
        Require all denied
    </FilesMatch>

    # Deny access via HTTP requests to composer files.
    <FilesMatch "^(composer\.json|composer\.lock)$">
        Require all denied
    </FilesMatch>

    # Except those allowed below.
    <If "%{REQUEST_URI} =~ m#^/(index|index_dev|upgrade/upgrade)\.php#">
        Require all granted
    </If>
</IfModule>

# Fallback for Apache < 2.4
<IfModule !authz_core_module>
    # Deny access via HTTP requests to all PHP files.
    <FilesMatch "\.php$">
        Order deny,allow
        Deny from all
    </FilesMatch>

    # Deny access via HTTP requests to composer files
    <FilesMatch "^(composer\.json|composer\.lock)$">
        Order deny,allow
        Deny from all
    </FilesMatch>

    # Except those allowed below.
    <If "%{REQUEST_URI} =~ m#^/(index|index_dev|upgrade/upgrade)\.php#">
        Order allow,deny
        Allow from all
    </If>
</IfModule>


“”"

1 Like

@joeyk
Here are debug logs specifically when I open email and click unsubscribe link.
Email open is being tracked yet unsubscribe does not work to set contact as ‘Do not contact’

[2024-10-21 13:54:32] mautic.DEBUG: CONTACT: 828692 set as current lead. {"hostname":"mail.domain.com","pid":3815683}

[2024-10-21 13:54:32] mautic.DEBUG: CAMPAIGN: Campaign triggered for event type email.open(email / 1) {"hostname":"mail.domain.com","pid":3815683}

[2024-10-21 13:54:32] mautic.DEBUG: CONTACT: Tracking session for contact ID# 828692 through GET /email/67164f28061f6044518167.gif {"hostname":"mail.domain.com","pid":3815683}

[2024-10-21 13:54:32] mautic.DEBUG: CAMPAIGN: Current contact ID# 828692 {"hostname":"mail.domain.com","pid":3815683}

[2024-10-21 13:54:32] mautic.DEBUG: CAMPAIGN: Contact does not have any applicable email.open associations. {"hostname":"mail.domain.com","pid":3815683}

[2024-10-21 13:54:32] mautic.DEBUG: CONTACT: Tracking session for contact ID# 828692 through GET /email/67164f28061f6044518167.gif {"hostname":"mail.domain.com","pid":3815683}

[2024-10-21 13:54:36] mautic.DEBUG: CONTACT: 828692 set as current lead. {"hostname":"mail.domain.com","pid":4071097}

Okay.
If you check in your mysql db:

SELECT * FROM "email_stats" WHERE tracking_hash = "67164f28061f6044518167" LIMIT 50

Do you get a result?

@joeyk
Yes I see results, exactly 1 row.

here is is:

+--------+----------+---------+---------+-------+----------------------------------+------------------------+---------------------+---------+-----------+-------------------+---------------------+------------------------+-------------+----------------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| id     | email_id | lead_id | list_id | ip_id | copy_id                          | email_address          | date_sent           | is_read | is_failed | viewed_in_browser | date_read           | tracking_hash          | retry_count | source         | source_id | tokens                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | open_count | last_opened         | open_details                                                                                                                                                                                                                                                                                                                                           | generated_sent_date |
+--------+----------+---------+---------+-------+----------------------------------+------------------------+---------------------+---------+-----------+-------------------+---------------------+------------------------+-------------+----------------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| 886363 |        1 |  828694 |    NULL |  8596 | da170d357c8760081c17724fafdd12db | realEmailAdress@yahoo.com | 2024-10-21 15:38:01 |       1 |         0 |                 0 | 2024-10-21 15:38:44 | 67167559255bd656215952 |           0 | campaign.event |        47 | a:16:{s:36:"{dynamiccontent="Dynamic Content 1"}";s:23:"Default Dynamic Content";s:18:"{unsubscribe_text}";s:135:"<a href="https://ems.domain.com/email/unsubscribe/67167559255bd656215952">Unsubscribe</a> to no longer receive emails from us.";s:17:"{unsubscribe_url}";s:72:"https://ems.domain.com/email/unsubscribe/67167559255bd656215952";s:14:"{webview_text}";s:126:"<a href="https://ems.domain.com/email/view/67167559255bd656215952">Having trouble reading this email? Click here.</a>";s:13:"{webview_url}";s:65:"https://ems.domain.com/email/view/67167559255bd656215952";s:11:"{signature}";s:31:"Best regards, user userLastname";s:9:"{subject}";s:25:"Some subject line";s:31:"{contactfield=firstname|friend}";s:4:"Iuri";s:18:"{ownerfield=email}";s:26:"user@domain.com";s:22:"{ownerfield=firstname}";s:6:"user";s:21:"{ownerfield=lastname}";s:10:"userLastname";s:21:"{ownerfield=position}";s:0:"";s:22:"{ownerfield=signature}";s:0:"";s:37:"{trackable=0851d398b804eb8f613ff9ca2}";s:300:"https://ems.domain.com/r/0851d398b804eb8f613ff9ca2?ct=YTo1OntzOjY6InNvdXJjZSI7YToyOntpOjA7czoxNDoiY2FtcGFpZ24uZXZlbnQiO2k6MTtpOjQ3O31zOjU6ImVtYWlsIjtpOjE7czo0OiJzdGF0IjtzOjIyOiI2NzE2NzU1OTI1NWJkNjU2MjE1OTUyIjtzOjQ6ImxlYWQiO3M6NjoiODI4Njk0IjtzOjc6ImNoYW5uZWwiO2E6MTp7czo1OiJlbWFpbCI7aToxO319&";s:37:"{trackable=0c9706f1c017abd3c98bce8c3}";s:300:"https://ems.domain.com/r/0c9706f1c017abd3c98bce8c3?ct=YTo1OntzOjY6InNvdXJjZSI7YToyOntpOjA7czoxNDoiY2FtcGFpZ24uZXZlbnQiO2k6MTtpOjQ3O31zOjU6ImVtYWlsIjtpOjE7czo0OiJzdGF0IjtzOjIyOiI2NzE2NzU1OTI1NWJkNjU2MjE1OTUyIjtzOjQ6ImxlYWQiO3M6NjoiODI4Njk0IjtzOjc6ImNoYW5uZWwiO2E6MTp7czo1OiJlbWFpbCI7aToxO319&";s:16:"{tracking_pixel}";s:64:"https://ems.domain.com/email/67167559255bd656215952.gif";} |          2 | 2024-10-21 15:45:33 | a:2:{i:0;a:3:{s:8:"datetime";s:19:"2024-10-21 15:38:44";s:9:"useragent";s:72:"YahooMailProxy; https://help.yahoo.com/kb/yahoo-mail-proxy-SLN28749.html";s:9:"inBrowser";b:0;}i:1;a:3:{s:8:"datetime";s:19:"2024-10-21 15:45:33";s:9:"useragent";s:72:"YahooMailProxy; https://help.yahoo.com/kb/yahoo-mail-proxy-SLN28749.html";s:9:"inBrowser";b:0;}} | 2024-10-21          |
+--------+----------+---------+---------+-------+----------------------------------+------------------------+---------------------+---------+-----------+-------------------+---------------------+------------------------+-------------+----------------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+

@joeyk
I attached different contact, which has different hash, not this one: 67164f28061f6044518167
But still the situation is exactly the same.

@joeyk
To add more context I have developed a custom solution to allow scheduling of emails, so in front end user can add “schedule rows”, each holding specific number of how many contacts will be created each day (cron job running, executing 1 row every day).

See image:

Back-end is ready and working and some of it requires manipulations with leads table and I also needed to edit some.php files related to import.

This scheduling feature is fully working and doing its purpose, yet when email is sent to a person unsubscribe link click will not mark as Do not contact.

Simplified flow of scheduling feature:

  1. Contacts are imported (user leaves empty segment field but adds segment_name column in csv and during import mapps segment_name column with segment_name field)

  2. back-end is changed in a way to import into customleads table which is exactly identical to leads table. (Nothing goes into leads table from import directly)

  3. Cron job is running executing every day, moving specified number of rows from customleads into leads and deleting moved ones from customleads.

  4. segment with pre-defined filter segment_name custom filed equals to segment12 will accumulate those moved contacts in segment12 (this is example segment).

  5. campaign built on top of segment12 will send emails to moved contacts/leads.

Issue related findings:

Now my findings are that in working default mautic instance (community 4.4.10 version) where unsubscribe works if I do following actions and send email, then ‘do not contact’ will work.

Those actions were chosen accordingly to showcase approximately similar flow of scheduling feature.

Action 1:

INSERT INTO leads (email, is_published, points, segment_name, owner_id, title, firstname, stage_id, date_added, date_identified, last_active, created_by_user, modified_by_user) VALUES ("realUserEmail@yahoo.com", 1, 0, "segment12", 1, "eaxmpletitle", "Iuri", NULL, '2024-10-21 15:14:15', '2024-10-21 15:14:15', '2024-10-21 15:14:15', NULL, NULL);

This will safely make that contact appear inside Mautic contacts page.

Action 2:
sudo /usr/bin/php /home/realDomain/domains/subserver.realDomain/public_html/bin/console mautic:segments:update

After this action that inserted contact will appear in segment12 which has filter checking for custom field of segment_name equals to ‘segment12’

Action 3:

 mautic:campaigns:trigger

Email will be sent to user and once unsubscribe link is clicked contact history will immediately show that contact was marked as Do not contact

Important finding:

When I replicated all actions from above on server which has scheduling feature, only thing that was different is that contact was not marked as Do not contact

Now since for scheduling feature I only changed back-end for Import related .php files, this strongly suggests to me that the problem is some misconfigurations or user ownerships of this server

Important comment: it might confuse you why do I have segment_name custom field, but with current back-end it is necessary to make things work fully. So for now with scheduling feature when importing contacts, they must include segment_name column which will be used to determine future segment, since scheduling feature does not support segment mapping yet.

Hello,
It looks like a nice plugin, but I don’t understand what it does :slight_smile:
Joey

@joeyk
It allows users to upload large number of contacts once and then just set how many emails you want to set daily (basically as show in front end image, send 500 on day 1, 1000 day 2 and so on). Where as before user will need to go in every day and upload new contacts to send for that day.

If you ignore the functionality of this plugin, because it is not contributing to error that much, where or what would be the root cause for unsubscribe problem? Since you asked for hash and I found it.

@joeyk
I identified that that ‘Do not contact’ is not working because of changes I made in /app/bundles folder to some .php files, yet most likely I have only changed files that were related to contact importing. Are there any logics related to unsubscribes in import related methods?

Also where are unsubscribe related logics concentrated in bundles folder? Or are they spread across many places inside bundles folder?