From redaxo-yform
Guides YForm email templates with REX_YFORM_DATA placeholders, tpl2email form actions, programmatic PHP sending, attachments, and substitution troubleshooting.
npx claudepluginhub friendsofredaxo/claude-marketplace --plugin redaxo-yformThis skill uses the workspace's default tool permissions.
YForm ships its own email-template system, separate from REDAXO's content. Templates live under **YForm → Email Templates** in the backend with a key, subject, plain-text body, optional HTML body, and From/To metadata.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Builds production-ready Apache Airflow DAGs with patterns for operators, sensors, testing, and deployment. For data pipelines, workflow orchestration, and batch jobs.
Share bugs, ideas, or general feedback.
YForm ships its own email-template system, separate from REDAXO's content. Templates live under YForm → Email Templates in the backend with a key, subject, plain-text body, optional HTML body, and From/To metadata.
Inside a template body or subject, reference form fields with:
REX_YFORM_DATA[field="fieldname"]
For choice fields, two extra suffixes give you the human-readable labels instead of the stored values:
REX_YFORM_DATA[field="choice_field_LABELS"] -- choice labels as comma-separated text
REX_YFORM_DATA[field="choice_field_LIST"] -- choice labels with line breaks
Inline PHP also works inside templates:
<?php
if ('REX_YFORM_DATA[field="anrede"]' == 'w') {
echo "Frau";
} else {
echo "Herr";
}
?>
Substitution happens after placeholder replacement, so the literal 'REX_YFORM_DATA[...]' becomes the field value before PHP runs.
tpl2email)$yform->setActionField('tpl2email', [
'template_key', // backend template key
'', // sender email field (or '' to use template's From)
'email', // recipient email field name
]);
In pipe syntax:
action|tpl2email|template_key|email_sender_field|email_recipient_field
The action runs after validation passes. Multiple tpl2email actions per form are allowed (e.g. notify admin + send confirmation to user).
Use this when you need to send a YForm email template from a cronjob, a callback action, or anywhere outside the form lifecycle:
$tpl = rex_yform_email_template::getTemplate('template_key');
if (!$tpl) {
return; // template doesn't exist
}
$values = [
'vorname' => 'Max',
'nachname' => 'Mustermann',
'email' => 'max@example.com',
];
foreach ($values as $key => $value) {
foreach (['body', 'body_html', 'subject'] as $part) {
$tpl[$part] = str_replace(
'REX_YFORM_DATA[field="' . $key . '"]',
$value,
$tpl[$part]
);
}
}
$tpl['mail_to'] = 'recipient@example.com';
rex_yform_email_template::sendMail($tpl);
The $tpl array stays mutable up to sendMail() – set mail_from, mail_to, mail_cc, mail_bcc, mail_reply_to, attachments directly before sending.
When a form has an upload field, route the uploaded files into the template attachments:
$yform->setValueField('upload', ['attachment', 'Attachment']);
$yform->setValueField('php', ['php_attach', 'Attach',
'<?php if (isset($this->params["value_pool"]["files"])) {
$this->params["value_pool"]["email_attachments"] =
$this->params["value_pool"]["files"];
} ?>'
]);
$yform->setActionField('tpl2email', ['template_key', '', 'email']);
The php value field re-keys uploads into the email_attachments pool that tpl2email reads.
If the template uses an HTML body, every REX_YFORM_DATA[...] placeholder that contains user input is interpolated raw. Always wrap user-provided strings in HTML-escaping inside the template:
<p>From: <?= rex_escape('REX_YFORM_DATA[field="email"]') ?></p>
For plain-text bodies, escaping is unnecessary but newlines from textareas come through as-is — make sure the template doesn't accidentally HTML-render those.
Create one template per language with a _<clang_code> suffix (e.g. contact_form_de, contact_form_en). Pick the right one in PHP before sending:
$key = 'contact_form_' . rex_clang::getCurrent()->getCode();
$tpl = rex_yform_email_template::getTemplate($key)
?? rex_yform_email_template::getTemplate('contact_form_de'); // fallback
tpl2email that doesn't exist – the action silently fails. Verify the template key in the backend.mail_to from a user-controlled field without validating it as an email – open relay risk.body_html only without a plain-text body – Gmail and several corporate mail filters quarantine messages.