# llEmail

*LSL function*

```lsl
void llEmail(string address, string subject, string msg);
```

- `string address`: Destination email address.
- `string subject`: Subject of the email.
- `string msg`: Message body of the email.

- Delay: 20 s
- Energy: 10

Sends an email with the given destination address, subject, and body msg. The email will be sent from `{ll.GetKey()}@lsl.secondlife.com`. This can be used for script communication; see llGetNextEmail()

Sends an email to **address** with **subject** and `message`.

The entire message (including the address, **subject** and other miscellaneous fields) can't be longer than 4096 bytes combined.

```lsl title="How to use" frame="terminal"
llEmail("", "", "");
```

## Specification

The `message` is prefixed with information about the [prim](https://wiki.secondlife.com/wiki/Primitive) sending the email.

<table>
	<tr>
		<th>Template</th>
		<th>Example</th>
	</tr>
	<tr>
		<td>

			```lsl
			Object-Name: *prim*
			Region: *simname* (*simpos.x*, *simpos.y*)
			Local-Position: (*primpos.x*, *primpos.y*, *primpos.z*)

			*message*
			```

		</td>
		<td>

			```lsl
			Object-Name: Object
			Region: Gibson (254976, 256000)
			Local-Position: (117, 129, 50)

			The real message starts here.
			```

		</td>
	</tr>
</table>

## Caveats

- If you're sending to the [object](https://wiki.secondlife.com/wiki/object) [owner](https://wiki.secondlife.com/wiki/Category:LSL_Owner), prefer the [llTargetedEmail](/functions/llTargetedEmail/) method.
- There is a limit to the number of email messages an object can send in a given amount of time.
- There is a limit of 500 messages from a single [agent](/constants/AGENT/)'s objects in a one-hour period.
- The 4096-byte size limit includes the **subject** line and automatically added text. The practical maximum body size is approximately 3600 bytes.
- (Sept-2008) The Email Throttle was modified slightly, Per Prospero Linden's comments:

> "there has long been a throttle that makes a single script sleep for 20 seconds after sending an email. The new throttle is per user... some were using many, many different [scripts](https://wiki.secondlife.com/wiki/scripts) to send spam. (the new throttle applies) when the destination is outside of Second Life. I know that messages within the same [region](https://wiki.secondlife.com/wiki/region) were not throttled (beyond the 20-second delay), and I \*believe\* that messages between different [sims](https://wiki.secondlife.com/wiki/simulator) were not throttled (between the 20-second delay)."

- Due to the bug [SVC-23](https://jira.secondlife.com/browse/SVC-23) (present since 2005), objects may stop receiving emails completely until either the region is restarted or the object crosses a region boundary (resetting the script doesn't help). Emails sent may eventually be received after a restart/region-cross. Hence, don't rely on this function for reliable inter-region messaging.
- Due to bug [BUG-229767](https://jira.secondlife.com/browse/BUG-229767), an object's email queue can still become suspended until the object crosses a region border (neither a region restart nor a script reset helps). First analysis has revealed a potential workaround, by implementing a delay of about 30 seconds before first trying to send email to a freshly rezzed script - apparently registering the [email(...)](/events/email/) event handler can take quite some time, and emails arriving prior to said registry process is what gets the entire queue stuck. Official Linden Lab response still pending.
- Due to the bug [SVC-391](https://jira.secondlife.com/browse/SVC-391), [llEmail](/functions/llEmail/) will silently fail (no mail will arrive) when [non-ASCII](https://en.wikipedia.org/wiki/ASCII) characters are present in the **subject**. However, non-ASCII characters in the message body will be replaced by `"?"`.

## Examples

<details open>
<summary>Example 1</summary>

```lsl collapse={1-10}
string emailAddress = "somebody@example.com";
string emailHeader = "Someone touched me!";

default
{
    touch_start(integer num_detected)
    {
        // llSay(PUBLIC_CHANNEL, "Sending eMail report now, this will take ~20 seconds.");

        key id = llDetectedKey(0);
        string name = llDetectedName(0);

        llEmail(emailAddress, emailHeader,
            "I was touched by: '" + name + "' (" + (string)id + ").");

        // llSay(PUBLIC_CHANNEL, "Email has been sent.");
    }
}
```

</details>

## Helper functions

```lsl
email(string time, string address, string subj, string message, integer num_left)
{
    if (llGetSubString(address, -19, -1) == "@lsl.secondlife.com") //trim the header
        message = llDeleteSubString(message, 0, llSubStringIndex(message, "\n\n") + 1);
}
```

Get the region name and object position of the object that sent the email:

```lsl
string region = llList2String(llParseString2List(message, ["Region: "," ("], []),1);
vector position = (vector) ("<" + llList2String(llParseString2List(message, ["Local-Position: (",")\n\n"], []),1) + ">");
```

## Notes

- Because of the long delay on this function, it is often called from a second script triggered by [link_message](/events/link_message/).
- If you are sending email to a prim within Second Life, its address is `''[key]''@lsl.secondlife.com`
  - Which means if the key returned by [llGetKey](/functions/llGetKey/) is "`a2e76fcd-9360-4f6d-a924-000000000003`", then its email address is "`a2e76fcd-9360-4f6d-a924-000000000003@lsl.secondlife.com`".
  - Agents do not have fixed email addresses, use [llInstantMessage](/functions/llInstantMessage/) or [llOwnerSay](/functions/llOwnerSay/)[^wiki-5a8d27].

### Prim2Prim Email

In LSL you can both send email with [llEmail](/functions/llEmail/) and receive it with the [email](/events/email/) event.

The email event is triggered with five pieces of information:

- string — time — When the message was sent, in the `(string)llGetUnixTime` format
- string — address — Who sent the message
- string — **subject** — Subject of the message
- string — message — Body of the message
- integer — num_left — The number of emails left in the email queue

<table>
</table>

When receiving a message sent with [llEmail](/functions/llEmail/) it helps to separate the message from the prefixed header. The header and original message body are separated by `"\n\n"`

```lsl
integer divide = llSubStringIndex(message, "\n\n");
string header = llDeleteSubString(message, divide, -1);
message = llDeleteSubString(message, 0, divide + 1);
```

To get just one of the header items, do this:

```lsl
list lines = llParseStringKeepNulls(header, ["\n"], []);
string objname_line  = llList2String(lines, 0);
string region_line   = llList2String(lines, 1);
string localpos_line = llList2String(lines, 2);
```

To get a pure region name, do this:

```lsl
string region_name = llStringTrim(
            (string)llDeleteSubList(
                llParseStringKeepNulls(
                    llDeleteSubString(region_line, 0, 12),
                    [],
                    ["("]
                ), -2, -1), STRING_TRIM);
```

This application uses email to have objects check with a central server to see if the owner has the latest version. In the objects:

```lsl
string version = "1"; //
string type = "lolcube";
default
{
    on_rez(integer start_param)
    {
        llEmail("5a634b27-f032-283f-2df2-55ead7724b23@lsl.secondlife.com",
            version,
            (string)llGetOwner() + "," + type);
    }
}
```

The server:

```lsl
default
{
    state_entry()
    {
        llSetTimerEvent(15.0);
    }

    timer()
    {
        llGetNextEmail("", "");
    }

    email(string time, string address, string version, string message, integer num_left)
    {
        if ((integer)version < 2)
        {
            list info = llCSV2List(llDeleteSubString(message, 0, llSubStringIndex(message, "\n\n") + 1));
            llGiveInventory(llList2Key(info, 0), llList2String(info, 1));
        }

        if (num_left)
            llGetNextEmail("","");
    }
}
```

[^wiki-5a8d27]: If the agent or object are *known* to be in the same region, then you can use [llRegionSayTo](/functions/llRegionSayTo/) instead.

## Tests

- [internal test](https://osiris.lindenlab.com/mediawiki/index.php/Email_Test)[internal test](https://osiris.lindenlab.com/mediawiki/index.php/Email_Test)

## Known issues

From the issue templates included by the wiki article:

- SVC-23 (bug): Region incoming email queue for objects becomes suspended
- SVC-391 (bug): llEmail and llHTTPRequest do not handle non-ASCII characters
- SVC-412 (bug): Include "Content-Type: text/plain; charset=UTF-8" header in the messages forwarded from second life.
- SCR-499 (bug): llEmails to objects not in the same region arrive without a body or do not arrive at all.
- BUG-229767 (bug): Object-to-object email sporadically fails

## See also

### Functions

- [llGetNextEmail](/functions/llGetNextEmail/)
- [llMessageLinked](/functions/llMessageLinked/)

### Events

- [email](/events/email/)
- [link message](/events/link_message/)

### Articles

- [IM to email](https://wiki.secondlife.com/wiki/IM_to_email)
- [Postcards](https://wiki.secondlife.com/wiki/Postcards)

---

*Source: [LlEmail](https://wiki.secondlife.com/wiki/LlEmail) on the Second Life Wiki. Content from the Second Life Wiki articles LlEmail (revision 1218199, 2025-04-23), Template:Issues/SVC-23 (revision 1175993, 2013-01-09), Template:Issues/SVC-391 (revision 293013, 2009-03-25), Template:Issues/SVC-412 (revision 293033, 2009-03-25), Template:Issues/SCR-499 (revision 1175991, 2013-01-09) and Template:Issues/BUG-229767 (revision 1209756, 2020-12-15), CC BY-SA 3.0.*

---

From lsl.dev: https://lsl.dev/functions/llEmail/
