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 usersDirect: Send to the users specified inRecipientPlayerIdsRecipientPlayerIds: List of recipientPlayerIdvalues that you must specify forDirect, 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 bodyAttachment: Mail with both a body and attached itemsAttachments: List of attached items that you pass only whenMailContentTypeisAttachment, 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
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
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.