Keeping email delivery working¶
This guide sets up outgoing email, turns on bounce processing, and fixes mail that stops sending.
All mail settings live in application/configs/application.ini on the server. The database holds none of them. A copy of the production database restored on another machine therefore cannot send email to participants.
Before you start¶
| Requirement | Detail |
|---|---|
| Admin account | Access to Configure → ePT Global Settings |
| Server access | A shell on the server, as root or with sudo, for the bounce and queue sections |
| Mail account | An SMTP account. For Gmail or Google Workspace, an app password and IMAP turned on |
| ePT version | 7.6.23 or later |
Set or change the SMTP login¶
- Open Configure → ePT Global Settings.
- Open the Email Settings section.
- Fill in SMTP Host, SMTP Port, Encryption, Username and Authentication Type.
- Enter the new password in Password. To keep the current password, leave the field blank.
- Fill in From Name and From Email. If From Email is empty, mail goes out from the SMTP username.
- Click Update.
Before saving, the page logs in to the mail server with the new details. If the server refuses the login, a red message shows the server's reply and nothing is saved. The previous settings keep working.
If the page reports that application.ini is not writable, run sudo ept update. The updater makes the file writable by the web server.
Turn on bounce processing¶
Bounce processing reads delivery-failure reports from an IMAP mailbox. It marks each address that no longer exists, so shipment emails, the copy-email buttons and Send Email to Participants skip it.
Bounces of mail that ePT sends come back to the SMTP account. Bounces of mail you send from your own Gmail, after copying addresses from ePT, come back to your own inbox.
- In the SMTP account's Gmail, create a filter. Set From to
mailer-daemon@googlemail.comand choose Apply the labelept-bounces. - If you also send from your own Gmail, create a filter there too. Set From to
mailer-daemon@googlemail.comand choose Forward it to the SMTP account. -
Open Configure → ePT Global Settings → Email Settings and fill in the Bounce Inbox part:
Field Value IMAP Host imap.gmail.comIMAP Port 993Encryption SSL Folder or Gmail Label ept-bouncesUsername and Password Leave empty to use the SMTP login. To read a different mailbox, fill them in Click Update. The page opens the mailbox and the folder before saving. If that fails, a red message shows why and nothing is saved.
-
Preview what the processor would mark:
cd /var/www/ept sudo -u www-data php bin/process-bounces.php --dry-run --reset-stateEach line starting with
HARDnames an address the processor would mark as bounced.--reset-statemakes this first run read the whole folder. -
Run it once for real, or wait up to 30 minutes for the scheduler. Saving a new mailbox or folder makes the next run read the whole folder.
sudo -u www-data php bin/process-bounces.php --reset-state
After this, the scheduler runs the processor every 30 minutes. It reads only new messages. It does not delete or move them.
A full mailbox, a spam block or a rate limit does not mark the address. Only a report that the mailbox does not exist does.
Check that bounce processing is working¶
Open Configure → ePT Global Settings → Email Settings. Under Bounce Inbox, a box shows the latest check:
| Box | Meaning | What to do |
|---|---|---|
| Green, "Last checked on …" | The last check worked. It shows how many new messages it read and how many addresses it marked | Nothing. If it says older messages are still waiting, it is working through the mailbox |
| Yellow, "Not checked yet" | No check has run since the inbox was saved | Wait 30 minutes and reload |
| Red, "The last check failed" | The mailbox could not be read. The box shows the server's reply | Fix the login or folder and click Update |
| Red, "No check has run for over two hours" | The ePT scheduler is not running | Ask the server administrator to check the cron job that runs crunz schedule:run |
The box also shows how many addresses are marked as bounced so far. To see which ones, use Unusable Emails on Configure → PT Participants.
Find participants and data managers who cannot receive email¶
- Open Configure → PT Participants, or Configure → Data Manager (Participant Login).
- Click Unusable Emails.
- Open the downloaded workbook. It has a Participants sheet and a Data Managers sheet.
- Filter Reachable By Email to
No. These accounts get no email at all.
| Problem shown | Meaning | Fix |
|---|---|---|
| No email | The address is empty | Add an address |
| Login-only address (made up at import) | Bulk import generated the address so the account can sign in. No mailbox exists | Add a real address, or leave it if the account only signs in |
| Bounced | The mail server reported that the mailbox does not exist. Bounce Reason shows the reply | Get a new address from the laboratory |
| Domain does not accept mail | The domain has no mail server | Correct the domain |
| Not a valid email address | The address is malformed | Correct the address |
To fix an account, edit its email address in ePT. A changed address loses its old problem and is checked again on the next validation run.
Fix mail that sends sometimes and fails sometimes¶
- Open Configure → Failed Emails.
-
Read the Failure Reason of the recent rows. Use this table to find the cause:
Text in Failure Reason or the log Cause Fix 535orUsername and Password not acceptedThe mail server refuses the SMTP login Create a new app password. Enter it in Email Settings Invalid emailsfor one recipientThe address was skipped as undeliverable See Find participants and data managers who cannot receive email No valid To recipientsEvery recipient was skipped Correct the recipient's address mail settings are still in global_config.mailin the logThe update did not finish moving the old settings Run ept run-once -
Search today's log for mail errors:
grep -iE "smtp|mail" /var/www/ept/logs/$(date +%F)-logfile.log | tail -20 -
Find the queue IDs of the failed messages in MySQL:
SELECT temp_id, to_email, subject, updated_at FROM temp_mail WHERE status = 'failed' ORDER BY temp_id DESC LIMIT 20; -
After fixing the cause, put those messages back in the queue:
UPDATE temp_mail SET status = 'pending', failure_reason = NULL WHERE status = 'failed' AND temp_id IN (10746);Replace
10746with thetemp_idvalues from step 4.
Check that mail works¶
- Send yourself an email from Send Email to Participants, or trigger a password reset for a test account.
- Wait up to one minute for the queue to run.
- Confirm the message is not listed on Configure → Failed Emails.
- Confirm the message arrived in the test mailbox.