# The email sending stops, and I don't know why

**URL:** <https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029>\
**Category:** Mautic 7 Install / Upgrade Support\
**Created:** [April 1, 2026, 11:31pm UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029 "2026-04-01T23:31:42Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![krasho](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/krasho/32/14444_2.png) [@krasho](https://forum.mautic.org/u/krasho)\
**Post date:** [April 1, 2026, 11:31pm UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/1 "2026-04-01T23:31:42Z")

</div>

**Your software**  
My Mautic version is: 7  
My PHP version is: 8.3  
My Database type and version is: MariaDB 10.11.14-MariaDB-0ubuntu0.24.04.1 Ubuntu 24.04  
I installed Mautic via: Docker  
I’m using Doctrine to queued process

**Your problem**  
My problem is:

I’m experiencing an issue with Mautic 7 where campaign emails are not being sent to all eligible contacts, and I’d appreciate any guidance or insight.

I have a segment with ~15,000 contacts.  
I created a campaign with a simple flow:

- Segment → Send Email (delay 1 min)

I’m using staggered cron jobs as recommended:

```auto
0,15,30,45 * * * * php /var/www/html/bin/console mautic:segments:update
5,20,35,50 * * * * php /var/www/html/bin/console mautic:campaigns:update
10,25,40,55 * * * * php /var/www/html/bin/console mautic:campaigns:trigger 2>&1 | tee /tmp/stdout

```

## Issue observed

- Total contacts in campaign: **15,389**

- Contacts that received the email: **6,400**

- Contacts not sent: **8,989**

## 🔍 Database verification

- All contacts reached the campaign event:

```auto
SELECT COUNT(*) FROM campaign_lead_event_log WHERE campaign_id = X;
-- Result: 15389

```

- Only 6,400 records in `email_stats`:

```auto
SELECT COUNT(DISTINCT lead_id) FROM email_stats WHERE email_id = X;
-- Result: 6400

```

## ❓ Key questions

1. Is it possible that `mautic:campaigns:trigger` is not finishing before the next cron execution and causing incomplete processing?

2. Could there be a locking issue where:

3. Is there a known issue where:

* * *

## 🧪 Additional notes

- No errors are clearly visible in logs yet (still investigating)

- Using Docker setup with:

* * *

## 🙏 What I need help with

- Understanding why valid contacts are skipped

- Whether this is expected behavior with large batches

- Recommended way to ensure all contacts are processed reliably

- Best practices for cron + queue setup (Doctrine vs Redis)

thanks

---

<div class="post-metadata">

**Author:** ![krasho](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/krasho/32/14444_2.png) [@krasho](https://forum.mautic.org/u/krasho)\
**Post date:** [April 2, 2026, 12:19am UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/2 "2026-04-02T00:19:57Z")

</div>

I found this error:  
`root@b31faa658a90:/var/www/html/var/logs# cat prod-2026-04-01.php [2026-04-01T21:12:21.289350+00:00] console.CRITICAL: Error thrown while running command "messenger:consume email". Message: "An exception occurred while executing a query: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction" {"exception":"[object] (Symfony\\Component\\Messenger\\Exception\\TransportException(code: 0): An exception occurred while executing a query: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction at /var/www/html/vendor/symfony/doctrine-messenger/Transport/Connection.php:251)\n[previous exception] [object] (Doctrine\\DBAL\\Exception\\DeadlockException(code: 1213): An exception occurred while executing a query: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction at /var/www/html/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php:39)\n[previous exception] [object] (Doctrine\\DBAL\\Driver\\PDO\\Exception(code: 1213): SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction at /var/www/html/vendor/doctrine/dbal/src/Driver/PDO/Exception.php:28)\n[previous exception] [object] (PDOException(code: 40001): SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction at /var/www/html/vendor/doctrine/dbal/src/Driver/PDO/Statement.php:130)","command":"messenger:consume email","message":"An exception occurred while executing a query: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction"} {"hostname":"b31faa658a90","pid":26}`

is it related to Doctrine?

---

<div class="post-metadata">

**Author:** ![rcarabelli](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/rcarabelli/32/6807_2.png) [@rcarabelli](https://forum.mautic.org/u/rcarabelli)\
**Post date:** [April 2, 2026, 12:49am UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/3 "2026-04-02T00:49:05Z")

</div>

Probably 2 workers are trying to send the same message and they like cancel each other.  
That’s why I only run only 1 worker at a time. But some might thing otherwise.

Cancel all your running workers and restart your sending.

---

<div class="post-metadata">

**Author:** ![krasho](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/krasho/32/14444_2.png) [@krasho](https://forum.mautic.org/u/krasho)\
**Post date:** [April 2, 2026, 3:37am UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/4 "2026-04-02T03:37:48Z")

</div>

Thanks \*\*[rcarabelli](https://forum.mautic.org/u/rcarabelli)  
\*\*  
do you think Doctrine could have problems? are you using doctrine ?

thanks

---

<div class="post-metadata">

**Author:** ![rcarabelli](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/rcarabelli/32/6807_2.png) [@rcarabelli](https://forum.mautic.org/u/rcarabelli)\
**Post date:** [April 2, 2026, 3:55am UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/5 "2026-04-02T03:55:22Z")

</div>

I use doctrine, yes, have a guide, will search for it and share it

---

<div class="post-metadata">

**Author:** ![krasho](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/krasho/32/14444_2.png) [@krasho](https://forum.mautic.org/u/krasho)\
**Post date:** [April 2, 2026, 5:47pm UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/6 "2026-04-02T17:47:57Z")

</div>

thanks **[rcarabelli](https://forum.mautic.org/u/rcarabelli)** did you find the doctrine guide?

thanks

---

<div class="post-metadata">

**Author:** ![rcarabelli](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/rcarabelli/32/6807_2.png) [@rcarabelli](https://forum.mautic.org/u/rcarabelli)\
**Post date:** [April 3, 2026, 2:31am UTC](https://forum.mautic.org/t/the-email-sending-stops-and-i-dont-know-why/38029/7 "2026-04-03T02:31:25Z")

</div>

I originally wrote a guide for Mautic’s knowledge base, but it needs an update. Please use the following file and save it with this exact path and name:

/full\_path\_to\_mautic/var/lock/consume\_mautic.sh

Before using it, edit the configuration variables inside the script to match your environment. In particular, you will need to update:

- the sending frequency settings
- the path to your PHP binary
- the path to your Mautic installation

You will also need to create the `lock` directory inside Mautic’s `var` directory if it does not already exist:

/full\_path\_to\_mautic/var/lock/

After saving the file, make it executable from the terminal with:

chmod +x /full\_path\_to\_mautic/var/lock/consume\_mautic.sh

Then create a cron job to run it once per minute. For example:

\* \* \* \* \* /full\_path\_to\_mautic/var/lock/consume\_mautic.sh \> /dev/null 2\>&1

You can change the log output part if you want to store logs instead of discarding them.

What does this file do?

This script replaces the usual `messenger:consume` cron job and gives you much more control over how email sending is processed in Mautic.

With this script, you can:

- limit how many emails are processed per hour
- control the pacing of email processing through delays between runs
- restrict sending to specific days of the week
- restrict sending to specific hours of the day
- prevent overlapping executions by making sure only one worker runs at a time

In other words, it gives you a simple way to throttle email sending and avoid multiple workers running at the same time, which can be useful for controlling server load and keeping delivery behavior more predictable.

The file content starts here:

```auto
#!/bin/bash
set -euo pipefail

########################################

USER CONFIG

########################################

PHP_BIN=“/usr/bin/php8.3”

MAUTIC_ROOT=“/full_path_to_mautic”
MAUTIC_BIN=“$MAUTIC_ROOT/bin/console”
LOCK_DIR=“$MAUTIC_ROOT/var/lock”

LOCKFILE=“$LOCK_DIR/consume_mautic.lock”
STATEFILE=“$LOCK_DIR/consume_mautic_hourly.state”

LOCKFILE_TIMEOUT=50

1=Lun … 7=Dom

WORKING_DAYS=(“1” “2” “3” “4” “5” “6”)

Start time, end time

START_HOUR=6
END_HOUR=22

Cadence

INTERVAL=5
PER_BURST=1
HARD_LIMIT=50

Max per hour

HOURLY_LIMIT=500

Consumer limits

TIME_LIMIT=1
MEMORY_LIMIT=“8192M”

########################################

INTERNALS

########################################

mkdir -p “$LOCK_DIR”

current_hour_key() {
date +%Y%m%d%H
}

is_working_day() {
local dow
dow=$(date +%u)

for d in “${WORKING_DAYS[@]}”; do
if [“$d” = “$dow”]; then
return 0
fi
done

return 1
}

is_allowed_hour() {
local hour
hour=$(date +%H)
hour=$((10#$hour))

if [“$hour” -lt “$START_HOUR”] || [“$hour” -ge “$END_HOUR”]; then
return 1
fi

return 0
}

load_state() {
local now_hour
now_hour=$(current_hour_key)

if [! -f “$STATEFILE”]; then
printf “%s|0\n” “$now_hour” > “$STATEFILE”
fi

local state_hour state_count
IFS=‘|’ read -r state_hour state_count < “$STATEFILE” || true

if [-z “${state_hour:-}”] || [-z “${state_count:-}”]; then
state_hour=“$now_hour”
state_count=0
printf “%s|%s\n” “$state_hour” “$state_count” > “$STATEFILE”
fi

if [“$state_hour” != “$now_hour”]; then
state_hour=“$now_hour”
state_count=0
printf “%s|%s\n” “$state_hour” “$state_count” > “$STATEFILE”
fi

STATE_HOUR=“$state_hour”
STATE_COUNT=“$state_count”
}

save_state() {
printf “%s|%s\n” “$STATE_HOUR” “$STATE_COUNT” > “$STATEFILE”
}

########################################

GUARDS

########################################

if ! is_working_day; then
echo “This is not an approved day. Exiting…”
exit 0
fi

if ! is_allowed_hour; then
echo “Outside of authorized time frame (${START_HOUR}:00-${END_HOUR}:00). Exiting…”
exit 0
fi

if [-e “$LOCKFILE”]; then
LOCKFILE_AGE=$(( $(date +%s) - $(stat -c %Y “$LOCKFILE”) ))
if [“$LOCKFILE_AGE” -ge “$LOCKFILE_TIMEOUT”]; then
echo “Lock > ${LOCKFILE_TIMEOUT}s. Deleting old lock file…”
rm -f “$LOCKFILE”
else
echo “Process already running. Exiting…”
exit 1
fi
fi

touch “$LOCKFILE”
trap ‘rm -f “$LOCKFILE”’ EXIT INT TERM

########################################

MAIN

########################################

load_state

if [“$STATE_COUNT” -ge “$HOURLY_LIMIT”]; then
echo “Hourly limit has been reached (${STATE_COUNT}/${HOURLY_LIMIT}) in the hour ${STATE_HOUR}. Exiting…”
exit 0
fi

SENT_REAL=0
START_TS=$(date +%s)

while (( $(date +%s) - START_TS < HARD_LIMIT )); do
load_state

if [“$STATE_COUNT” -ge “$HOURLY_LIMIT”]; then
echo “LÃ­mite horario alcanzado (${STATE_COUNT}/${HOURLY_LIMIT}).”
break
fi

if “$PHP_BIN” “$MAUTIC_BIN” messenger:consume email 
–limit=“$PER_BURST” 
–time-limit=“$TIME_LIMIT” 
–memory-limit=“$MEMORY_LIMIT” 
–no-interaction; then

STATE_COUNT=$(( STATE_COUNT + 1 ))
SENT_REAL=$(( SENT_REAL + 1 ))
save_state

echo "Processed: 1 | Hour: $STATE_HOUR | Accumulated on hour: $STATE_COUNT/$HOURLY_LIMIT"

else
echo “Messeger command returned:consume returned error. Exiting…”
break
fi

NOW=$(date +%s)
if (( NOW - START_TS + INTERVAL >= HARD_LIMIT )); then
break
fi

sleep “$INTERVAL”
done

echo “Processed in this run: $SENT_REAL”
exit 0

```
