Attachments¶
send() has no attachment argument — anything with an attachment goes through the two-phase flow: compose() a draft, attach()/attach_text() add content, dispatch() enqueues it.
DO $$
DECLARE
v_id bigint;
BEGIN
v_id := pgrelay_notifier.compose('mailer', ARRAY['[email protected]'],
'Monthly report', 'Report attached.');
PERFORM pgrelay_notifier.attach(v_id, 'report.pdf', $pdf_bytes$, 'application/pdf');
PERFORM pgrelay_notifier.attach_text(v_id, 'summary.csv', $csv_text$, 'text/csv');
PERFORM pgrelay_notifier.dispatch(v_id);
END;
$$;
attach() takes binary content (bytea); attach_text() takes text (stored as UTF-8) — use it for CSVs, logs, or any attachment you already have as a string rather than raw bytes. Both take an optional content type (default application/octet-stream / text/plain) and an inline flag.
Attachments are frozen at dispatch. Once dispatch() has run, the message is visible to the Processor and may be fetched for delivery at any moment — attach()/attach_text() refuse to add anything more.
Limits are enforced when you attach, not when it's sent¶
Every profile carries two limits:
max_attach_mb— the notification's total attachment payload, in raw bytes (before base64 encoding adds its ~37% overhead on the wire).max_attach_number— how many attachments a single notification may carry.
Exceeding either makes attach()/attach_text() fail immediately, in your own transaction, naming the profile and the limit — not asynchronously, hours later, after a delivery attempt has already been burned. Typical starting values are 10 MB for SMTP profiles and 3 MB for Microsoft 365 (Microsoft's own attachment limit). If you hit one, the error names the fix; raising a profile's limits is a DBA task — see Attachment Limits and Profile Defaults.
One shortcut for a single attachment¶
If your message needs exactly one attachment, the Oracle UTL_MAIL-style functions do compose + attach + dispatch in one call — see The Oracle UTL_MAIL-Style Calls.