Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sendcloud Laravel Package

overtrue/sendcloud

A PHP SDK for SendCloud email delivery. It offers a clean, framework-agnostic API to send transactional and bulk email, use templates, manage address lists and tags, and query delivery statistics. Works with Laravel and any PHP app, handling authentication and HTTP requests so you can focus on your...

Deep Wiki
Context7

Getting Started

Install and wire up credentials

composer require overtrue/sendcloud

You need two things from the SendCloud console (发送云 / sendcloud.net) before any code runs:

  1. API_USER and API_KEY — generated under Mail API settings. Treat the key like a password; it can send as any verified sender on the account.
  2. A verified sending domain and sender address — SendCloud rejects from addresses on unverified domains with errors that look like auth failures.

Put them in env, not config files:

SENDCLOUD_API_USER=your_api_user
SENDCLOUD_API_KEY=your_api_key
[email protected]
SENDCLOUD_FROM_NAME="Your App"

First use case: a transactional email

use Overtrue\SendCloud\SendCloud; // confirm exact class name in src/

$client = new SendCloud(
    config('services.sendcloud.user'),
    config('services.sendcloud.key')
);

$client->send([
    'from'     => config('services.sendcloud.from'),
    'fromName' => config('services.sendcloud.from_name'),
    'to'       => ['[email protected]'],
    'subject'  => 'Your receipt',
    'html'     => view('emails.receipt', $data)->render(),
]);

Where to look first

  • README.md — usually one example and the minimum viable call. It is the quickest way to confirm the exact send() signature.
  • src/ — this is a thin wrapper; the client class and its allowed parameters are literally the API. Read it before assuming a method exists.
  • SendCloud's v2 API docs (sendcloud.net/doc/email-v2/) — the SDK mirrors endpoint params, so the docs tell you what keys the array accepts (attachments, cc/bcc, headers, x_smtpapi, etc.).
  • The test suite, if present — fastest source of truth for request shape and response handling.

Start with a raw HTML send to one address, then move to templates (below) once deliverability is confirmed.

Implementation Patterns

Wrap it behind your own service. Don't inject SendCloud into controllers. Create App\Mail\SendCloudMailer (or a Mailer contract) that constructs the client from config, exposes sendHtml(), sendTemplate(), and translates SDK exceptions into your domain exceptions. This is also your seam for tests and for replacing the SDK later.

Laravel binding. Register a singleton in a service provider:

$this->app->singleton(SendCloud::class, fn () => new SendCloud(
    config('services.sendcloud.user'),
    config('services.sendcloud.key')
));

Keep a config/services.php entry for user/key/from/from_name so config:cache picks it up.

Prefer templates for anything content-owned. Raw html sends are fine for one-off transactional mail, but marketing/product copy should live in SendCloud templates and be sent with the template endpoint, passing variables. This decouples copy changes from deploys and keeps large HTML blobs out of PHP.

Always send from a queued job.

class SendWelcomeEmail implements ShouldQueue
{
    use Queueable, InteractsWithQueue;

    public $tries = 3;
    public $backoff = [10, 60, 300];

    public function handle(SendCloudMailer $mailer): void
    {
        $mailer->sendTemplate('welcome', $this->user->email, [
            'name' => $this->user->name,
        ]);
    }
}

Retries belong on the queue, not inside the SDK. Do not retry validation/bounce-type failures; do retry network and 5xx.

Batch and multi-recipient sends. For newsletters or notifications to many users, use the batch endpoint rather than looping a single send — it is dramatically fewer HTTP calls and easier on rate limits. Keep each batch under SendCloud's per-request recipient cap and chunk accordingly.

Inject the HTTP client for tests. The package sits on Guzzle. If the constructor accepts a client, pass a MockHandler and assert the form params your wrapper produces. If it doesn't, hide the SDK behind your Mailer interface and fake that in tests; keep one contract test that hits SendCloud staging to catch upstream param changes.

Webhooks belong in their own controller. SendCloud can POST delivery/bounce/spam events. Accept them at a dedicated route, verify the token/secret, persist raw payloads, and process idempotently (events can be retried). Wire bounces back to your user table so you stop mailing dead addresses.

Log the response, not the secret. Capture statusCode, message, and the message id from each send; log the recipient domain, not the full PII payload. Never log apiKey.

Gotchas and Tips

  • HTTP 200 does not mean success. SendCloud commonly returns 200 with {"result": false, "statusCode": 4xx, "message": "..."}. If you only check the HTTP status, failed sends look successful and you'll silently lose mail. Check result and statusCode on every response.
  • Parameters are form-encoded. Booleans and integers may need to be strings ('true', '1'), and recipients may need array vs comma-joined forms depending on the endpoint. When a field "doesn't work," dump the exact request body first.
  • Sender verification failures masquerade as auth errors. If from isn't on a verified domain you can waste time rotating API keys. Verify the domain and sender in the console first.
  • Template variable syntax is version-sensitive. %name% vs {{name}} differ across SendCloud API generations. A mismatch sends literal placeholders to real users — test template sends to a real inbox, not a mocked client.
  • Set explicit timeouts. The default Guzzle timeout is effectively forever, and a slow SendCloud response will tie up queue workers. Set timeout and connect_timeout (e.g. 10s/5s) when constructing the client.
  • Recipient and attachment limits. There is a per-request recipient cap and a payload limit; base64 attachments blow through it quickly. Prefer attachment URLs or the batch endpoint.
  • Regional latency and Chinese-first docs. The API host is api.sendcloud.net; from outside China expect higher latency. The authoritative docs are Chinese — budget time or use the API reference's parameter tables rather than prose.
  • Coverage gaps. With ~20 stars and a single maintainer, the SDK likely covers mail sending but not every endpoint (address lists, stats, subaccounts). Reach for the underlying Guzzle client and hit the endpoint directly rather than waiting for an SDK feature; or extend the class with one method per missing endpoint.
  • Pin the version. Recent release date notwithstanding, it's a low-traffic package. Use a caret constraint, keep it behind your Mailer interface, and be ready to swap to raw HTTP calls if maintenance stalls.
  • Subaccounts per environment. If your SendCloud plan supports subaccounts, use separate API users for staging and production so a misconfigured from in staging can't burn production reputation.
  • Reputation is shared. SendCloud pools sender reputation per account/domain; bounces and spam complaints from one product can affect another. Prune hard bounces from your lists and keep DMARC/SPF/DKIM set correctly on the sending domain.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings