> For the complete documentation index, see [llms.txt](https://docs.buildnatively.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buildnatively.com/guides/integration/sms-email.md).

# SMS/Email

## What are native SMS/Email?

The SMS / Email feature opens the device's native messaging or mail composer, pre-filled with the content you provide. The user can review and edit the message before sending - your app doesn't send anything automatically.

This is useful for sharing order confirmations, referral links, support requests, or any other content the user might want to send via SMS or email without leaving the app flow entirely.

![Native Email and SMS composers on iOS (similar on Android)](/files/qHT9WhUgvvAamln0DIPY)

## Prerequisites

{% hint style="success" %}
This feature is available in all plans. [See all plans](/getting-started/subscription-plans.md)
{% endhint %}

## Implementation

Choose your integration method below: **Bubble.io Plugin** (No-Code), **JavaScript SDK** (Code), or **AI Agents** (for AI-powered editors like Lovable, Base44, and Replit).

### Initialization

{% tabs %}
{% tab title="Bubble.io Plugin" %}
**Check Plugin**

Before starting, verify if the Natively plugin is already installed in your Bubble project.

1. Open your Bubble editor and navigate to the Plugins tab in the left sidebar.
2. **Check Installed Plugins:** Look through your list of installed plugins for "Natively iOS & Android app builder".
   * If it IS installed: Check the version number. If an update is available (e.g., you see a button saying "Update"), click it to ensure you have the latest features and bug fixes.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FmfnSUug82IdnxOAoBrak%252Fnatively_app_builder_bubble_plugin_update.png%3Falt%3Dmedia%26token%3Dc193f69f-b03b-4be4-b80b-f34ba37ac212&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=a89e4510&#x26;sv=2" alt=""><figcaption></figcaption></figure>

* If it is NOT installed: Click the + Add plugins button, search for "Natively", and click Install.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FC5rA42yQHcN1uGKFbzmF%252Fnatively_app_builder_bubble_plugin.png%3Falt%3Dmedia%26token%3Dd9706d9b-dbe8-459b-b9b3-5667648aa4b7&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=9aae2297&#x26;sv=2" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="JavaScript SDK" %}
**Check SDK**

Before writing any logic, ensure the Natively SDK is correctly installed and up-to-date in your codebase.

1. Open your project's main HTML file (or header settings) and look for the Natively script tag inside the `<head>` section.
2. Install/Update: If missing or outdated, add the following code. You can specify the SDK version in the URL (e.g., `@2.26.0`).

```javascript
<head>
  <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script>
</head>
```

{% hint style="info" %}
To ensure you are using the most up-to-date version, check the [Natively GitHub releases page](https://github.com/buildnatively/js-sdk/releases) for the latest version number.
{% endhint %}
{% endtab %}

{% tab title="AI Agents" %}
**Initialize the SDK**

AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features. Before implementing any feature, the Natively SDK must be initialized in your project.

Copy the line below and paste it into your AI agent to check and set up the Natively SDK in your project.

```
Check if the following Natively SDK script is present in the <head> of index.html. If missing or outdated, add it: <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script><script>function nativelyOnLoad() { window.natively.setDebug(true); console.log("✅ Natively SDK loaded successfully."); }</script> For reference: https://docs.buildnatively.com/guides/integration/how-to-get-started https://github.com/buildnatively/js-sdk/releases
```

{% endtab %}
{% endtabs %}

### Setup Logic

{% hint style="info" %}
All fields are optional. Any fields left empty can be filled in manually by the user in the composer.
{% endhint %}

{% tabs %}
{% tab title="Bubble.io Plugin" %}

#### \[Element] Natively - SMS/Email

#### Events:

* **SMS action is not allowed \[iOS]** - fires when the user has restricted SMS sending for other apps.
* **SMS sent \[iOS]** - fires when the SMS was successfully sent.
* **SMS sending failed \[iOS]** - fires when the SMS failed to send.
* **SMS sending cancelled \[iOS]** - fires when the SMS composer was closed without sending.
* **Email action is not allowed \[iOS]** - fires when the user has restricted email sending for other apps.
* **Email sent \[iOS]** - fires when the email was successfully sent.
* **Email sending failed \[iOS]** - fires when the email failed to send.
* **Email saved \[iOS]** - fires when the user saved the email as a draft.
* **Email sending cancelled \[iOS]** - fires when the email composer was closed without sending.

#### Actions:

* **Send SMS** - opens the native SMS composer:
  * Recipient - phone number to pre-fill. If left empty, a contact selector will open.
  * Body - the message text to pre-fill.
* **Send Email** - opens the native email composer:
  * Subject - the email subject to pre-fill.
  * Recipient - email address to pre-fill.
  * Body - the email body to pre-fill.
    {% endtab %}

{% tab title="JavaScript SDK" %}

```javascript
// ============================================================================
// NATIVELY SMS / EMAIL - DOCUMENTATION & EXAMPLES
// ============================================================================

// Initialize
const message = new NativelyMessage();

// ============================================================================
// ALL AVAILABLE METHODS
// ============================================================================
// message.sendSMS(body, recipient, callback)
//   - Opens the native SMS composer pre-filled with the provided content.
//   - The user reviews and sends the message manually.
//   - body: string — the message text to pre-fill. Pass an empty string to leave blank.
//   - recipient: string — phone number to pre-fill. Pass an empty string to open contact selector.
//                         Multiple recipients supported on Android (separate with , or ;)
//   - callback: function — called after the composer is closed
//
// message.sendEmail(subject, body, recipient, callback)
//   - Opens the native email composer pre-filled with the provided content.
//   - The user reviews and sends the email manually.
//   - subject: string — the email subject to pre-fill. Pass an empty string to leave blank.
//   - body: string — the email body to pre-fill. Pass an empty string to leave blank.
//   - recipient: string — email address to pre-fill. Pass an empty string to open a blank composer.
//                         Multiple recipients supported on Android (separate with , or ;)
//   - callback: function — called after the composer is closed

// ============================================================================
// CALLBACK RESPONSE FIELDS - sendSMS
// ============================================================================
// resp.status:
//   iOS:     "SENT" / "CANCELLED" / "FAILED" / "NOT_ALLOWED"
//   Android: "SMS SENT!" (always returned regardless of actual outcome)

// ============================================================================
// CALLBACK RESPONSE FIELDS - sendEmail
// ============================================================================
// resp.status:
//   iOS:     "SENT" / "CANCELLED" / "FAILED" / "NOT_ALLOWED" / "SAVED"
//   Android: "SENT" (always returned regardless of actual outcome)

// --- SMS / Email. SMS Example. Start ---

const sms_body = "Check out this referral link: https://yourapp.com/referral";
const sms_recipient = "+1234567890"; // leave empty "" to open contact selector

const send_sms_callback = function(resp) {
    console.log("SMS status:", resp.status);
};

message.sendSMS(sms_body, sms_recipient, send_sms_callback);

// --- SMS / Email. SMS Example. End ---


// --- SMS / Email. Email Example. Start ---

const email_subject = "Your order confirmation";
const email_body = "Thank you for your order. Here are your details...";
const email_recipient = "customer@example.com"; // leave empty "" to open blank composer

const send_email_callback = function(resp) {
    console.log("Email status:", resp.status);
};

message.sendEmail(email_subject, email_body, email_recipient, send_email_callback);

// --- SMS / Email. Email Example. End ---
```

{% endtab %}

{% tab title="AI Agents" %}
AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features.&#x20;

Copy the relevant line below and paste it into your AI agent.&#x20;

#### Natively SMS

<pre><code>[<a data-footnote-ref href="#user-content-fn-1">Your feature description</a>] using the Natively SMS SDK: const message = new NativelyMessage(); // message.sendSMS(body, recipient, callback) — opens native SMS composer pre-filled with provided content. body: string — message text, empty string leaves blank. recipient: string — phone number, empty string opens contact selector. Multiple recipients on Android: separate with , or ;. resp.status — iOS: "SENT"/"CANCELLED"/"FAILED"/"NOT_ALLOWED". Android: always "SMS SENT!". For reference: https://docs.buildnatively.com/guides/integration/sms-email
</code></pre>

{% hint style="warning" %}
Replace the placeholder at the beginning with a description of what you want to build - for example: "Open the native SMS composer pre-filled with a referral link when the user taps the share button".
{% endhint %}

#### Natively Email

<pre><code>[<a data-footnote-ref href="#user-content-fn-1">Your feature description</a>] using the Natively Email SDK: const message = new NativelyMessage(); // message.sendEmail(subject, body, recipient, callback) — opens native email composer pre-filled with provided content. subject: string — email subject, empty string leaves blank. body: string — email body, empty string leaves blank. recipient: string — email address, empty string opens blank composer. Multiple recipients on Android: separate with , or ;. resp.status — iOS: "SENT"/"CANCELLED"/"FAILED"/"NOT_ALLOWED"/"SAVED". Android: always "SENT". For reference: https://docs.buildnatively.com/guides/integration/sms-email
</code></pre>

{% hint style="warning" %}
Replace the placeholder at the beginning with a description of what you want to build - for example: "Open the native email composer pre-filled with an order confirmation when the user taps contact support".
{% endhint %}
{% endtab %}
{% endtabs %}

### How to use

#### Pre-fill as much as possible

The more you pre-fill, the less friction for the user. At minimum, pre-fill the recipient and body - a user who just needs to tap send is more likely to complete the action than one who has to type everything manually.

#### Leave fields empty when appropriate

If you don't know the recipient upfront - for example, when the user wants to share something with a contact of their choice - leave the recipient empty. For SMS, this opens a contact selector; for email, it opens a blank composer.

#### Handle callback statuses carefully on Android

On Android, the callback always returns `SENT` for email and `SMS SENT!` for SMS, regardless of what actually happened - the user may have cancelled, or the message may have failed. Do not rely on the Android callback status to confirm delivery. On iOS, the statuses are accurate and can be used to trigger follow-up logic.

#### `SAVED` status on iOS email

If `resp.status` returns `SAVED`, the user saved the email as a draft rather than sending it. Handle this case in your callback if your flow depends on the email being sent.

#### No sending without user confirmation

The feature always opens the native composer - your app never sends SMS or email automatically. The user must tap send themselves.

## Troubleshooting

<details>

<summary>The SMS or email composer is not opening</summary>

Make sure the feature is triggered from a user interaction - like a button tap - rather than automatically on page load. Also, verify the SDK is fully loaded before calling the method.

</details>

<details>

<summary><code>NOT_ALLOWED</code> status on iOS</summary>

The user has restricted the app from sending SMS or email in their device settings. This is a user-controlled permission - you can prompt them to go to **Settings → \[Your App] → Allow Sending** to re-enable it.

</details>

<details>

<summary>Android callback always returns <code>SENT</code> or <code>SMS SENT!</code></summary>

This is expected behavior on Android - the callback status does not reflect the actual outcome. Do not rely on Android callback status to confirm whether the message was sent, cancelled, or failed.

</details>

<details>

<summary>Multiple recipients are not working</summary>

Multiple recipients are confirmed to work on Android by separating with `,` or `;`. If you are experiencing issues on iOS, test with a single recipient first - multiple recipient behavior on iOS has not been fully confirmed.

</details>

<details>

<summary>The email composer opens, but no email client is installed</summary>

On some Android devices, if no email client is installed, the composer will not open. This is a device-level limitation - consider showing a fallback message if your audience includes users who may not have an email app configured.

</details>

[^1]: Replace this placeholder
