> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brudcast.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send your first email

> Send a first email from a campaign, the send API or the SMTP relay, and check what happened to it.

export const DemoVideo = ({id, title, embedUrl, src, poster, duration}) => {
  if (embedUrl) {
    return <figure className="brd-media" data-media-id={id}>
        <iframe className="brd-media-frame w-full aspect-video" src={embedUrl} title={title} allow="accelerometer; autoplay; clipboard-write; encrypted-media; picture-in-picture" allowFullScreen />
      </figure>;
  }
  if (src) {
    return <figure className="brd-media" data-media-id={id}>
        <video className="brd-media-frame w-full aspect-video" src={src} poster={poster} controls playsInline preload="metadata" />
      </figure>;
  }
  const label = duration ? `Video walkthrough coming soon · ${duration}` : "Video walkthrough coming soon";
  return <Placeholder id={id} kind="video" label={label} description={title} ratio="16 / 9" icon={<PlayIcon />} />;
};

export const Screenshot = ({id, src, srcDark, alt, caption}) => {
  if (!src) {
    return <Placeholder id={id} kind="screenshot" label="Screenshot coming soon" description={alt} icon={<ImageIcon />} />;
  }
  return <figure className="brd-media" data-media-id={id}>
      <img className="brd-media-frame block dark:hidden" src={src} alt={alt} />
      <img className="brd-media-frame hidden dark:block" src={srcDark || src} alt={alt} />
      {caption && <figcaption className="brd-media-caption">{caption}</figcaption>}
    </figure>;
};

Get a first email out of Brudcast in whichever way suits you: from the dashboard, from code, or from
an application that already speaks SMTP.

<Screenshot id="ss-email-first-email-hero-campaign-results" alt="A campaign results page showing a first email campaign as sent, with one recipient delivered" />

<Info>
  **Before you start:**

  * For a campaign: the managed sending address or a verified domain, at least one contact, and your
    postal address in [Organization Settings](/organization/organization-settings).
  * For the send API or SMTP: a verified domain of your own, plus a
    [sending key](/channels/email/domain-api-keys) or an [SMTP user](/channels/email/smtp-users).
</Info>

<Accordion title="Watch the walkthrough" icon="circle-play">
  <DemoVideo id="V03" title="Send your first email in 5 minutes" duration="3 min" />
</Accordion>

<Tabs>
  <Tab title="Campaign">
    <Steps>
      <Step title="Have at least one contact">
        Add yourself under **Contacts**, or import a CSV. See
        [Add and edit contacts](/contacts/add-and-edit-contacts).
      </Step>

      <Step title="Create an email campaign">
        Go to **Campaigns**, start a new campaign, and choose email as the channel.
      </Step>

      <Step title="Pick the audience and sender">
        Choose a list, a segment or individual contacts. Pick a from address on a verified domain, or
        the managed sending address.
      </Step>

      <Step title="Write the content">
        Add a subject, preview text and a body. Build it in the visual builder, or write HTML or plain
        text.
      </Step>

      <Step title="Check it first">
        Preview the email from the campaign, or send this first campaign to an audience that
        contains only your own contact. See
        [Create and send a campaign](/campaigns/create-a-campaign).
      </Step>

      <Step title="Send or schedule">
        The send checklist tells you if anything is missing. See
        [Send checklist](/campaigns/send-checklist).
      </Step>
    </Steps>

    Full detail is in [Create a campaign](/campaigns/create-a-campaign).
  </Tab>

  <Tab title="Send API">
    Post a message with your sending key in the `Authorization` header.

    <CodeGroup>
      ```bash cURL theme={"system"}
      curl -X POST https://mailing-service.prod.brudcast.com/api/v1/send \
        -H "Authorization: Bearer your_sending_key" \
        -H "Content-Type: application/json" \
        -d '{
          "from": { "name": "Example Co", "address": "hello@mail.example.com" },
          "to": [{ "name": "Jane", "address": "jane@example.com" }],
          "subject": "Hello from Brudcast",
          "html": "<p>It works.</p>",
          "text": "It works."
        }'
      ```

      ```js Node.js theme={"system"}
      const response = await fetch("https://mailing-service.prod.brudcast.com/api/v1/send", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.BRUDCAST_SENDING_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          from: { name: "Example Co", address: "hello@mail.example.com" },
          to: [{ name: "Jane", address: "jane@example.com" }],
          subject: "Hello from Brudcast",
          html: "<p>It works.</p>",
          text: "It works.",
        }),
      });

      const { data } = await response.json();
      console.log(data.jobId);
      ```

      ```python Python theme={"system"}
      import os
      import requests

      response = requests.post(
          "https://mailing-service.prod.brudcast.com/api/v1/send",
          headers={"Authorization": f"Bearer {os.environ['BRUDCAST_SENDING_KEY']}"},
          json={
              "from": {"name": "Example Co", "address": "hello@mail.example.com"},
              "to": [{"name": "Jane", "address": "jane@example.com"}],
              "subject": "Hello from Brudcast",
              "html": "<p>It works.</p>",
              "text": "It works.",
          },
      )

      print(response.json()["data"]["jobId"])
      ```

      ```php PHP theme={"system"}
      <?php
      $payload = [
          'from' => ['name' => 'Example Co', 'address' => 'hello@mail.example.com'],
          'to' => [['name' => 'Jane', 'address' => 'jane@example.com']],
          'subject' => 'Hello from Brudcast',
          'html' => '<p>It works.</p>',
          'text' => 'It works.',
      ];

      $ch = curl_init('https://mailing-service.prod.brudcast.com/api/v1/send');
      curl_setopt_array($ch, [
          CURLOPT_POST => true,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_HTTPHEADER => [
              'Authorization: Bearer ' . getenv('BRUDCAST_SENDING_KEY'),
              'Content-Type: application/json',
          ],
          CURLOPT_POSTFIELDS => json_encode($payload),
      ]);

      $response = json_decode(curl_exec($ch), true);
      echo $response['data']['jobId'];
      ```
    </CodeGroup>

    A successful call returns `202`:

    ```json theme={"system"}
    {
      "status": true,
      "message": "Email queued for delivery",
      "data": { "jobId": "0b6f7c1e-4d2a-4f5e-9a3b-2c8d1e7f6a90" }
    }
    ```

    `202` means Brudcast accepted the message and queued it, not that it was delivered. The send API
    uses `status` in its response, where the platform API uses `success`.

    The full field list is in [Send email over HTTP](/developers/sending/http-api).
  </Tab>

  <Tab title="SMTP">
    Point your application's mailer at the relay with an SMTP user's credentials.

    | Setting               | Value                                              |
    | --------------------- | -------------------------------------------------- |
    | Host                  | `out-smtp.prod.brudcast.com`                       |
    | Port                  | `587` with STARTTLS (or `465` with TLS, or `2525`) |
    | Username and password | From the domain's **SMTP Credentials** tab         |

    <CodeGroup>
      ```bash cURL theme={"system"}
      cat > message.txt <<'EOF'
      From: Example Co <hello@mail.example.com>
      To: Jane <jane@example.com>
      Subject: Hello from Brudcast

      It works.
      EOF

      curl --url "smtp://out-smtp.prod.brudcast.com:587" --ssl-reqd \
        --mail-from "hello@mail.example.com" \
        --mail-rcpt "jane@example.com" \
        --user "your_smtp_username:your_smtp_password" \
        --upload-file message.txt
      ```

      ```js Node.js theme={"system"}
      import nodemailer from "nodemailer";

      const transporter = nodemailer.createTransport({
        host: "out-smtp.prod.brudcast.com",
        port: 587,
        secure: false,
        requireTLS: true,
        auth: {
          user: process.env.BRUDCAST_SMTP_USERNAME,
          pass: process.env.BRUDCAST_SMTP_PASSWORD,
        },
      });

      await transporter.sendMail({
        from: '"Example Co" <hello@mail.example.com>',
        to: "jane@example.com",
        subject: "Hello from Brudcast",
        text: "It works.",
        html: "<p>It works.</p>",
      });
      ```

      ```python Python theme={"system"}
      import os
      import smtplib
      from email.message import EmailMessage

      msg = EmailMessage()
      msg["From"] = "Example Co <hello@mail.example.com>"
      msg["To"] = "jane@example.com"
      msg["Subject"] = "Hello from Brudcast"
      msg.set_content("It works.")

      with smtplib.SMTP("out-smtp.prod.brudcast.com", 587) as smtp:
          smtp.starttls()
          smtp.login(os.environ["BRUDCAST_SMTP_USERNAME"], os.environ["BRUDCAST_SMTP_PASSWORD"])
          smtp.send_message(msg)
      ```
    </CodeGroup>

    The relay drops Bcc-only recipients, `Reply-To` and custom headers. See
    [SMTP users](/channels/email/smtp-users) for the rules.
  </Tab>
</Tabs>

## Check what happened

* **Campaigns:** open the campaign's results. See [Campaign results](/campaigns/results).
* **API and SMTP:** look the message up with the platform API at
  `GET /api/v1/user/messages/{jobId}` (scope `messages:read`), or subscribe to
  [webhooks](/developers/webhooks/overview). See [Message status](/developers/sending/message-status).

"Delivered" means the receiving mail server accepted the message. It doesn't tell you whether the
message reached the inbox or the spam folder.

## If it didn't arrive

<AccordionGroup>
  <Accordion title="The call returned 202 but nothing arrived">
    **Why:** `202` only means queued. The recipient may be on your suppression list, which drops them
    without an error, or the receiving server may have bounced or deferred the message.
    **Fix:** check [Message status](/developers/sending/message-status) and your
    [suppression list](/contacts/suppressions).
  </Accordion>

  <Accordion title="The call was refused">
    **Why:** the error message says what's wrong, for example a from address on the wrong domain.
    **Fix:** find the exact message in [Email troubleshooting](/channels/email/troubleshooting).
  </Accordion>
</AccordionGroup>

## Related

<Columns cols={2}>
  <Card title="Email troubleshooting" icon="life-buoy" href="/channels/email/troubleshooting">
    Every send error, and its fix.
  </Card>

  <Card title="Developer quickstart" icon="rocket" href="/developers/quickstart">
    From API key to first send and webhook.
  </Card>
</Columns>
