Skip to main content

benecaster_send_email()

Utilities Free
benecaster_send_email( int $user_id, string $type, string $subject, string $template, array $context = [] ): int

Sends one Benecaster email to a WordPress user through the full dispatch pipeline. This is the supported way for an add-on to perform a send — a hook cannot do it, because benecaster_before_email_send lets you react to a send already under way and cannot be invoked to start one.

Registering a type does not make it send. benecaster_managed_email_types is a descriptive catalogue that makes a type discoverable and editable in the Email Editor; this function is what dispatches one. The two are separate steps and both are needed.

Everything the internal path does, this does: the should_send gate (and therefore unsubscribe suppression), merge-tag assembly, template resolution, subscriber-locale selection, the subject/body/from/header filters, and the before/after send actions. It is a pass-through, not a reimplementation.

Parameters

Name Type Default Required Description
user_id int — Yes Recipient WordPress user ID. Not an email address — see the notes.
type string — Yes Email type slug, e.g. welcome. Register it with benecaster_managed_email_types first so podcasters can find and edit it.
subject string — Yes Subject line; merge tags are replaced. '' sends the type's registered default_subject.
template string — Yes Template name resolved by the renderer. '' uses the type's registered default_template_path.
context array [] No Merge-tag context. A show_id key doubles as the send's show context — pass it whenever you have one.

Return Value

Type: int

The benecaster_email_queue row ID, or 0 when a filter suppressed the send, when the user has no address, or when the send failed. It is not a delivery result — the queue sends later, on the benecaster_process_email_queue cron pass.

Example

$queue_id = benecaster_send_email(
    $user_id,
    'my_episode_notification',
    sprintf( __( 'New episode: %s', 'my-addon' ), get_the_title( $episode_id ) ),
    'my-addon/episode-notification',
    [
        'show_id'       => $show_id,
        'episode_title' => get_the_title( $episode_id ),
        'episode_url'   => get_permalink( $episode_id ),
    ]
);

// 0 means suppressed or failed — most often an opt-out, which is not an
// error and must not be retried.
if ( 0 === $queue_id ) {
    return;
}

Notes

Do not resolve EmailManager from the container to do this. That was the only route before this function existed, and it made an internal class part of the published surface. The class is not stable; this function is.

Pass show_id in $context whenever you have it. Unsubscribe enforcement needs both the user and the show — omit the show and a subscriber who opted out of that show still receives the mail.

Pass '' for $subject and $template to send what the type registered. Register your type in benecaster_managed_email_types with a default_subject and a default_template_path, then pass '' for both, so an email editor shows, edits and resets the same subject you send. A subject's {{tags}} are replaced after the benecaster_email_subject filter runs. With an empty $template and no registered template, nothing is sent and the return is 0.

$user_id is a WordPress user ID, not an email address, and that is deliberate. The queue stores recipient_user_id and resolves the address from it; a row for an address with no user account enqueues with user_id = 0 and is then failed permanently by the processor. Accepting an arbitrary address would promise delivery the queue cannot make. Resolve an address first with benecaster_get_user_id_by_subscriber_email(). The address is read from the account when the queue sends, not when you call this, so someone who changes their WordPress email after the send is queued receives it at the new address.

A 0 return is the only signal a caller gets that a filter suppressed the send, which is why this returns an int rather than a bool. Treat it as do not retry, not as a transient failure — the most common cause is an opt-out, which is not an error.

For one-off mail with no registered type behind it, use benecaster_mail() instead.

Need this built rather than just documented? See our services →