Developer notes
File map
Section titled “File map”| Path | Purpose |
|---|---|
app/addons/kv_email_log/addon.xml |
Settings, tables, privileges |
app/addons/kv_email_log/init.php |
Hook registration |
app/addons/kv_email_log/func.php |
Hook handlers, GDPR callbacks, cron info, uninstall |
app/addons/kv_email_log/controllers/backend/kv_email_log.php |
Log, details, preview, resend, queue, templates, test, privacy, export, cron |
app/addons/kv_email_log/controllers/backend/orders.post.php, profiles.post.php |
E-mails tabs |
Tygh/Addons/KvEmailLog/Capture.php |
Decides per e-mail: send and log, mute or queue |
Tygh/Addons/KvEmailLog/Transport/ProxyTransport.php |
Transport wrapper used for one send |
Tygh/Addons/KvEmailLog/Sender.php |
Sends a logged message, records the result, retries, resend |
Tygh/Addons/KvEmailLog/Queue.php |
Deferred sending, cron worker, rate limit, stale claims |
Tygh/Addons/KvEmailLog/Repository.php |
Storage, search, retention, privacy |
Tygh/Addons/KvEmailLog/Codec.php |
Message description, body packing, order/customer links |
Tygh/Addons/KvEmailLog/Diagnostics.php |
Test e-mail, SMTP transcript, DNS checks |
Tygh/Addons/KvEmailLog/Presenter.php |
View data, preview document, CSV |
Tygh/Addons/KvEmailLog/License/*, Upgrade/Synchronizer.php |
License client, self-healing upgrades |
schemas/gdpr/user_data.post.php |
Core GDPR integration |
schemas/menu/*, schemas/permissions/* |
Menu entries, privileges, vendor access, cron URL |
design/backend/templates/addons/kv_email_log/ |
Admin and vendor pages |
design/backend/css/addons/kv_email_log/styles.less, js/addons/kv_email_log/admin.js |
Styles, preview switch |
How sending is captured
Section titled “How sending is captured”Every e-mail of CS-Cart goes through Tygh\Mailer\Mailer::send(), which calls the hook mailer_send_pre($mailer, $transport, $message, $area, $lang_code) right before $transport->sendMessage($message). The add-on registers this hook with priority 4294967000, so it runs after the add-ons that change the message (for example the core PDF documents add-on attaching an invoice). The handler replaces $transport (passed by reference) with ProxyTransport for this one send:
- send: a log row is written, the real transport sends, the result (status, error, duration, transport type) is recorded. A temporary failure becomes a retry.
- mute: logged as muted, not sent, success returned (no error notice).
- queue: the message (body, addresses, attachment copies) is stored and success is returned at once;
Queuesends it at the end of the request (fastcgi_finish_request()/litespeed_finish_request()first) or from cron, with the transportMailer::send()would have chosen (company transport or the default one).
If anything in the add-on fails (database error, missing table), the proxy calls the real transport directly: the e-mail always goes out. When Mailer::send() is called with its own transport settings, the e-mail is never queued.
Callers of Mailer::send() get true for queued and muted e-mails. A queued e-mail that finally fails is visible in the log, not to the caller.
Tables
Section titled “Tables”| Table | Contents |
|---|---|
?:kv_eml_log |
One row per e-mail: status, origin, area, language, template code, company, storefront, owner (vendor) company, order, customer, addresses, subject, size, attachments (JSON), transport, duration, attempts and their history, next attempt, error, resend link, message state, queue claim |
?:kv_eml_recipients |
Recipient index (address, entry, To/CC/BCC) for search and privacy requests |
?:kv_eml_bodies |
Stored messages (deflated and base64-encoded, so any character survives a utf8 connection) and metadata (charset, exact subject, embedded images) |
Attachment copies live in var/kv_email_log/<log_id>/ (web access denied).
Hooks used
Section titled “Hooks used”| Hook | Where (4.17.2 and 4.21.2, identical arguments) | Use |
|---|---|---|
mailer_send_pre |
app/Tygh/Mailer/Mailer.php |
Capture |
update_addon_status_pre |
app/functions/fn.addons.php |
Send the queue before the add-on is disabled |
Statuses
Section titled “Statuses”P sending, S sent, F failed, R retrying, Q queued, M muted, X cancelled. Origin: M store, R resend, T test.
Cron and console
Section titled “Cron and console”php admin.php --dispatch=kv_email_log.cron # send the queue and due retries, daily cleanupphp admin.php --dispatch=kv_email_log.cron --purge=1 # also force the cleanupphp admin.php --dispatch=kv_email_log_license.check # license checkClaims are atomic (UPDATE ... SET lock_token ... LIMIT n), so several workers never send the same e-mail. Claims older than 10 minutes go back to the queue; inline sends that never finished are closed as failed (their outcome is unknown, so they are not sent twice).
Performance
Section titled “Performance”Logging adds the row, the recipient index and the stored message per e-mail (a few milliseconds; the mail server itself usually takes 100 ms or more). Queued sending answers in a few milliseconds instead of waiting for the mail server. List pages use indexed filters; the daily cleanup deletes in batches of 5000 (10,000 entries in about half a second on a test store).
License check
Section titled “License check”fn_kv_email_log_is_licensed() (License\Client::isActive()) together with the Log e-mails setting gates the capture (logging, muting, queueing), resend, bulk resend and the test e-mail. The log, the preview, the export, the cleanup, the privacy tools and the delivery of e-mails already queued always work. The licence check itself runs only in the admin panel or from cron.