En vous promenant sur Beamreactor, nous stockons votre IP 48h pour des raisons de sécurité.

Lecteur Markdown

newsletter Documentation › NEWSLETTER_DOCUMENTATION

Newsletter Documentation

XDP Plugin: Newsletter #

Plugin: newsletter.php

Version: 2.1.0

Since: 2004

Last updated: 2025-12-26

Author: Treveur Bretaudière

License: Proprietary

Overview

Batch newsletter sending system with text and HTML support, WYSIWYG editor, configurable batch sending, per-recipient tracking, and dual-audience subscriber management (registered users + visitor subscriptions). Operates in two modes: admin interface for creation/sending, and public subscribe/unsubscribe form for embedding in pages.

Files #

| File | Role |

|---|---|

| newsletter.php | Main plugin — admin interface + embedded public form |

| newsletter_subscribe.php | Standalone subscription form |

| newsletter_send.mod.php | Scheduler module for automated batch sending (JSON API) |

| newsletter.conf.inc.php | Configuration (batch size, access level) |

| newsletter_en_inc.php | English locale |

| newsletter_fr_inc.php | French locale |

| newsletter.sql | Table creation script |

Database #

Table: newsletter #

| Column | Type | Description |

|---|---|---|

| id | INT (PK) | Auto-increment |

| user_id | INT | Creator user ID |

| subject | VARCHAR(998) | Email subject (RFC 2822: 1000 octets max, -2 for CRLF) |

| body_text | TEXT | Plain text content (or HTML fallback) |

| newsletter_html | TEXT | HTML content |

| format | ENUM | text or html |

| status | ENUM | draft, queued, sending, sent, failed |

| total_recipients | INT | Total recipient count |

| sent_count | INT | Successfully sent counter |

| created_at | DATETIME | Creation timestamp |

| sent_at | DATETIME | Completion timestamp (NULL if in progress) |

Table: newsletter_recipients #

| Column | Type | Description |

|---|---|---|

| id | INT (PK) | Auto-increment |

| newsletter_id | INT | FK → newsletter.id (CASCADE delete) |

| user_id | INT | User ID (0 for visitor subscribers) |

| email | VARCHAR(255) | Recipient email |

| status | ENUM | pending, sent, failed |

| sent_at | DATETIME | Sent timestamp |

| error_message | TEXT | Error details on failure |

Table: newsletter_subscription #

| Column | Type | Description |

|---|---|---|

| id | INT (PK) | Auto-increment |

| email | VARCHAR(255) | Visitor email (UNIQUE) |

| subscribed_at | DATETIME | Subscription timestamp |

Stores non-registered visitor subscriptions. Registered users use the email_bot flag in the main user table instead.

Security Model #

| Level | Constant | Capabilities |

|---|---|---|

| Moderator | NEWSLETTER_LEVEL_MODERATOR | Create, preview, queue, send newsletters |

| Scheduler module | NEWSLETTER_LEVEL_MODERATOR | Trigger batch sending via cron |

Public form (subscribe/unsubscribe) requires no authentication.

Sanitization #

Subject: Parser::sanitize(..., 'string', [], 998) — max 998 chars per RFC 2822.

Body text: Parser::sanitize(..., 'string', [['WORDWRAP' => 75]], 65535) — standard email line width + MySQL TEXT limit.

HTML body: Parser::sanitize(..., 'html', ['moderator'], 65535) — tag filtering (script, iframe, etc.).

Subject encoding: =?UTF-8?B?...?= per RFC 2047 for non-ASCII characters.

Architecture #

Dual-mode Operation #

Admin interface ($obj == 'newsletter.php'): creation, preview, queue, batch send, history. Requires NEWSLETTER_LEVEL_MODERATOR.

Public form ($obj != 'newsletter.php' or via newsletter_subscribe.php): toggle subscribe/unsubscribe widget, embeddable in any page. No authentication required.

Subscriber Sources #

Newsletter recipients are aggregated from two sources at queue time:

1. Registered users: SELECT FROM {$cfg['dbtable']} WHERE email_bot='1' AND activated='1'

2. Visitor subscriptions: SELECT FROM newsletter_subscription — with deduplication against registered users (visitors already in the user table are removed from newsletter_subscription and not double-counted)

Data Flow #

text
Registered users → {$cfg['dbtable']}.email_bot ('0'/'1')
Visitor subscribers → newsletter_subscription.email
					↓
			  queueNewsletter()
			  [deduplication + merge]
					↓
		  newsletter_recipients (status='pending')
					↓
			 sendBatch() ×N
					↓
		newsletter.status='sent'

Actions #

list (default) #

URL: ?obj=newsletter.php

Displays table of all newsletters with subject (clickable), creator username, status badge, recipient count, sent count with percentage, and creation date. "Create newsletter" button links to the create form.

create #

URL: ?obj=newsletter.php&action=create

Form fields: subject (max 998 chars, required), format toggle (text/html radio), text textarea (20×80) or RTE HTML editor (800×400, full toolbar with source toggle). Displays active subscriber count. Blocks creation if zero subscribers. Submits to action=preview.

preview #

URL: ?obj=newsletter.php&action=preview (POST)

Validates subject and body. For HTML format, generates a plain text fallback via strip_tags() with 75-column wordwrap. Displays the preview with buttons to queue, edit, or cancel.

queue #

URL: ?obj=newsletter.php&action=queue (POST)

Inserts the newsletter record, retrieves all subscribers (registered + visitors), deduplicates visitor entries against the user table, and inserts all recipients as status='pending'. Displays confirmation with recipient count and link to start sending.

send_batch #

URL: ?obj=newsletter.php&action=send_batch&id={id}

Fetches next batch of pending recipients (default 50, configurable via NEWSLETTER_BATCH_SIZE). Constructs MIME headers, sends via mail(), tracks per-recipient success/failure. Displays sent/failed/remaining counts. If remaining > 0, offers "Send next batch" button. When complete, sets newsletter status to sent.

view #

URL: ?obj=newsletter.php&action=view&id={id}

Read-only view of a newsletter: subject, creator, status, recipient/sent counts, dates, and content preview (HTML rendered + text fallback, or plain text).

Email Format #

Plain text: Content-Type: text/plain; charset=UTF-8; format="flowed" — single-part.

HTML: Content-Type: multipart/alternative with MIME boundary BeamReactor_{website}_{uniqid}. Contains text/plain fallback part followed by text/html part. Ensures clients without HTML rendering receive a readable version.

From: $cfg[11]['noreply'] (priority) or $cfg[10] (fallback).

X-Mailer: BeamReactor/2.0

Scheduler Module #

newsletter_send.mod.php provides a JSON API endpoint for automated batch sending, intended for cron job integration:

bash
*/5 * * * * curl -s "https://example.com/?mod=newsletter_send"

If no specific newsletter ID is provided, it picks the oldest queued or sending newsletter. Returns JSON with success, sent, failed, remaining, and status fields.

Subscribe / Unsubscribe #

Toggle mechanism: same form, same action. If the email is already subscribed, it unsubscribes. If not, it subscribes.

Registered users: toggles email_bot field ('0'/'1') in the user table.

Visitors: INSERT into / DELETE from newsletter_subscription.

Available as embedded form (when newsletter.php is included with $obj != 'newsletter.php') or as standalone plugin (newsletter_subscribe.php).

Configuration #

| Variable | Usage | Default |

|---|---|---|

| NEWSLETTER_BATCH_SIZE | Emails per batch | 50 |

| $cfg[10] | Default sender email | — |

| $cfg[11]['noreply'] | Noreply email (priority) | — |

| $cfg['dbtable'] | User accounts table | — |

| $charset | Email charset | UTF-8 |

| $website | Site name (MIME boundary) | — |

| $basedisplevel | Config access level | BASE_LEVEL_MODERATOR |

Locale #

File: getlocale('newsletter') — Variable: $dialnewsletter[]

| Range | Content |

|---|---|

| 0–8 | Validation errors, sending feedback |

| 9–18 | List view labels, subscriber count |

| 19–27 | Create/edit form labels |

| 28–38 | Queue and batch sending messages |

| 39–41 | Detail view labels |

| 60–67 | Subscribe/unsubscribe form |

Dependencies #

  • Beamreactor\Database\SQL — prepared statements
  • Beamreactor\Sanitizer\Parser — input validation
  • frameheader() / framefooter() — frame system
  • secure() — permission checks
  • forbids() — access denied handler
  • rte-modern.js — WYSIWYG editor
  • mail() — PHP native mail function

Configuration Reference #

| Config | Usage |

|---|---|

| $cfg[0] | Site base URL |

| $cfg[10] | Default sender email |

| $cfg[11]['noreply'] | Noreply email address |

| $cfg[17] | Max file upload size |

| $cfg['dbtable'] | User accounts table name |

de en fr