Skip to content

Send mail

Call SendMailAsync() to send operational mail or reward mail. Before sending, prepare the recipients, content type, attached items, and expiration time, and save the MailId received in the response to use for retrieval and recall when needed.

1. Prepare the sending request values

The call parameters for sending mail consist of the recipients, the mail content, and the expiration policy. Decide these three things first before sending.

1.1. Set the recipients

Use RecipientScope to decide whether to send the mail to all users or only to specified users. For mail sent to specified users, put the list of recipient PlayerId values in RecipientPlayerIds.

  • Broadcast: Send to all users
  • Direct: Send to the users specified in RecipientPlayerIds
  • RecipientPlayerIds: List of recipient PlayerId values that you must specify for Direct, up to 100

PlayerId is the user identifier issued after you create a user login account.

Because mailbox methods are called with a logged-in user's session, you cannot specify Broadcast. If you send a request with Broadcast, the sending result is returned as BroadcastMailNotAllowedForUser, so specify the recipients with Direct and send the mail.

1.2. Compose the mail content and attached items

MailContentType is a value that distinguishes whether the mail has only a body or also has attached items. For mail with attached items, also fill in Attachments and put the attached item type, reference ID, and quantity in each item.

  • Text: Mail with only a body
  • Attachment: Mail with both a body and attached items
  • Attachments: List of attached items that you pass only when MailContentType is Attachment, up to 10

The app must implement validating whether the attached items are valid, as well as granting, claiming, and using up the attached items within the app.

Along with the title Title and the body Body, you must also pass SenderDisplayName. SenderDisplayName is the sender name the user sees on the mail screen, and the value at the time of sending is saved as is. Therefore, even if you change the sender name later, the change is not reflected in mail that has already been sent.

1.3. Organize the expiration time and mail operating policy

ExpiresAt is the mail expiration time in UTC. You cannot set a time more than 30 days from the current UTC time. Organize Language, MailCategory, and MailExtension according to your app's policy and pass them together.

2. Send mail

Method

SendMailAsync

Call SendMailAsync() to request mail sending. When the request is accepted, an asynchronous acceptance response equivalent to 202 Accepted is returned. Use the MailId in the response data for Get sent mail and Recall mail when needed.

Note

When the mail is created successfully, the sending request is considered accepted. If you need logic that validates recipient PlayerId values or prevents attached items from being granted twice, we recommend validating on the app server first before you send the mail.

Duplicate sending prevention (idempotency)

When sending mail, the Hive Axyl SDK automatically generates and sends an idempotency key (Idempotency-Key) that identifies the request. A new automatically generated key is created for each SendMailAsync() call, and the same key is kept only when the SDK internally retries the transmission because of a network error.

If a request with the same idempotency key and the same request content arrives again within 60 minutes, the mailbox server treats it as a duplicate request and delivers only the mail sent first to the recipients. The idempotency key is valid for 60 minutes.

Therefore, if the app calls SendMailAsync() twice, the keys differ even if the request content is the same, so each call is sent as separate mail. To prevent your retry logic from sending the same mail twice, specify the same key that the app generates itself in IdempotencyKey of ApiCallContext, the per-call settings object, when you make the call.

Call parameters

Field name Type Required Description
request SendMailRequest Required Mail sending request
context ApiCallContext? Optional Per-call settings object. If omitted, the default values are used.

SendMailRequest

Field name Type Required Description
SenderDisplayName string Required Sender name to show on the mail screen, up to 100 characters. The value at the time of sending is saved, so changing the name later is not reflected in mail that has already been sent
RecipientScope SendMailRequestRecipientScope Required Recipient scope. Broadcast or Direct. There is no default value, so you must specify it
RecipientPlayerIds IReadOnlyList<long>? Optional List of recipient PlayerId values, up to 100. You must specify it for Direct
MailContentType SendMailRequestMailContentType Required Content type. Text or Attachment. There is no default value, so you must specify it
Title string Required Mail title, up to 300 characters
Body string Required Mail body, up to 1000 characters
Language LanguageCode Required Mail language, such as Ko or En. There is no default value, so you must specify it
ExpiresAt DateTimeOffset Required Mail expiration time in UTC. You can set only a time within 30 days from the current UTC time
MailCategory string Optional Mailbox category. Default "DEFAULT", up to 64 characters
Attachments IReadOnlyList<AttachmentItem>? Optional List of attached items. Used only for Attachment. Up to 10
MailExtension string? Optional Policy string defined by the app. Used to store app policy information such as mail display conditions or claim conditions. The server does not interpret this value and stores it as is. Up to 4096 characters

AttachmentItem

Field name Type Required Description
AttachmentType string Optional Attached item type. Default "DEFAULT", up to 30 characters
ReferenceId string Required Attached item reference ID, up to 100 characters
Quantity int Required Quantity to grant

Call example

See the example below and the response status for the success result of MailboxSendMailResult and the domain-specific results (Outcome) of this method. For the result model and handling principles of common failures (Failure) returned when the request cannot be performed, see Common error handling.

using Hive.Axyl.Mailbox;
using Hive.Axyl.Core;

IMailboxService mailbox = HiveCore.Resolve<IMailboxService>();

var request = new SendMailRequest {
    SenderDisplayName   = "운영팀",
    RecipientScope      = SendMailRequestRecipientScope.Direct,
    RecipientPlayerIds  = new long[] { 12345, 67890 },
    MailContentType     = SendMailRequestMailContentType.Attachment,
    Title               = "보상 우편",
    Body                = "랭킹 보상을 보내드립니다.",
    Language            = LanguageCode.Ko,
    MailExtension       = "claimCondition=season_rank",
    ExpiresAt           = System.DateTimeOffset.UtcNow.AddDays(7),
    Attachments = new[] {
        new AttachmentItem {
            AttachmentType = "ITEM",
            ReferenceId    = "potion_100",
            Quantity       = 5,
        },
    },
};

MailboxSendMailResult result = await mailbox.SendMailAsync(request);

switch (result)
{
    case MailboxSendMailResult.Success success:
        string? mailId = success.Data.MailId;
        break;

    case MailboxSendMailResult.BroadcastMailNotAllowedForUser:
        // Request not allowed by the mail sending policy (broadcast_mail_not_allowed_for_user)
        Debug.LogWarning("Mail to all users cannot be sent with a login session.");
        break;

    case MailboxSendMailResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
        break;

    default:
        Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
        break;
}

Response data

On success, the result is contained in Data (AcceptedResponseData) of MailboxSendMailResult.Success. Data.MailId is the key identifier you use for retrieval and recall when needed.

Both fields are declared with types that can hold null, so check whether a value is null before you show it on the screen or pass it to the next call.

Field name Type Required Description
Data.MailId string? Optional Sent mail identifier
Data.AcceptedAt DateTimeOffset? Optional Time when the sending request was accepted
Warning

You must save Data.MailId because it is used for Get sent mail and Recall mail. Keep it in secure storage and be careful not to expose it externally.

Response example

// success.Data (AcceptedResponseData)
string? mailId = success.Data.MailId;                       // Example: "0196f7c3-8b2e-7f4d-a123-9c8d7e6f5a4b"
DateTimeOffset? acceptedAt = success.Data.AcceptedAt;       // Example: 2026-06-10T03:21:45Z

Response status

The returned object MailboxSendMailResult branches into one of the cases below. We recommend handling it with a switch statement.

Response case Description App client handling
Success The sending request was accepted. Data.MailId and Data.AcceptedAt are returned. Success is returned even when the request is determined to be a duplicate. Save MailId and use it for status retrieval or recall when needed. If you count the number of mail items sent, filter out duplicates based on MailId.
BroadcastMailNotAllowedForUser You cannot send mail to all users with a login session. The server error code is broadcast_mail_not_allowed_for_user. Change RecipientScope to Direct, specify the recipients in RecipientPlayerIds, and send again
Failure Common Failure. See Common error handling. Handle according to the common error handling criteria
UnknownOutcome A new result that this SDK version does not recognize. Treat it as a failure and record the result code

Next steps

To check the status of sent mail again or if you need to recall it, see Get sent mail and Recall mail.

To check the status right after sending, use single-item detail retrieval with the saved MailId, and additionally use list retrieval only when you view multiple sending records together.

Learn more