Skip to main content

WarmupRamp

\Benecaster\Email\Warmup\WarmupRamp

Class Free

Paces a new sending address. While a From domain has little recent sending history, the ramp limits how many standard-priority emails it sends per day and raises the limit each sending day. The email queue fetches the batch that Emails per hour allows and then asks the ramp how many of those rows may go; the rest stay pending. Emails per hour is the ceiling and the ramp sits beneath it.

On plain host mail a domain starts at 50 on its first sending day and doubles each sending day to a hard 2,400 a day, whatever Emails per hour says. With a mail service detected it starts at 500 and doubles to the configured rate. Only days that actually send count. A domain that sends nothing for 30 days moves two steps back down its ladder and climbs again, which takes three sending days. High-priority email (feed URL resets, password resets, security alerts, mail to admins) is exempt and not counted.

The ramp is open loop. Benecaster has no bounce or placement feedback, so it reads only the install’s own sending history and setup. There is no filter to change it. The full-rate override on Settings → Email is honoured only while a mail service is detected. Add-ons read the ramp through describe(), posture() and capacity_over_next_days(); get it from the container.

Constructor Dependencies

Type Description
?\Benecaster\Email\Warmup\WarmupState Optional, defaulted. Per-domain sending history.
?\Benecaster\Email\Warmup\PostureDetector Optional, defaulted. Whether a mail service handles mail, and SPF/DMARC.
?\Benecaster\Admin\DebugLog Optional, defaulted. Records when the ramp held mail back, at info level.

Methods

Method Visibility Since Description
allowed_sends_today( string $domain ): int Public — The whole of today's allowance for the domain: the lower of its ramp step and its ceiling. Not what is left of it; use remaining_today() for that.
remaining_today( string $domain ): int Public — How many more emails the domain may send today.
is_warm( string $domain ): bool Public — True once the domain has reached its ceiling and has had a sending day there without being held back. A day counts even when the queue ran dry, so a show that sends a few emails a day still graduates. A cooled domain is not warm.
capacity_over_next_days( int $messages, string $domain = '', int $max_days = 365 ): array Public — Projects when $messages enqueued now would finish, walking the ramp forward the way it will advance. Returns days, finish_day (Y-m-d, UTC), per_day (day, allowance, sends) and complete, which is false when $max_days ran out first. It is a best case, because WP-Cron fires only on traffic, and it counts what the domain has already sent today. An empty $domain means the site's From domain. See the recipe show-an-honest-finish-date.
posture( string $domain = '' ): SendingPosture Public — The sending-setup reading for a domain (the site's From domain when empty). Reuse it rather than doing your own DNS lookup.
describe( string $domain = '' ): array Public — Everything a screen needs in one call: the posture fields plus sending_days (days that actually sent), first_sent_on and days_since_first_send (the sending age, a different number), allowed_today, remaining_today, ceiling_per_day, is_warm, override_available and override_active. This is the warmup block of GET /email-settings.
record_tick( string $domain, int $sent, int $wanted ): void Public — Called by the email queue each tick with what it sent and what it would have sent without the ramp. The difference is how the ramp knows it held mail back. Not for add-ons.

Constants

Name Value Description
HOST_FIRST_DAY 50 First sending day's allowance on plain host mail.
SERVICE_FIRST_DAY 500 First sending day's allowance with a mail service detected.
HOST_DAILY_CEILING 2400 The most plain host mail sends in a day, whatever Emails per hour says.
COOL_STEPS_BACK 2 Steps down its own ladder a domain drops after 30 days without sending.
OPTION_OVERRIDE 'benecaster_email_warmup_override' The full-rate override switch. Honoured only with a mail service detected.

Notes

Don't estimate a send's duration by dividing by Emails per hour. On a new or cooled domain that promises a date the queue can't meet; use capacity_over_next_days().